Open main menu

CDOT Wiki β

Changes

Console UI Core Classes - OOP344 20113

26,176 bytes added, 06:31, 21 March 2012
CText Tester Crash
Tuesday Oct <del>26</del> 30th. 23:59
===Tester===
*[svn://zenit.senecac.on.ca/oop344/trunk/cioTesters/Test2DialogAndLabel.cpp Test2DialogAndLabel.cpp ]*on matrix, with putty (Terminal/keyboard: Xterm R6)*: on OSX, you can emulate XTerm keyboard settings using [http://iterm.sourceforge.net/ iTerm]/[http://www.iterm2.com/#/section/home ITerm 2]*: ~fardad.soleimanloo/t2 runs the demo for the test====Makefile for test 2 on matrix====*create a file in the root of cio call it '''"makefile"''' and copy the content below:*: make sure the lines starting with c++ are tabbed once.*: then at command line issue the command '''"make"''' to complie; the name of the executable will be '''prjexe'''<big><pre>t2: console.o cframe.o cfield.o cdialog.o clabel.o Test2DialogAndLabel.o c++ console.o cframe.o cfield.o cdialog.o clabel.o \Test2DialogAndLabel.o -lncurses -oprjexe console.o: console.cpp console.h keys.h c++ -c console.cpp cframe.o: cframe.cpp cframe.h cuigh.h console.h keys.h c++ -c cframe.cpp cfield.o: cfield.cpp cfield.h cuigh.h cframe.h console.h keys.h c++ -c cfield.cpp cdialog.o: cdialog.cpp cdialog.h cfield.h cuigh.h cframe.h console.h keys.h c++ -c cdialog.cpp clabel.o: clabel.cpp clabel.h cfield.h cframe.h cuigh.h console.h keys.h c++ -c clabel.cpp Test2DialogAndLabel.o: Test2DialogAndLabel.cpp clabel.h cdialog.h cframe.h cuigh.h cfield.h console.h keys.h c++ -c Test2DialogAndLabel.cpp</pre></big> 
==R0.3==
# CLineEdit
===Due Date===
*<del>Friday Nov 18th 23:59</del>Sunday Nov 20th 15:00
===Testers===
# [svn://zenit.senecac.on.ca/oop344/trunk/cioTesters/Test6Check.cpp Test6Check.cpp]
# [svn://zenit.senecac.on.ca/oop344/trunk/cioTesters/Test7MenuItem.cpp Test7MenuItem.cpp]
* to run the demos on matrix, with putty (Terminal/keyboard: Xterm R6)
*:On Terminal Window type:
*: $ ~fardad.soleimanloo/tX <ENTER> where X is the number of the test
 
==R0.6==
* CText
* CCheckList
* CMenu
===To Do===
# Before starting CText:
#: Modify '''Console::edit(char *str....)''' and add two argument to the argument list; ''IsTextEditor'', ''ReadOnly'':
#: ''int Console::edit(char *str, int row, int col, int fieldLength, int maxStrLength, bool* insertMode, int* strOffset, int* curPosition,'' '''bool IsTextEditor = false, bool ReadOnly = false''''')''
#:* '''IsTextEditor''': If IsTextEditor is true, then if offset is modified, stop editing and terminate the function returning the last key entered by the user. The easiest way to accomplish this, is as follows:
#:*# Save the value of the '''offset''' in a local variable at the very beginning of the main processing loop in the '''edit()''' function.
#:*# At the very end of the processing loop, If '''IsTextEditor''' is true, then compare the saved value with the value of offset. If the values are different, then set the termination flag (done) to true.
#:* Also if '''IsTextEditor''' is true, '''ESCAPE''' should no longer undo the changes in the line. (since in this case, it is responsibility of the Text editor (CText) to undo the changes.
# Before starting CCheckList:
#: Add the following methods to the CCheckMark class
#:* bool radio();
#:* void radio(bool isRadio);
#:* operator bool();
#:* operator char*();
#:* bool operator=(bool flag);
#:: (see [[#CCheckMark|CCheckMark]] description)
# Divide and assign tasks.
# Branch and Create Mock-ups for the classes
# Start coding.
 
===Due Dates===
* Tuesday Dec, 6, 2011
 
===Testers===
*[svn://zenit.senecac.on.ca/oop344/trunk/cioTesters/Test8Text.cpp Test8Text.cpp]
*[svn://zenit.senecac.on.ca/oop344/trunk/cioTesters/Test9CCheckList.cpp Test9CCheckList.cpp]
*[svn://zenit.senecac.on.ca/oop344/trunk/cioTesters/Test10Menu.cpp Test10Menu.cpp]
 
==Project makefiles==
*create a file in the root of cio call it '''"makefile"''' and copy the makefile of your test from "[svn://zenit.senecac.on.ca/oop344/trunk/cio_makefile cio makefiles]" into it.
*: make sure the lines starting with c++ are tabbed once.
*: then at command line issue the command '''"make"''' to complie;
*: the name of the executable will bt tX, where X is the number of the test.
* Again: here are the project [svn://zenit.senecac.on.ca/oop344/trunk/cio_makefile makefiles] for Linux
== POST YOUR PROBLEM HERE==
#Problem with tester: http://ryandang-cpa.blogspot.com/2011/10/problem-with-tester.html(resolved)#Problem with CCheckMark tester: http://hak9.com/2011/11/problem-with-ccheckmark-tester-file-c-oop344-project/ (resolved)
=CUI General Header file (cuigh.h)=
class CLabel : public CField{
// int _length; Use void CFrame::width(int) to store length, and int CFrame::width() to retrieve the length
 
public:
CLabel(const CLabel& L);
public:
CLabel(const char *Str, int Row, int Col,
int Len = 0);
void set(const void* str);
</syntaxhighlight></big>
<del>if _length is greater than zero, it will copy the string pointed by str into the string pointed by _data upto _length characters.if _length is zero,</del><br /> It will delete the memory pointed by _data and reallocates enough memory for str and copies the string pointed by str into the newly allocated memory pointed by _data.
==CDialog==
Organizes CField objects on the screen, displays them and then lets the user edit them one by one.
<span style="color:#FF0000"><b>iolgh.h doesnt exist. I think he meant cuigh.h. iolgh.h is the old name they used from previous semester.</b></span>
<big><syntaxhighlight lang="cpp">
#pragma once#include "iolghcuigh.h"
#include "cframe.h"
namespace cio{ class CField; class CDialog: public CFrame{ private: int _fnum; int _curidx; CField* _fld[C_MAX_NO_FIELDS]; bool _dyn[C_MAX_NO_FIELDS]; bool _editable; public: CDialog(CFrame *Container = (CFrame*)0, int Row = -1, int Col = -1, int Width = -1, int Height = -1, bool Borderd = false, const char* Border=C_BORDER_CHARS); virtual ~CDialog(); void draw(int fn = C_FULL_FRAME); int edit(int fn = C_FULL_FRAME); int add(CField* field, bool dynamic = true); int add(CField& field, bool dynamic = false); CDialog& operator<<(CField* field); CDialog& operator<<(CField& field);  bool editable(); int fieldNum()const; int curIndex()const;
bool editable(); int fieldNum()const; int curIndex()const; CField& operator[](unsigned int index); CField& curField(); };}
</syntaxhighlight></big>
===Attributes===
'''ClineEdit''' encapsulates the console.edit() function of Console class.
<big><syntaxhighlight lang="cpp">
#pragma once
#include "cfield.h"
namespace cio{
class CLineEdit: public CField{
bool _dyn;
int _maxdatalen;
bool* _insertmode;
int _curpos;
int _offset;
public:
CLineEdit(char* Str, int Row, int Col, int Width,
int Maxdatalen, bool* Insertmode,
bool Bordered = false,
const char* Border=C_BORDER_CHARS);
CLineEdit(int Row, int Col, int Width,
int Maxdatalen, bool* Insertmode,
bool Bordered = false,
const char* Border=C_BORDER_CHARS);
~CLineEdit();
void draw(int Refresh = C_FULL_FRAME);
int edit();
bool editable()const;
class CLineEdit: public CField{ bool _dyn; int _maxdatalen; bool* _insertmode; int _curpos; int _offset;public: CLineEdit(char* Str, int Row, int Col, int Width, int Maxdatalen, int* Insertmode, bool Bordered = false, const char* Border=C_BORDER_CHARS); CLineEdit(int Row, int Col, int Width, int Maxdatalen, int* Insertmode, bool Bordered = false, const char* Border=C_BORDER_CHARS); ~CLineEdit(); void draw(int Refresh = C_FULL_FRAME); int edit(); bool editable()const; void set(const void* Str); };}
</syntaxhighlight></big>
#pragma once
#include "cfield.h"
namespace cio{ class CButton: public CField{ public: CButton(const char *Str, int Row, int Col, bool Bordered = true, const char* Border=C_BORDER_CHARS); virtual ~CButton(); void draw(int fn=C_FULL_FRAME); int edit(); bool editable()const; void set(const void* str); };
public:
CButton(const char *Str, int Row, int Col,
bool Bordered = true,
const char* Border=C_BORDER_CHARS);
virtual ~CButton();
void draw(int rn=C_FULL_FRAME);
int edit();
bool editable()const;
void set(const void* str);
};
}
</syntaxhighlight></big>
First draw() the Button, then surround it by squared brackets, place the cursor under the first character of Button's text and wait for user entry.<br />
When user hits a key, if the key is ENTER_KEY or SPACE, return C_BUTTON_HIT (defined in cuigh.h) otherwise return the entered key.<br />
 
<big><syntaxhighlight lang="cpp">
void set(const void* str);
</syntaxhighlight></big>
First deallocated what is pointed by Field's _data.
Then allocate new memory to the size of content of str and copy the content into it and make
Field's _data point to it.
 
<big><syntaxhighlight lang="cpp">
bool editable()const;
</syntaxhighlight></big>
Always returns true
 
==CValEdit==
<big><syntaxhighlight lang="cpp">
bool _radio;
char _format[4];
CLabel Label_Label;
public:
CCheckMark(bool Checked,const char* Format, const char* Text, int Row, int Col, int Width, bool IsRadio = false);
bool checked()const;
void checked(bool val);
bool radio(); // addition for R0.6
void radio(bool isRadio); // addition for R0.6
operator bool(); // addtion for R0.6
operator char*(); // addition for R0.6
bool operator=(bool flag);
};
}
 
</syntaxhighlight></big>
===Constructor / Destructor===
<big><syntaxhighlight lang="cpp">
CCheckCCheckMark(bool Checked,const char* Format, const char* Text, int Row, int Col, int Width, bool IsRadio = false);
</syntaxhighlight></big>
*Passes the ''Row, Col, Width and "1"'' to ''row, col, width and height'' arguments of CField and directly initializes _Label with ''Text, 0, 4, and (Width-4)'' for ''Str, Row, Col and Len'', arguments of CLabel's Constructor.<br />
*Sets the frame of _Label to itselfits owner (Checkmark i.e. 'this');
*Sets _flag to Checked
*Sets _radio to IsRadio
<big><syntaxhighlight lang="cpp">
CCheckCCheckMark(const CCheckCCheckMark& C);
</syntaxhighlight></big>
*Passes incoming CCheck CCheckMark reference ("C") to CField's copy constructor, and directly initializes the _Label with the _Label of C*Sets all the attributes of this object to the attributes of incoming CCheck CCheckMark reference ("C")
*Sets _data to the address of _flag
</syntaxhighlight></big>
*These methods set and get _flag.
<big><syntaxhighlight lang="cpp">
bool radio(); // addition for R0.6
void radio(bool isRadio); // addition for R0.6
</syntaxhighlight></big>
* These to methods, get and set the '''_radio''' attribute.
<big><syntaxhighlight lang="cpp">
operator bool(); // addtion for R0.6
</syntaxhighlight></big>
* Overload the '''bool''' cast to return the value of '''_flag'''
<big><syntaxhighlight lang="cpp">
operator char*(); // addtion for R0.6
</syntaxhighlight></big>
* Overload the '''char*''' cast to return the value of '''_Label.data()'''
<big><syntaxhighlight lang="cpp">
bool operator=(bool flag);; // addtion for R0.6
</syntaxhighlight></big>
* Overload the operator= and set the _flag to flag
 
==CMenuItem==
CMenuItem provides a Label that is can be marked as selected by pressing the space bar.
bool selected()const;
void selected(bool val);
const char* Text()const;
};
}
#Passes CM to CFiled and Initializes the Label with CM
#Sets the _selected to _selected of CM
#Sets CFeilds::_data to the address of _formated_format
#Sets the Label's frame to this object.
Sets _selected to val
<big><syntaxhighlight lang="cpp">
const char* Text()const;
</syntaxhighlight></big>
Returns the text of Label
==CText==
CText is a CField to edit a multiline text.<br />
To do this, it will use the [svn://zenit.senecac.on.ca/oop344/trunk/textClass Text class] to convert a character string containing a text into a (simulated) two dimensional array.
<big><syntaxhighlight lang="cpp">
 
#pragma once
#include "cfield.h"
#include "text.h"
 
using namespace cio;
 
 
class CText:public CField{
Text _T;
bool _displayOnly;
int _curpos;
bool* _insertmode;
int _offset;
int _lcurpos;
int _loffset;
public:
CText(int Row, int Col, int Width, int Height, bool* Insertmode,
bool displayOnly = false, const char* Border=C_BORDER_CHARS);
CText(const char* Str, int Row, int Col, int Width, int Height,
bool* Insertmode, bool displayOnly = false,
const char* Border=C_BORDER_CHARS);
void draw(int fn = C_FULL_FRAME);
 
void set(const void *Str);
void *data()const;
 
int edit();
bool editable()const;
bool displayOnly();
void displayOnly(bool val);
};
 
 
</syntaxhighlight></big>
===Attributes===
<big><syntaxhighlight lang="cpp">
Text _T;
</syntaxhighlight></big>
An instance of the [svn://zenit.senecac.on.ca/oop344/trunk/textClass Text class]
<big><syntaxhighlight lang="cpp">
bool _displayOnly;
</syntaxhighlight></big>
If it is set to true, then the Text can only be viewed but not edited; All scrolling, page UP, DOWN, etc... is enabled but any attempt to change the text, is ignored quietly. This attribute is passed to ReadOnly argument of Console::edit(......).
<big><syntaxhighlight lang="cpp">
int _curpos;
bool* _insertmode;
int _offset;
</syntaxhighlight></big>
Values used by Console::edit(......)
<big><syntaxhighlight lang="cpp">
int _lcurpos;
int _loffset;
</syntaxhighlight></big>
Vertical cursor position in text.
Vertical offset of the text relative to the frame of CText. This value indicates, how many line are hidden above the frame when text is scrolled down.
 
===Constructors/Destructor===
<big><syntaxhighlight lang="cpp">
CText(int Row, int Col, int Width, int Height, bool* Insertmode,
bool displayOnly = false, const char* Border=C_BORDER_CHARS);
</syntaxhighlight></big>
Initialized the CField with the corresponding incoming arguments and then sets all the attributes to their corresponding arguments.
<big><syntaxhighlight lang="cpp">
CText(const char* Str, int Row, int Col, int Width, int Height,
bool* Insertmode, bool displayOnly = false,
const char* Border=C_BORDER_CHARS);
</syntaxhighlight></big>
Works exactly like the previous constructor but it also '''set()'''s the class to '''Str'''.
 
===Methods===
'''Under Construction'''
<big><syntaxhighlight lang="cpp">
void draw(int fn = C_FULL_FRAME);
</syntaxhighlight></big>
First it will draw the CField using the fn arguement.<br />
Then it will use console.display to display all the Lines of _T that are positioned inside the frame of the CText. (i.e. from _loffset to _loffset + Height() - 2).<br />
Two Important things to note:
# you should note that '''Lines''' are '''console.display()'''ed from _offset character. (i.e. &_T[theLineNumber][_offset]).
# Also you should '''console.display()''' the Lines only if the length of the line is more than the _offset(i.e. _T[theLineNumver].strlen() > _offset)
<big><syntaxhighlight lang="cpp">
void set(const void *Str);
</syntaxhighlight></big>
Sets the '''_T''' attribute to the incoming string.
<big><syntaxhighlight lang="cpp">
void *data()const;
</syntaxhighlight></big>
Exports the string out of _T and returns its address after casting it to '''void*'''.
<big><syntaxhighlight lang="cpp">
int edit();
</syntaxhighlight></big>
# Create local variables to hold the following attributes in case ESCAPE is hit to undo:
## _T
## _curpos
## _offset
## _lcurpos
## _loffset
# Create the usual '''while(!done)''' structure for interfacing with user
# '''draw()''' the text
# '''console.edit()''' the Line at where vertical cursor is after _loffset.
## use absRow() and _lcurpos to calculate the row on which the editing should happen
## use absCol() to calculate the column on which editing to happen.
## use width() to calculate the fieldLen for '''console.edit()'''
## use the '''size()''' of the current '''Line''' in '''_T''' to determine the maximum data length of the string to '''console.edit()'''
## the isTextEditor is always true
## the ReadOnly depends on the value of '''_displayOnly'''
<big><syntaxhighlight lang="cpp">
bool editable()const;
</syntaxhighlight></big>
Always return true;
<big><syntaxhighlight lang="cpp">
bool displayOnly();
void displayOnly(bool val);
</syntaxhighlight></big>
These methods Get and Set the '''_displayOnly''' attribute.
 
===The Text Helper Class===
[svn://zenit.senecac.on.ca/oop344/trunk/textClass Text class]
<!-- ===CText Tester Crash=== Incorrect, TD[0].data() allocates mem and copies the data into it using text::export string
<syntaxhighlight lang="cpp">
char* data = (char*)TD[0].data();
delete [] data;
</syntaxhighlight>
This fails because TD[0].data() refers to CField::data() and NOT CText::data() like it should.
Here are some possible fixes that I think Fardad meant to use:
<syntaxhighlight lang="cpp">
char* data = (char*)((CText&)(TD[0])).data();
OR
char* data = (char*)txt.data();
</syntaxhighlight>
Note, this does NOT crash on Matrix, only Windows and Visual Studio.
-->
 
==CCheckList==
<big><syntaxhighlight lang="cpp">
#pragma once
#include "cfield.h"
#include "ccheckmark.h"
namespace cio{
 
class CCheckList : public CField{
CCheckMark* _checkmarks[32];
bool _radio;
char _format[4];
unsigned int _cnt;
unsigned int _flags;
unsigned int _cur;
public:
CCheckList(const char* Format, int Row, int Col, int Width,bool radio, bool Bordered = true,const char* Border=C_BORDER_CHARS);
~CCheckList(void);
CCheckList& add(const char* Text, bool selected = false);
CCheckList& operator<<(const char* Text);
void draw(int fn = C_FULL_FRAME);
int edit();
void* data();
void set(const void* data);
CCheckMark& operator[](unsigned int index);
bool editable()const;
bool radio()const;
void radio(bool val);
unsigned int flags()const;
void flags(unsigned int theFlags);
int selectedIndex()const;
void selectedIndex(int index);
unsigned int length();
};
}
</syntaxhighlight></big>
===Attributes===
<big><syntaxhighlight lang="cpp">
CCheckMark* _checkmarks[32];
</syntaxhighlight></big>
An array of 32 CCheckmark pointers that will piont to _cnt dynamically allocated CCheckMarks.
<big><syntaxhighlight lang="cpp">
bool _radio;
</syntaxhighlight></big>
Holds the behaviour of the CCheckList to be like a Radio Button List or Check Mark List
<big><syntaxhighlight lang="cpp">
char _format[4];
</syntaxhighlight></big>
Holds the format with which a check mark is displayed (i.e. "[X]" or "(o)" etc...)
<big><syntaxhighlight lang="cpp">
unsigned int _cnt;
</syntaxhighlight></big>
Holds the number of CCheckMarks currently in CCheckList
<big><syntaxhighlight lang="cpp">
unsigned int _flags;
</syntaxhighlight></big>
Always holds the bit pattern corresponding to the status of the CCheckMarks in the List. Note that bit 0 (right most) will correspond to the first CCheckMark.
<big><syntaxhighlight lang="cpp">
unsigned int _cur;
</syntaxhighlight></big>
Holds the index of the CCheckMark in the "_checkmarks" array which is currently being edited. (focused)
 
===Constructors/Destructor===
<big><syntaxhighlight lang="cpp">
CCheckList(const char* Format, int Row, int Col, int Width,bool radio, bool Bordered = true,const char* Border=C_BORDER_CHARS);
</syntaxhighlight></big>
Passes corresponding values to the Base class (CField) then
#sets the _data attribute to the address of _flags
#copies '''Format''' and '''radio''' into '''_format''' and '''_radio''' respectively
#sets '''_cnt, _cur''' and '''_flags''' to zero
<big><syntaxhighlight lang="cpp">
~CCheckList(void);
</syntaxhighlight></big>
Goes through '''_checkmarks''' up to '''_cnt''' and if deletes them one by one.
 
===Methods===
<big><syntaxhighlight lang="cpp">
CCheckList& add(const char* Text, bool selected = false);
</syntaxhighlight></big>
* Only adds a new CCheckMark if '''_cnt''' does not exceed the maximum amount of '''_checkmarks''' (32)
* Creates a new CCheckMark with the row being '''_cnt'''+1, the height being 1 and the length being the length of '''Text'''+4
* Sets the newly created CCheckMarks' frame to '''this'''
* Automatically expands the width of the CCheckList if the width of the newly created CCheckMark is bigger than the current width of the CCheckList
* Sets the height of the CCheckList to '''_cnt'''+3
* Updates the bit pattern of '''_flags'''
* Increments '''_cnt'''
<big><syntaxhighlight lang="cpp">
CCheckList& operator<<(const char* Text);
</syntaxhighlight></big>
returns add(Text).
<big><syntaxhighlight lang="cpp">
void draw(int fn = C_FULL_FRAME);
</syntaxhighlight></big>
Draws the frame and then draws all the '''_checkmarks''', making sure the cursor is standing under the first checked checkmark.
<big><syntaxhighlight lang="cpp">
int edit();
</syntaxhighlight></big>
*Draws the '''CCheckList''' then starts the editing the '''_checkmarks''' form '''_cur''' and according to the return key of CCheckMark::edit():
**If Down or Right key is hit it goes to the next '''_checkmark''', if '''_cur''' is the last one, then it exits the edit, returning the last key entered.
**UP and Left key works in opposite direction of Down and Right, if '''_cur''' is already zero, then it exits the edit, returning the last key entered.
**If Space is hit, then if '''_radio''' is true, it will uncheck all the '''_checkmarks''' other than the '''_cur'''rent one.
<big><syntaxhighlight lang="cpp">
void* data();
</syntaxhighlight></big>
returns the bit pattern held in _flags. <br />
''make sure _flags are updated to the status of the '''_checkmarks'''''
<big><syntaxhighlight lang="cpp">
void set(const void* data);
</syntaxhighlight></big>
sets the '''_flags''' and updates the '''_checkmarks''' to the bitpattern of '''_flags'''
<big><syntaxhighlight lang="cpp">
CCheckMark& operator[](unsigned int index);
</syntaxhighlight></big>
returns the CCheckMark corresponding the '''index''' value.
<big><syntaxhighlight lang="cpp">
bool editable()const;
</syntaxhighlight></big>
always returns true;
<big><syntaxhighlight lang="cpp">
bool radio()const;
</syntaxhighlight></big>
returns '''_radio'''
<big><syntaxhighlight lang="cpp">
void radio(bool val);
</syntaxhighlight></big>
sets the _radio and updates all _checkMarks radio value.
<big><syntaxhighlight lang="cpp">
unsigned int flags()const;
</syntaxhighlight></big>
returns the '''_flags''' attribute
<big><syntaxhighlight lang="cpp">
void flags(unsigned int theFlags);
</syntaxhighlight></big>
sets the '''_flags''' attribute
<big><syntaxhighlight lang="cpp">
int selectedIndex()const;
</syntaxhighlight></big>
returns the index of the first CCheckMark that is selected, and -1 if nothing is selected.
<big><syntaxhighlight lang="cpp">
void selectedIndex(int index);
</syntaxhighlight></big>
sets the selectedindex. (only un-selects the rest if object is in radio mode)<br />
if index is less than zero, then it will un-selects all
<big><syntaxhighlight lang="cpp">
unsigned int length();
</syntaxhighlight></big>
returns '''_cnt'''
 
==CMenu and MNode==
CMenu is a linked list of MNodes. Providing menu selection for the user in two formats; Drop Down List, or a simple menu.
 
<big><syntaxhighlight lang="cpp">
#ifndef __CIO__CMENU_H__
#define __CIO__CMENU_H__
#include "cuigh.h"
#include "cfield.h"
#include "cmenuitem.h"
#include "cbutton.h"
namespace cio{
class Cmenu;
 
class MNode{
CMenuItem* _item;
MNode* _next;
MNode* _prev;
unsigned int _index;
MNode(CMenuItem* item,unsigned int index, MNode* prev, MNode* next = ((MNode*)0));
~MNode(void);
friend class CMenu;
};
 
class CMenu : public CField{
MNode* _first;
MNode* _head;
MNode* _tail;
MNode* _cur;
char _format[3];
unsigned int _cnt;
int _selectedIndex;
bool _dropdown;
bool _dropped;
bool goNext();
bool goPrev();
CButton _Title;
public:
static const bool Select;
CMenu(const char* Title, const char* Format, int Row, int Col,
int Width, int Height,bool dropdown,
const char* Border=C_BORDER_CHARS);
CMenu& add(const char* Text, bool selected = false);
CMenu& operator<<(const char* Text);
CMenu& operator<<(bool select);
void draw(int fn = C_FULL_FRAME);
int edit();
void set(const void* data);
int selectedIndex() const;
int selectedIndex(int index);
const char* selectedText();
bool editable()const;
~CMenu(void);
};
extern const bool Select;
}
 
#endif
</syntaxhighlight></big>
===MNode===
MNode holds to main about an Item in the menut:
# The CMenuItem object
# The index of this Item
MNode is a fully private class and is only accessible by CMenu.
====Attributes====
<big><syntaxhighlight lang="cpp">
CMenuItem* _item;
</syntaxhighlight></big>
Holds the address of a dynamically allocated CMenuItem
<big><syntaxhighlight lang="cpp">
unsigned int _index;
</syntaxhighlight></big>
Holds the index (sequence -1) number of the '''CMenuItem''' in the '''CMenu'''.
<big><syntaxhighlight lang="cpp">
MNode* _next;
MNode* _prev;
</syntaxhighlight></big>
Standard next and previous pointer for a linked list node.
 
====Constructor/Destructor====
<big><syntaxhighlight lang="cpp">
MNode(CMenuItem* item,unsigned int index, MNode* prev, MNode* next = ((MNode*)0));
</syntaxhighlight></big>
Sets the corresponding attributes to the values of the arguments.
<big><syntaxhighlight lang="cpp">
~MNode(void);
</syntaxhighlight></big>
deletes the '''_item'''
 
===CMenu===
CMenu is a linked list of MNodes and also contains a CButton for a Title (only used on if in '''_dropdown''' mode). <br />
Assuming that a CMenu is created with a title as "FILE" and menu-items as "Save, Load, Print, Quit":
*When in '''_dropdown''' mode:
When drawing, Only the _Title(CButton) is drawn (and not the menu itself)
<big><pre>
FILE
</pre></big>
When edited (in '''_dropdown''' mode) the CButton gets activated and if it is hit, then the Menu will be dropped down (drawn) under the CButton and user can browse through the options and select one of them. selecting the option in this case will close the menu and CButton gets activated again:<br />
when active, CMenu looks like this:
<big><pre>
[FILE]
</pre></big>
User hits enter: (since nothing is selected all menu items are unselected)
<big><pre>
FILE
/-------\
| Save |
| Load |
| Print |
| Quit |
\-------/
</pre></big>
Now the cursor is standing under '''S'''ave.
User hits down arrow twice to select '''P'''rint and then hits Space:
<big><pre>
[FILE]
</pre></big>
The Print is selected and The menu is closed and FILE is active again.
If the user hits Enter again:
<big><pre>
FILE
/-------\
| Save |
| Load |
|[Print]|
| Quit |
\-------/
</pre></big>
We will see the Print is selected and the cursor in under P.
If user hits Enter instead of space, the selection wont change and whatever was selected before will remain the same:
<big><pre>
[FILE]
</pre></big>
User hits navigation keys and moves out of the CMenu Field.
''Note that if '''left''' or '''right''' navigation keys are hit when the title is active, then they are translated to '''up''' or '''down''' respectively.
*When NOT in '''_dropdown''' mode:
*:The CButton will not be displayed at all, and when user starts to edit, he enters the menu browsing the items and if he gets to the end of the menu, the control goes to the next field in the dialog. If user goes up and passes the first them, then the control will go to the previous field in the dalog.
<big><pre>
/-------\
| Save |
| Load |
|[Print]|
| Quit |
\-------/
</pre></big>
''Note that if the number of menu items are more than the space provided by the CField's frame, then the menu items should scroll up and down to accommodate the selection''
====Attributes====
<big><syntaxhighlight lang = "cpp">
MNode* _first;
</syntaxhighlight></big>
points to the first CMenuItem visible on the menu.
<big><syntaxhighlight lang = "cpp">
MNode* _head;
MNode* _tail;
MNode* _cur;
</syntaxhighlight></big>
standard Link list pointers
<big><syntaxhighlight lang = "cpp">
char _format[3];
</syntaxhighlight></big>
The two characters used to surround the selected menu item
<big><syntaxhighlight lang = "cpp">
unsigned int _cnt;
</syntaxhighlight></big>
The number of CMenuItems in CMenu
<big><syntaxhighlight lang = "cpp">
int _selectedIndex;
</syntaxhighlight></big>
The index of the selected CMenuItem (saved in MNode::index), if there is no selected menu, then this value is -1.
<big><syntaxhighlight lang = "cpp">
bool _dropdown;
</syntaxhighlight></big>
True if the Menu is a Drop Down Menu.
<big><syntaxhighlight lang = "cpp">
bool _dropped;
</syntaxhighlight></big>
Flag used to hold the status of a Drop Down Menu, (_dropped or not)
<big><syntaxhighlight lang = "cpp">
bool goNext();
bool goPrev();
</syntaxhighlight></big>
standard gonext() and goprev() in linked lists
<big><syntaxhighlight lang = "cpp">
CButton _Title;
</syntaxhighlight></big>
CButton holding the Title of this menu
====Constructor/Destructor====
<big><syntaxhighlight lang = "cpp">
CMenu(const char* Title, const char* Format, int Row, int Col,
int Width, int Height,bool dropdown,
const char* Border=C_BORDER_CHARS);
</syntaxhighlight></big>
#Initializes CField as follows:
#* Row: Passes Row, if this menu is not a dropdown, otherwise it will pass Row+1.
#* Col, Width, Height are passed directly
#* Data: a void null pointer is passed for data
#* Bordered: since CMenu is always bordered, true is passed here
#* Border is directly passed.
#Initializes _Title (the CButton) as follows:
#* Str, Title is passed here
#* Row, -1
#* Col, 1
#* Bordered, since the title of the dorpdown is alway NOT bordered, then false is passed here.
#Constructor Settings:
#* Link list attributes are set as standard linked list contructor
#* Format is copied into _format
#* _cnt is set to zero
#* _selectedIndex is set to -1
#* _data is set to address of _selectedIndex
#* _dropdown is set to dropdown
#* _dropped is set to false
#* _Title's frame is set to the CMenu object (this)
<big><syntaxhighlight lang = "cpp">
~CMenu();
</syntaxhighlight></big>
Standard Linked list destructor
 
====Methods====
<big><syntaxhighlight lang = "cpp">
CMenu& add(const char* Text, bool selected = false);
</syntaxhighlight></big>
Standard append for a linked list:
#creates an MNode with
#* a new CMenutItem with
#*:selected, _format, Text for first three arguments
#*:1, 1, and (width of the menu) -2, for Row col and width
#* the rest are what is needed for a standard append procedure for a linked list
#appends the new MNode to the end of the list
#if the new added CMenuItem is selected, it will update the selected index
'''''Note that if the added CMenuItem is the first CMenuItem in the list, then the _first pointer should be pointing to it'''''
<big><syntaxhighlight lang = "cpp">
CMenu& operator<<(const char* Text);
</syntaxhighlight></big>
returns add(Text)
<big><syntaxhighlight lang = "cpp">
CMenu& operator<<(bool select);
</syntaxhighlight></big>
if select is true, it will select the last CMenuItem added to the CMenu
<big><syntaxhighlight lang = "cpp">
void draw(int fn = C_FULL_FRAME);
</syntaxhighlight></big>
#if this is a '''_dropdown''', then it will draw the _Title
#: and then if '''_dropped''' is true, it will draw the CField and then draw the CMenuItems starting form what _first is pointing to, up to (CField's hieght -2) times.
#if this not a '''_dropdown''' then the _Title will never be drawn and the CMenuItems should be drawn as above.
<big><syntaxhighlight lang = "cpp">
int edit();
</syntaxhighlight></big>
Edits the menu the way it is explains in [[#CMenu|CMenu]] description.<br />
If it is too confusing, this [[CMenu pseudo code - OOP344 20113|pseudo code]] may help.
<big><syntaxhighlight lang = "cpp">
void set(const void* data);
</syntaxhighlight></big>
Sets the selected index to the integer pointed by data;
<big><syntaxhighlight lang = "cpp">
int selectedIndex() const;
</syntaxhighlight></big>
returns the selected index or -1 if nothing is selected
<big><syntaxhighlight lang = "cpp">
int selectedIndex(int index);
</syntaxhighlight></big>
sets the selected index.
<big><syntaxhighlight lang = "cpp">
const char* selectedText();
</syntaxhighlight></big>
returns the text of the selected menu, if nothing is selected, and empty string is returned.
<big><syntaxhighlight lang = "cpp">
bool editable()const;
</syntaxhighlight></big>
returns true if '''_cnt''' is greater than zero