Difference between revisions of "Console Framework Classes 20103 - OOP344"
m (Reverted edits by MCanaday49 (Talk) to last revision by Ldchen1) |
|||
(93 intermediate revisions by 11 users not shown) | |||
Line 1: | Line 1: | ||
+ | {{OOP344 Index | 20103}} | ||
=The Frame work= | =The Frame work= | ||
− | + | under construction!!!! | |
+ | |||
+ | Your objective at this stage is to create a framework of classes designed to interact with the user. This user interface framework then can be used in development of any interactive application. | ||
+ | |||
+ | please note that the class definitions here are minimum requirement for the framework and you are free to add any enhancements or features you find useful. Obviously it would be wise the discuss these enhancements with your professor to make sure they are feasible. | ||
+ | |||
+ | |||
+ | Depending on the section you are in, you may have different scope in number of the classes you create. please double check your professor's notes on the project before you begin. | ||
+ | |||
+ | |||
+ | It is highly recommended to develop the classes in the order they are stated here. At each stage a tester program is provided to help you test your development. Executables of the test programs are available on matrix to show you how it is supposed to run. | ||
+ | |||
+ | |||
+ | Start by creating mock-up classes (class declaration and definition with empty methods that only compiles and don't do anything) | ||
+ | Each class MUST have its own header file to hold its declaration and "cpp" file to hold its implementation. To make sure you do not do circular includes follow these simple guidelines: | ||
+ | * Add recompilation safeguards to all your header files. | ||
+ | * Always use forward declaration if possible instead of including a class. | ||
+ | * Use includes only in files in which the actual header file code is used. avoid "just in case" includes. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | = General Internal Header file = | ||
+ | The general header file holds the common setting and definition between all classes in the frame work. | ||
<big><syntaxhighlight lang="cpp"> | <big><syntaxhighlight lang="cpp"> | ||
#ifndef ___CONFW_H__ | #ifndef ___CONFW_H__ | ||
Line 11: | Line 35: | ||
#define _CRT_SECURE_NO_WARNINGS | #define _CRT_SECURE_NO_WARNINGS | ||
#endif | #endif | ||
− | + | #include <string.h> | |
extern "C"{ | extern "C"{ | ||
#include "iol.h" | #include "iol.h" | ||
− | }; | + | }; |
+ | |||
+ | #define FW_BORDER_CHARS "/-\\|/-\\|" | ||
+ | |||
+ | #define FW_MAX_NO_FIELDS 100 | ||
+ | #define FW_BUTTON_HIT 1 | ||
+ | #define FW_MAX_LINE_CHARS (1024u) | ||
+ | |||
+ | #define FW_REFRESH -2 | ||
+ | #define FW_FULL_FRAME -1 | ||
+ | #define FW_NO_REFRESH 0 | ||
+ | |||
+ | |||
+ | enum MessageStatus{ClearMessage,SetMessage}; | ||
+ | |||
+ | |||
+ | #ifdef NO_HELPFUNC | ||
+ | # undef NO_HELPFUNC | ||
+ | #endif | ||
+ | #define NO_HELPFUNC ((void(*)(MessageStatus, FWDialog&))(0)) | ||
+ | #ifdef NO_VALDFUNC | ||
+ | # undef NO_VALDFUNC | ||
+ | #endif | ||
+ | #define NO_VALDFUNC ((bool(*)(const char*, FWDialog&))(0)) | ||
+ | |||
#endif | #endif | ||
</syntaxhighlight></big> | </syntaxhighlight></big> | ||
− | ==Classes== | + | =File Names= |
+ | Use the following rules to create filenames for your class. | ||
+ | *Each class MUST have its own header file and cpp file for implementation | ||
+ | *Use the class name for the name of the file but make sure it is all lowercase. | ||
+ | *:For example '''FWBorder''' class should have '''fwborder.h''' and '''fwborder.cpp''' files for its implemetation | ||
+ | |||
+ | =Classes= | ||
+ | These classes encapsulate all the functions written in IOL library in an Object Oriented method: | ||
+ | ==Hierarchy== | ||
+ | <big><pre> | ||
+ | FWBorder | ||
+ | | | ||
+ | |---FWDialog | ||
+ | | | ||
+ | | | ||
+ | |---FWField | ||
+ | | | ||
+ | |-------- FWLabel | ||
+ | | | | ||
+ | | |-------FWCheck | ||
+ | | |-------FWMenuItem (Maybe?) | ||
+ | | | ||
+ | |-------- FWButton | ||
+ | | | ||
+ | | | ||
+ | |-------- FWLineEdit | ||
+ | | | | ||
+ | | |-------FWValEdit | ||
+ | | | ||
+ | |-------- FWText | ||
+ | | | ||
+ | |-------- FWCheckList (Maybe?) | ||
+ | |-------- FWMenu (Maybe?) | ||
+ | </pre></big> | ||
+ | |||
+ | ==FWBorder== | ||
+ | FWBorder is the base of all IO entities in our framework. It encapsulate a window or a container in witch IO Fields are to be placed and run. | ||
+ | Also, It encapsulates a border, cordinates and size. | ||
− | === | + | ===Class Definition=== |
− | = | + | <big><syntaxhighlight lang="cpp"> |
− | + | class FWBorder { | |
int _row; | int _row; | ||
int _col; | int _col; | ||
int _height; | int _height; | ||
int _width; | int _width; | ||
+ | char _border[9]; | ||
+ | bool _visible; | ||
FWBorder* _container; | FWBorder* _container; | ||
− | bool | + | |
− | char _border[9]; | + | protected: |
+ | int absRow()const; | ||
+ | int absCol()const; | ||
+ | public: | ||
+ | FWBorder(int Row=-1, int Col=-1, int Width=-1,int Height=-1, | ||
+ | bool Visible = false, | ||
+ | const char* Border=FW_BORDER_CHARS, | ||
+ | FWBorder* Container = (FWBorder*)0); | ||
+ | |||
+ | virtual void draw(int refresh = FW_NO_REFRESH)const; | ||
+ | virtual ~FWBorder(); | ||
+ | |||
+ | void visible(bool val); | ||
+ | bool visible()const; | ||
+ | |||
+ | void container(FWBorder* theContainer); | ||
+ | FWBorder* container(); | ||
+ | |||
+ | bool fullscreen()const; | ||
+ | |||
+ | void row(int val); | ||
+ | int row()const; | ||
+ | |||
+ | void col(int val); | ||
+ | int col()const; | ||
+ | |||
+ | void size(int width, int height); | ||
+ | int height()const; | ||
+ | int width()const; | ||
+ | |||
+ | }; | ||
+ | |||
+ | </syntaxhighlight></big> | ||
+ | ====Properties==== | ||
+ | int _row, holds the relative coordinate of top row of this border with respect to its container.<br /> | ||
+ | int _col, same as _row, but for _col. <br /> | ||
+ | int _height, height of the entity. <br /> | ||
+ | int _width, width of the entity. <br /> | ||
+ | char _border[9], characters used to draw the border: <br /> | ||
+ | : _border[0], left top | ||
+ | : _border[1], top side | ||
+ | : _border[2], right top | ||
+ | : _border[3], right side | ||
+ | : _border[4], right bottom | ||
+ | : _border[5], bottom side | ||
+ | : _border[6], bottom left | ||
+ | : _border[7], left side | ||
+ | bool _visible; Indicates if the border surrounding the entity is to be drawn or not. <br /> | ||
+ | FWBorder* _container; holds the container (another FWBorder) which has opened this one (owner or container of the current FWBorder). '''_container''' will be NULL if this FWBorder does not have a container, in which case, it will be full screen and no matter what the values of row, col, width and height are, FWBorder will be '''Full Screen''' (no border will be drawn) | ||
+ | ====Methods==== | ||
+ | =====Protected===== | ||
+ | |||
+ | *int absRow()const; | ||
+ | *:it returns the sum of '''row()''' of this border plus all the '''row()'''s of the '''_containter'''s | ||
+ | *int absCol()const; | ||
+ | *:it returns the sum of '''col()''' of this border plus all the '''col()'''s of the '''_containter'''s | ||
+ | |||
+ | The following are the pseudo code to get absRow( ) and as well as absCol( ): | ||
+ | <pre> | ||
+ | r = _row | ||
+ | Cnt = container | ||
+ | while(Cnt is not null)begin | ||
+ | add Cnt.row to r | ||
+ | set Cnt to Cnt.container | ||
+ | end | ||
+ | return r | ||
</pre> | </pre> | ||
− | ==== | + | |
+ | These two methods return the absolute coordinates of the FWBorder instance. (the row an column with respect to left top corner of the screen). These two functions are used to '''draw''' the border on the screen. | ||
+ | |||
+ | =====public===== | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | FWBorder(int Row=0, int Col=0, int Width=0,int Height=0, | ||
+ | bool Visible = false, | ||
+ | const char* Border=FW_BORDER_CHARS, | ||
+ | FWBorder* Container = (FWBorder*)0); | ||
+ | </syntaxhighlight></big> | ||
+ | Sets the corresponding attributes to the incoming values in the argument list. | ||
+ | |||
<big><syntaxhighlight lang="cpp"> | <big><syntaxhighlight lang="cpp"> | ||
− | + | void visible(bool val); | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | void visible(bool val); | ||
bool visible()const; | bool visible()const; | ||
Line 47: | Line 203: | ||
void row(int val); | void row(int val); | ||
+ | int row()const; | ||
+ | |||
void col(int val); | void col(int val); | ||
− | void size(int height, int | + | int col()const; |
+ | |||
+ | void size(int width, int height); | ||
+ | int height()const; | ||
+ | int width()const; | ||
+ | </syntaxhighlight></big> | ||
+ | |||
+ | These Methods, set and get the corresponding attributes of the class | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | bool fullscreen()const; | ||
+ | </syntaxhighlight></big> | ||
+ | Returns true if _container is null or else, it returns false; | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | virtual ~FWBorder(); | ||
+ | </syntaxhighlight></big> | ||
+ | An empty virtual destructor. | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | virtual void draw(int refresh = FW_NO_REFRESH)const; | ||
+ | </syntaxhighlight></big> | ||
+ | |||
+ | If _container is null then it just clears the screen and exits. <br /> | ||
+ | Otherwise:<br /> | ||
+ | *If '''Refresh''' flag is set to FW_REFRESH, it will call the _container's draw, passing the same value as argument | ||
+ | *If the _visible flag is true, it will draw a box at _row and _col, with size of _width and _height using the _border characters and fills it with spaces. Otherwise it will just draw a box using spaces at the same location and same size. | ||
+ | |||
+ | ===Border Tester=== | ||
+ | |||
+ | [[OOP344 20103 BorderTester | BorderTester.cpp]] | ||
+ | |||
+ | ==FWField== | ||
+ | This is an abstract class that is the base of any IO Field entity on a Dialog Box. It holds essential common attributes of a Fields (which some are inherited from border) and enforces implementation of essential methods by it children through pure virtual methods. | ||
+ | |||
+ | Forward declaration of FWDialog is needed for this class; | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | class FWField: public FWBorder{ | ||
+ | protected: | ||
+ | void* _data; | ||
+ | public: | ||
+ | FWField(int Row = 0, int Col = 0, | ||
+ | int Width = 0, int Height =0, | ||
+ | void* Data = (void*) 0, | ||
+ | bool Bordered = false, | ||
+ | const char* Border=FW_BORDER_CHARS); | ||
+ | ~FWField(); | ||
+ | virtual int edit() = 0; | ||
+ | virtual bool editable() const = 0; | ||
+ | |||
+ | |||
+ | virtual void set(const void* data) = 0; | ||
+ | virtual void* data(); | ||
+ | |||
+ | void container(FWDialog* theOwner); | ||
+ | FWDialog* container(); | ||
+ | }; | ||
+ | </syntaxhighlight></big> | ||
+ | |||
+ | |||
+ | |||
+ | ===Attributes=== | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | void* _data; | ||
+ | </syntaxhighlight></big> | ||
+ | Will hold the address of any type of data a FWField can hold. | ||
+ | ===Methods=== | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | FWField(int Row = 0, int Col = 0, | ||
+ | int Width = 0, int Height =0, | ||
+ | void* Data = (void*) 0, | ||
+ | bool Bordered = false, | ||
+ | const char* Border=FW_BORDER_CHARS); | ||
+ | </syntaxhighlight></big> | ||
+ | |||
+ | Passes the corresponding attributes to it's parents constructor and then sets the _data attribute to the incoming Data argument. | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | ~FWField(); | ||
+ | </syntaxhighlight></big> | ||
+ | An empty destructor | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | virtual int edit() = 0; | ||
+ | </syntaxhighlight></big> | ||
+ | Enforces the children to implement an edit() method | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | virtual bool editable() const = 0; | ||
+ | </syntaxhighlight></big> | ||
+ | Enforces the children to implement an editable() method that returns true if the class is to edit data and false if the class is to only display data. | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | virtual void set(const void* data) = 0; | ||
+ | </syntaxhighlight></big> | ||
+ | Enforces the children to implement a set() method to set the _data attribute to the data the class is to work with. | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | virtual void* data(); | ||
+ | </syntaxhighlight></big> | ||
+ | Returns _data; | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | void container(FWDialog* theOwner); | ||
+ | </syntaxhighlight></big> | ||
+ | |||
+ | Sets the _container attribute of FWBorder to '''theowner''' argument. | ||
+ | |||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | FWDialog* container(); | ||
+ | </syntaxhighlight></big> | ||
+ | |||
+ | Casts the return value of FWBorder::container() to a FWDialog* and returns it. | ||
+ | |||
+ | ==FWLabel== | ||
+ | FWLabel is child of FWField (therefore inheriting FWBorder too) responsible to display a short character string on the display. | ||
+ | This class is never editable | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | class FWLabel: public FWField{ | ||
+ | int _length; | ||
+ | public: | ||
+ | FWLabel(const char *Str, int Row, int Col, | ||
+ | int Len = -1); | ||
+ | FWLabel(int Row, int Col, int Len); | ||
+ | ~FWLabel(); | ||
+ | void draw(int Refresh = FW_NO_REFRESH) const; | ||
+ | int edit(); | ||
+ | bool editable()const; | ||
+ | void set(const void* str); | ||
+ | }; | ||
+ | |||
+ | </syntaxhighlight></big> | ||
+ | |||
+ | ===Attributes=== | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | int _length; | ||
+ | </syntaxhighlight></big> | ||
+ | Holds the Length of the display area needed by iol_display. | ||
− | + | ===Methods=== | |
− | + | <big><syntaxhighlight lang="cpp"> | |
− | + | FWLabel(const char *Str, int Row, int Col, | |
− | + | int Len = -1); | |
</syntaxhighlight></big> | </syntaxhighlight></big> | ||
+ | *Passes corresponding arguments to its parent constructor | ||
+ | *Sets _length to the '''Len''' attribute. | ||
+ | *Allocates enough memory for the size of data (that is '''_lentgth''' or the length of the '''Str''' if '''_length''' is zero or negative) and sets '''_data''' to point to it. | ||
+ | *Then it will copy the content of what '''Str''' is pointing. | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | FWLabel(int Row, int Col, int Len); | ||
+ | </syntaxhighlight></big> | ||
+ | *Passes corresponding arguments to its parent constructor | ||
+ | *Sets _length to the '''Len''' attribute. | ||
+ | *Allocates Len + 1 bytes and sets it to be an empty string and then sets '''_data''' to point to it. | ||
+ | |||
+ | This constructor is used when FWLabel is used for messaging and does not need initial value. | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | ~FWLabel(); | ||
+ | </syntaxhighlight></big> | ||
+ | Deallocates the memory pointed by _data; | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | void draw(int Refresh = FW_NO_REFRESH) const; | ||
+ | </syntaxhighlight></big> | ||
+ | Ignores the Refresh argument and make a direct call to '''iol_display''' to display the _data at '''absRow()''' and '''absCol()''' upto '''_length''' characters. | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | int edit(); | ||
+ | </syntaxhighlight></big> | ||
+ | Since no editing is happening here, it just calls draw(); | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | bool editable()const; | ||
+ | </syntaxhighlight></big> | ||
+ | Returns False. | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | void set(const void* str); | ||
+ | </syntaxhighlight></big> | ||
+ | copies the string pointed by '''str''' upto '''_length''' characters to '''_data'''. | ||
+ | |||
+ | ==FWDialog== | ||
+ | FWDialog is a collection of several FWField; it organizes and groups FWFields for user entry and interaction <br /> | ||
+ | The following definition is just a suggestion for how to implement this class. You can change it under with your professors confirmation to a better way if you like. | ||
+ | |||
+ | ===Class Definition=== | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | |||
+ | class FWDialog: public FWBorder{ | ||
+ | private: | ||
+ | int _fnum; | ||
+ | int _curidx; | ||
+ | FWField* _fld[FW_MAX_NO_FIELDS]; | ||
+ | bool _dyn[FW_MAX_NO_FIELDS]; | ||
+ | bool _editable; | ||
+ | public: | ||
+ | FWDialog(FWBorder *Container = (FWBorder*)0, | ||
+ | int Row = -1, int Col = -1, | ||
+ | int Width = -1, int Height = -1, | ||
+ | bool Borderd = false, | ||
+ | const char* Border=FW_BORDER_CHARS); | ||
+ | virtual ~FWDialog(); | ||
+ | void draw(int fn = FW_NO_REFRESH)const; | ||
+ | int edit(int fn = FW_NO_REFRESH); | ||
+ | |||
+ | |||
+ | int add(FWField* field, bool dynamic = true); | ||
+ | int add(FWField& field, bool dynamic = false); | ||
+ | FWDialog& operator<<(FWField* field); | ||
+ | FWDialog& operator<<(FWField& field); | ||
+ | |||
+ | |||
+ | bool editable(); | ||
+ | int fieldNum()const; | ||
+ | int curIndex()const; | ||
+ | |||
+ | |||
+ | FWField& operator[](unsigned int index); | ||
+ | FWField& curField(); | ||
+ | }; | ||
+ | |||
+ | |||
+ | </syntaxhighlight></big> | ||
+ | |||
+ | |||
+ | ===Attributes=== | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | int _fnum; | ||
+ | </syntaxhighlight></big> | ||
+ | Holds the number of FWFields added to FWDialog. | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | int _curidx; | ||
+ | </syntaxhighlight></big> | ||
+ | Holds the index of the FWFields that is being edited now. | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | FWField* _fld[FW_MAX_NO_FIELDS]; | ||
+ | </syntaxhighlight></big> | ||
+ | An array of FWFields pointers. Initially all the elements of _fld is set to null. When a FWField is added to the form, it will be pointed by one of the elements of this array. | ||
+ | |||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | bool _dyn[FW_MAX_NO_FIELDS]; | ||
+ | </syntaxhighlight></big> | ||
+ | An array of boolean values exactly to the number of elements of _fld. When FWField number "n" is added to FWDialog and is pointed by _fld[n-1], the corresponding _dyn[n-1] indicate if the FWField held in _fld[n-1] is dynamically allocated or not. the _dyn flags will be used in the destructor as deallocation condition for each _fld element. | ||
+ | |||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | bool _editable; | ||
+ | </syntaxhighlight></big> | ||
+ | Is set to true, if at least one of the FWFields in _fld is editable. | ||
+ | |||
+ | ===Methods=== | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | FWDialog(FWBorder *Container = (FWBorder*)0, | ||
+ | int Row = -1, int Col = -1, | ||
+ | int Width = -1, int Height = -1, | ||
+ | bool Borderd = false, | ||
+ | const char* Border=FW_BORDER_CHARS); | ||
+ | </syntaxhighlight></big> | ||
+ | Passes all the arguments to its parent constructor and then sets the FWDialog to an empty dialog.<br /> | ||
+ | (Sets all the Field pointers to null, flags to false and numbers to zero) | ||
+ | |||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | virtual ~FWDialog(); | ||
+ | </syntaxhighlight></big> | ||
+ | Loops through all the field pointers and checks to see if any of them are dynamically allocated and deletes them. | ||
+ | (it only deletes those fields that are flagged as dynamic) | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | void draw(int fn = FW_NO_REFRESH)const; | ||
+ | </syntaxhighlight></big> | ||
+ | If '''fn''' is '''FW_REFRESH''' or '''FW_FULL_FRAME''', it will call its parent draw with '''fn''' as its argument. Then It will draw all the '''Fields''' in the '''Dialog'''. <br /> | ||
+ | If '''fn''' is '''FW_NO_REFRESH''', then it will just draw all the '''Fields''' in the '''Dialog'''.<br /> | ||
+ | If '''fn''' is a non-zero positive value, then it will only draw '''Field''' number '''fn''' in the dialog. (First added '''Field''' is field number one.) | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | int edit(int fn = FW_NO_REFRESH); | ||
+ | </syntaxhighlight></big> | ||
+ | |||
+ | If '''FWDialog''' is not editable (all fields are non-editable), it will just display the Dialog and then waits for the user to enter a key and then terminates the function returning the key.<br /> | ||
+ | If fn is '''0''' or less, then before editing, the draw method is called with '''fn''' as its argument and then editing begins from the first editable Field. | ||
+ | |||
+ | If fn is greater than '''0''' then editing begins from the first editable key on or after Field number '''fn'''. | ||
+ | |||
+ | Note that fn is the sequence number of field and not the index. (First field number is one) | ||
+ | |||
+ | Start editing from field number '''fn'''; | ||
+ | |||
+ | Call the edit of each field and depending on the value returned, do the following:<br /> | ||
+ | # For '''ENTER_KEY''', '''TAB_KEY''' and '''DOWN_KEY''', go to next editable Field , if this is the last editable Field then restart from Field number one. | ||
+ | # For '''UP_KEY''' go to the previous editable Field, if there is no previous editable Field, go to the last editable Field in the Dialog. | ||
+ | # For any other key, terminate the edit function returning the character which caused the termination. | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | int add(FWField* field, bool dynamic = true); | ||
+ | </syntaxhighlight></big> | ||
+ | Adds the '''FWField''' pointed by '''field''' to the Fields of the Dialog; by appending the value of the field pointer to the _fld array , setting the corresponding _dyn element to the value of dynamic argument and then increasing _fnum by one and returning it. | ||
+ | |||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | int add(FWField& field, bool dynamic = false); | ||
+ | </syntaxhighlight></big> | ||
+ | Makes a direct call to the previous add() method, passing the address of the '''field''' argument and the value of the '''dynamic''' argument and returning what it returns. | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | FWDialog& operator<<(FWField* field); | ||
+ | </syntaxhighlight></big> | ||
+ | Makes a direct call the first '''add()''' method returning a reference of the owner (the FWDialog); | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | FWDialog& operator<<(FWField& field); | ||
+ | </syntaxhighlight></big> | ||
+ | Makes a direct call the second '''add()''' method returning a reference of the owner (the FWDialog); | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | bool editable(); | ||
+ | </syntaxhighlight></big> | ||
+ | If at least one editable field exist in the Dialog, it returns true, otherwise, it returns false; | ||
+ | |||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | int fieldNum()const; | ||
+ | </syntaxhighlight></big> | ||
+ | Returns number of fields added to the Dialog. | ||
+ | |||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | int curIndex()const; | ||
+ | </syntaxhighlight></big> | ||
+ | Returns the index of the Field that was just being edited. | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | FWField& operator[](unsigned int index); | ||
+ | </syntaxhighlight></big> | ||
+ | Returns the reference of the Field with incoming index. (Note that here, the first field index is '''0''') | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | FWField& curField(); | ||
+ | </syntaxhighlight></big> | ||
+ | Returns the reference of the Field that was just being edited. | ||
+ | |||
+ | ===Dialog and Label Tester=== | ||
+ | [[OOP344 20103 Framework Dialog and Label Tester | Test2DialogAndLabel.cpp]] | ||
+ | |||
+ | ==FWLineEdit== | ||
+ | |||
+ | ===Class Definition=== | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | |||
+ | class FWLineEdit: public FWField{ | ||
+ | bool _dyn; | ||
+ | int _maxdatalen; | ||
+ | int* _insertmode; | ||
+ | int _curpos; | ||
+ | int _offset; | ||
+ | public: | ||
+ | FWLineEdit(char* Str, int Row, int Col, int Width, | ||
+ | int Maxdatalen, int* Insertmode, | ||
+ | bool Bordered = false, | ||
+ | const char* Border=FW_BORDER_CHARS); | ||
+ | FWLineEdit(int Row, int Col, int Width, | ||
+ | int Maxdatalen, int* Insertmode, | ||
+ | bool Bordered = false, | ||
+ | const char* Border=FW_BORDER_CHARS); | ||
+ | ~FWLineEdit(); | ||
+ | void draw(int Refresh = FW_NO_REFRESH)const; | ||
+ | |||
+ | int edit(); | ||
+ | bool editable()const; | ||
+ | |||
+ | void set(const void* Str); | ||
+ | }; | ||
+ | |||
+ | </syntaxhighlight></big> | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | FWLineEdit(char* Str, int Row, int Col, int Width, | ||
+ | int Maxdatalen, int* Insertmode, | ||
+ | bool Bordered = false, | ||
+ | const char* Border=FW_BORDER_CHARS); | ||
+ | </syntaxhighlight></big> | ||
+ | LineEdit, sets the Field's _data to the value of str. If LineEdit is instantiated with this constructor then it will edit an external string provided by the caller function of LineEdit. LineEdit in this case is not creating any dynamic memory, therefore _dyn is set to false (therefore the destructor will not attempt to deallocate the memory pointed by _data).<br /> | ||
+ | The location (row and col) and Bordered are directly passed to the parent (FWField) and str is passed as data to the parent constructor. Unlike Label, LineEdit could have border or not so depending on this (Bordered being true or false) the Height is set to 3 or 1 respectfully. <br /> | ||
+ | (hint: use '''? :''' operator to pass the proper value to FWField's constructor) | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | FWLineEdit(int Row, int Col, int Width, | ||
+ | int Maxdatalen, int* Insertmode, | ||
+ | bool Bordered = false, | ||
+ | const char* Border=FW_BORDER_CHARS); | ||
+ | </syntaxhighlight></big> | ||
+ | Works exactly like the previous constructor with one difference; since no external data is passed to be edited here, this constructor must allocate enough dynamic memory to accommodate editing of '''Maxdatalen''' characters. Then make it an empty string and set Fields's _data to point to it. Make sure _dyn is set to true in this case, so the destructor knows that it has to deallocate the memory at the end. | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | ~FWLineEdit(); | ||
+ | </syntaxhighlight></big> | ||
+ | If '''_dyn''' is true, it will deallocate the character array pointed by Fields's '''_data''' | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | void draw(int Refresh = FW_NO_REFRESH)const; | ||
+ | </syntaxhighlight></big> | ||
+ | If the Border is visible, it will first call Border's draw passing '''Refresh'''as an argument to it.<br /> | ||
+ | Then it will make a direct call to iol_display to show the data kept in Field's '''_data'''.<br /> | ||
+ | The values used for the arguments of iol_display are: | ||
+ | *str: address of string pointed by _data + the value of _offset | ||
+ | *row: absRos() (''add one if border is visible'') | ||
+ | *col: absCol() (''add one if border is visible'') | ||
+ | *len: width() (''reduce by two is border is visible''') | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | int edit(); | ||
+ | </syntaxhighlight></big> | ||
+ | Makes and direct call to, and returns '''iol_edit()'''. | ||
+ | For the coordinates and width arguments follow the same rules as the draw function. | ||
+ | For the rest of the arguments of iol_edit, use the attributes of '''FWLineEdit'''. | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | bool editable()const; | ||
+ | </syntaxhighlight></big> | ||
+ | Always return true; | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | void set(const void* Str); | ||
+ | </syntaxhighlight></big> | ||
+ | Copies the characters pointed by '''Str''' into the memory pointed by Field's '''_data''' up to '''_maxdatalen''' characters. | ||
+ | |||
+ | === Dialog and Line editor Tester === | ||
+ | |||
+ | [[oop344 20103 Framework Dialog and Lineeditor Tester | DialogAndLineEditor.cpp]] | ||
+ | |||
+ | ==FWButton== | ||
+ | Button is a child of FWField. | ||
+ | It displays a small piece of text (usually one word or two) and accepts one key hit entry. | ||
+ | When in edit mode, to indicate the editing mode, it will surround the text with squared brackets. | ||
+ | ===Class Definition=== | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | |||
+ | class FWButton: public FWField{ | ||
+ | public: | ||
+ | FWButton(const char *Str, int Row, int Col, | ||
+ | bool Bordered = true, | ||
+ | const char* Border=FW_BORDER_CHARS); | ||
+ | ~FWButton(); | ||
+ | void draw(int Refresh = FW_NO_REFRESH) const; | ||
+ | int edit(); | ||
+ | bool editable()const; | ||
+ | void set(const void* str); | ||
+ | }; | ||
+ | |||
+ | </syntaxhighlight></big> | ||
+ | |||
+ | ===Methods=== | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | FWButton(const char *Str, int Row, int Col, | ||
+ | bool Bordered = true, | ||
+ | const char* Border=FW_BORDER_CHARS); | ||
+ | </syntaxhighlight></big> | ||
+ | When creating a Button, allocate enough memory to hold the contents of the '''Str''' and set Field's _data to point to it. Then copy the content of '''Str''' into the newly allocated memory.<br /> | ||
+ | Pass all the arguments directly to Field's constructor.<br /> | ||
+ | For Field size (width and hight) do the following:<br /> | ||
+ | For width: Set width to the length of '''Str''' + 2 (adding 2 for surrounding brackets) or if the Button is bordered set width to the length of '''Str''' + 4 (adding 2 for surrounding brackets and 2 for the borders). | ||
+ | For height: Set the height to 1 or if the Button is bordered, set the height to 3. | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | ~FWButton(); | ||
+ | </syntaxhighlight></big> | ||
+ | Deallocates the allocated memory pointed by Field's '''_data'''. | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | void draw(int Refresh = FW_NO_REFRESH) const; | ||
+ | </syntaxhighlight></big> | ||
+ | *First calls Border's draw() | ||
+ | use iol_display to display the Button's text (pointed by Field's _data) | ||
+ | *If not bordered | ||
+ | *:display the text at absRow() and absCol() | ||
+ | *If bordered | ||
+ | *:display the text at absRow()+1 and absCol()+2 | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | int edit(); | ||
+ | </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 FW_BUTTON_HIT (defined in confw.h) otherwise return the entered key.<br /> | ||
+ | Make sure the surrounding characters are replaced with spaces before exiting the edit() method. | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | bool editable()const; | ||
+ | </syntaxhighlight></big> | ||
+ | Always returns true; | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | void set(const void* str); | ||
+ | </syntaxhighlight></big> | ||
+ | Reallocate memory for new text set it to content of '''str''': | ||
+ | :''First deallocated what is pointed by Field's '''_data'''.''<br /> | ||
+ | :''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.'' | ||
+ | |||
+ | ===Button Tester=== | ||
+ | |||
+ | [[Project Button Text - OOP344 20103 | ButtonTest.cpp]] | ||
+ | |||
+ | ==FWCheck== | ||
+ | FWCheck class is a '''flagged''' Label. | ||
+ | FWCheck prints a checkbox and a Label in front of it and waits for user entry to possibly toggle the checkbox and exit. | ||
+ | ===Class Definition=== | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | class FWCheck : public FWLabel { | ||
+ | int _flag; | ||
+ | int _radio; | ||
+ | char _format[4]; | ||
+ | public: | ||
+ | FWCheck(bool Checked,const char* Format, const char* Text, int Row, int Col, bool IsRadio = false); | ||
+ | void draw(int Refresh = FW_NO_REFRESH) const; | ||
+ | int edit(); | ||
+ | bool editable()const; | ||
+ | void set(const void* flag); | ||
+ | void *data(); | ||
+ | bool checked()const; | ||
+ | void checked(bool val); | ||
+ | }; | ||
+ | </syntaxhighlight></big> | ||
+ | |||
+ | ===Attributes=== | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | int _flag; | ||
+ | int _radio; | ||
+ | char _format[4]; | ||
+ | </syntaxhighlight></big> | ||
+ | *'''_flag''' holds the status of the Checkbox (0: unchecked or 1: checked). | ||
+ | *'''_radio''' dictates the behavior of the Checkbox as a radio-button, or a check-mark. | ||
+ | *'''_format''' holds the characters, the Checkbox is drawn with (i.e. "[X]", "(O)", "<*>", etc...). | ||
+ | ===Methods=== | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | FWCheck(bool Checked,const char* Format, const char* Text, int Row, int Col, bool IsRadio = false); | ||
+ | </syntaxhighlight></big> | ||
+ | To create a FWCheck, pass Text, Row and Col + 4 to Parents Str, Row, Col. (added 4 to Col to make space for the checkmark at left). | ||
+ | Store Checked, IsRadio and Format in class attributes for future use. | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | void draw(int Refresh = FW_NO_REFRESH) const; | ||
+ | </syntaxhighlight></big> | ||
+ | First call Label's draw passing Refresh as argument.<br /> | ||
+ | Then display a checkbox using iol_displayflag() using '''_format''' and '''_flag''' at absRow() and absCol(). <br /> | ||
+ | ''(make sure there is a space between the checkmark and the Label text)'' | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | int edit(); | ||
+ | </syntaxhighlight></big> | ||
+ | Direct call and return of iol_flag, using same arguments used in draw(); | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | bool editable()const; | ||
+ | </syntaxhighlight></big> | ||
+ | Always returns true; | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | void set(const void* flag); | ||
+ | </syntaxhighlight></big> | ||
+ | Set the '''_flag''' to the boolean pointed by '''flag''' attribute. | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | void *data(); | ||
+ | </syntaxhighlight></big> | ||
+ | Returns address of '''_flag''' | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | bool checked()const; | ||
+ | </syntaxhighlight></big> | ||
+ | Return true if '''_flag''' is not zero. | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | void checked(bool val); | ||
+ | </syntaxhighlight></big> | ||
+ | Sets '''_flag''' to 1 if val is true, or zero if val is false. | ||
+ | |||
+ | ===Button Tester=== | ||
+ | [[Framework Checkbox Tester - OOP344 21013 | CheckboxTester.cpp]] | ||
+ | |||
+ | ==FWValEdit== | ||
+ | ValEdit is a LineEdit that uses two remote functions (using pointer to functions) to provide help and validation service in addition to what LineEdit does. | ||
+ | |||
+ | ===Class Definition=== | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | class FWValEdit: public FWLineEdit{ | ||
+ | void (*_help)(MessageStatus, FWDialog&); | ||
+ | bool (*_validate)(const char*, FWDialog&); | ||
+ | public: | ||
+ | FWValEdit(char* Str, int Row, int Col, int Width, | ||
+ | int Maxdatalen, int* Insertmode, | ||
+ | bool (*Validate)(const char* , FWDialog&) = NO_VALDFUNC, | ||
+ | void (*Help)(MessageStatus, FWDialog&) = NO_HELPFUNC, | ||
+ | bool Bordered = false, | ||
+ | const char* Border=FW_BORDER_CHARS); | ||
+ | FWValEdit(int Row, int Col, int Width, | ||
+ | int Maxdatalen, int* Insertmode, | ||
+ | bool (*Validate)(const char* , FWDialog&) = NO_VALDFUNC, | ||
+ | void (*Help)(MessageStatus, FWDialog&) = NO_HELPFUNC, | ||
+ | bool Bordered = false, | ||
+ | const char* Border=FW_BORDER_CHARS); | ||
+ | int edit(); | ||
+ | }; | ||
+ | </syntaxhighlight></big> | ||
+ | |||
+ | |||
+ | ===Attributes=== | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | void (*_help)(MessageStatus, FWDialog&); | ||
+ | bool (*_validate)(const char*, FWDialog&); | ||
+ | </syntaxhighlight></big> | ||
+ | Pointers to keep the address of possible help and validation function.<br /> | ||
+ | ''Note that if these two are NULL, then ValEdit works exactly like LineEdit'' | ||
+ | ===Methods=== | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | FWValEdit(char* Str, int Row, int Col, int Width, | ||
+ | int Maxdatalen, int* Insertmode, | ||
+ | bool (*Validate)(const char* , FWDialog&) = NO_VALDFUNC, | ||
+ | void (*Help)(MessageStatus, FWDialog&) = NO_HELPFUNC, | ||
+ | bool Bordered = false, | ||
+ | const char* Border=FW_BORDER_CHARS); | ||
+ | FWValEdit(int Row, int Col, int Width, | ||
+ | int Maxdatalen, int* Insertmode, | ||
+ | bool (*Validate)(const char* , FWDialog&) = NO_VALDFUNC, | ||
+ | void (*Help)(MessageStatus, FWDialog&) = NO_HELPFUNC, | ||
+ | bool Bordered = false, | ||
+ | const char* Border=FW_BORDER_CHARS); | ||
+ | </syntaxhighlight></big> | ||
+ | They Pass the arguments to corresponding parents constructor.<br /> | ||
+ | Then they Set '''_validate''' and '''_help''' attributes to their corresponding values in argument list. | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | int edit(); | ||
+ | </syntaxhighlight></big> | ||
+ | If the container() is NULL then this function works exactly like LineEdit::edit().<br /> | ||
+ | If the container() is not NULL: | ||
+ | #If _help function exist it calls the function passing MessageStatus::SetMessage and container()'s reference as arguments. | ||
+ | #Calls LineEdit's edit() | ||
+ | #If validation function exists and the terminating key of LineEdit's edit() is a navigation key(see below) | ||
+ | #:It will call the validation function on the Field's _data, if the data is valid, it goes to next step, otherwise it will repeat calling LineEdit's edit(). | ||
+ | #After validation is done, if _help function exists, it will recall the help function using MessageStatus::ClearMessage and contianer()'s reference as arguments. | ||
+ | #It will return the terminating key | ||
+ | |||
+ | ''Navigation keys are Up key, Down key, Tab key or Enter key.''<br /> | ||
+ | ''MessageStatus is enumerated in confw.h''' | ||
+ | |||
+ | ===Validated Line editor Tester=== | ||
+ | [[Validated LineEdit Tester - OOP344 20103 | FWValEditTester.cpp]] | ||
+ | |||
+ | ==FWText== | ||
+ | The FWText class splits a string of text into series if strings at newline characters, then starts editing them in a text area one string at a time. | ||
+ | Each string in this array of strings represents a line in text. | ||
+ | The lines can scroll left and right (already implemented in iol_edit) and up and down during the edit if needed. | ||
+ | at any time by calling the data() method the array of strings is converted back to a newline separated and null terminated array of characters (Converted back to text) and returned. | ||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | class FWText:public FWField{ | ||
+ | AnArrayOfStrings _lines; // see below | ||
+ | bool _readOnly; | ||
+ | int _curpos; | ||
+ | int _fieldlen; | ||
+ | int _maxdatalen; | ||
+ | int* _insertmode; | ||
+ | int _offset; | ||
+ | int _lcurpos; | ||
+ | int _loffset; | ||
+ | public: | ||
+ | FWText(int Row, int Col, int Width, int Height, bool Readonly, | ||
+ | int* Insertmode, const char* Border=FW_BORDER_CHARS); | ||
+ | FWText(const char* Str, int Row, int Col, int Width, int Height, bool Readonly, | ||
+ | int* Insertmode, const char* Border=FW_BORDER_CHARS); | ||
+ | |||
+ | void draw(int Refresh = FW_NO_REFRESH)const; | ||
+ | void set(const void *Str); | ||
+ | void *data(); | ||
+ | int edit(); | ||
+ | bool editable()const; | ||
+ | bool readOnly()const; | ||
+ | void readOnly(bool val); | ||
+ | ~FWText(); | ||
+ | }; | ||
+ | |||
+ | </syntaxhighlight></big> | ||
+ | |||
+ | |||
+ | ===Attributes=== | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | AnArrayOfStrings _lines; | ||
+ | </syntaxhighlight></big> | ||
+ | Could be one the following: | ||
+ | *A two dimensional array of characters: char _lines[max_number_of_lines][max_number_of_characters_in_line+1];<br /> | ||
+ | *: In this case you text size is limited to the max_number_of_lines and can not grow more than that. | ||
+ | *A dynamic array of strings: [[Dynamic Array Of Strings - OOP344 | StrArr]] _lines;<br /> | ||
+ | *: This case ([[Dynamic Array Of Strings - OOP344 | StrArr]]) is designed to simulate a two dimensional array of characters (or an array of strings) and has no limit in the number of lines and expands automatically if needed. You can use the code for ([[Dynamic Array Of Strings - OOP344 | StrArr]]) at your own risk to implement FWText, or you can design your own logic.<br /> | ||
+ | *A Doubly Linked List (Queue) of strings [[Queue of Strings - OOP344 | StrQue]] | ||
+ | *: [[Queue of Strings - OOP344 | StrQue]] is a Queue of null terminated characters arrays (strings) and like StrArr has no limit in the number of lines and expands automatically if needed. Like StrArr, you can use the code for [[Queue of Strings - OOP344 | StrQue]] at your own risk to implement FWText, or you can design your own logic.<br /> | ||
+ | If you found any bugs or problems with [[Queue of Strings - OOP344 | StrQue]] or [[Dynamic Array Of Strings - OOP344 | StrArr]], do not modify it yourself but instead, please blog about it and send an email to [[mailto:fardad.soleimanloo@senecac.on.ca?subject=OOP344-StrQue me]] and I will take care of updating it.<br /> | ||
+ | You can also find the code for [[Queue of Strings - OOP344 | StrQue]] and it's tester program in class notes repo: (svn://zenit.senecac.on.ca/oop344/trunk/C/13-Nov12). | ||
+ | |||
+ | |||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | bool _readOnly; | ||
+ | </syntaxhighlight></big> | ||
+ | Keeps the status of the text being read only, or editable. (note that when read only, you can still scroll the text to left and right or up and down, but you can't modify the text).<br /> | ||
+ | This flag is passed to iol_edit for the same reason. | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | int _curpos; | ||
+ | int _fieldlen; | ||
+ | int _maxdatalen; | ||
+ | int* _insertmode; | ||
+ | int _offset; | ||
+ | </syntaxhighlight></big> | ||
+ | Variables to be used with iol_edit to edit the lines of text. | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | int _lcurpos; | ||
+ | </syntaxhighlight></big> | ||
+ | Line Cursor Position; this variable keeps track of which line of text the cursor is on. _lcurpos is zero, if the cursor is on the fist line appearing in the Border. | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | int _loffset; | ||
+ | </syntaxhighlight></big> | ||
+ | Offset Of the First Line; this variable keeps track of which line is the first appearing in the border. _loffset is zero, if the first string (line) of the string array is appearing on the fist line of the Border.<br /><br /> | ||
+ | '''_lcurpos''' and '''_loffset''' have the same responsibility as _curpos, and _offset, but only for lines of the text. So as the left and right scrolling is done by manipulating _offset and _curpos, up and down scrolling of lines in the text are done by manipulating '''_loffset''' and '''_lcurpose''' | ||
+ | |||
+ | ===Methods=== | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | FWText(int Row, int Col, int Width, int Height, bool Readonly, | ||
+ | int* Insertmode, const char* Border=FW_BORDER_CHARS); | ||
+ | </syntaxhighlight></big> | ||
+ | Sets all the attributes to their proper/corresponding values<br /> | ||
+ | :''Note that FWText is always bordered'' | ||
+ | If dynamic array of strings is used, initial text is allocated and set to an empty text.<br /> | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | FWText(const char* Str, int Row, int Col, int Width, int Height, bool Readonly, | ||
+ | int* Insertmode, const char* Border=FW_BORDER_CHARS); | ||
+ | </syntaxhighlight></big> | ||
+ | Works exactly like the previous constructor, but also it will call the '''set''' method of FWText to split the incoming text ('''Str''') at newline characters into an array of strings. | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | void draw(int Refresh = FW_NO_REFRESH)const; | ||
+ | </syntaxhighlight></big> | ||
+ | #Calls its parents draw, to draw the border. | ||
+ | #Using iol_display, it prints lines of text from index _loffset, up to height()-2 times. | ||
+ | #:Note that each line is printed from _offset character using absRow() and absCol(), up o width()-2 characters | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | void set(const void *Str); | ||
+ | </syntaxhighlight></big> | ||
+ | Converts the newline delimited array of characters (the text) into an array of strings.<br /> | ||
+ | Set starts with the first string in the array of strings and copies the characters of the array to the current string until it reaches a newline character. <br /> | ||
+ | Then it will null terminate the current string and go to the next string in the array of strings and repeats the same over and over until it reaches the end of the text. | ||
+ | :''Note that if '''FW_MAX_LINE_CHARS''' is reached before getting to the newline character, the current string is null terminated and copying continues into the next one''. | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | void *data(); | ||
+ | </syntaxhighlight></big> | ||
+ | Converts the array of strings, back to a single string of text and returns it.<br /> | ||
+ | '''data()''' first calculates the size of the whole text including the newline characters at the end of each line. Then it will allocated enough memory to hold it all.<br /> Finally, it will concatenate all the strings back into the allocated memory adding a newline character to the end of each of them and returns it. | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | int edit(); | ||
+ | </syntaxhighlight></big> | ||
+ | Draws the text area and then starts the editing from the first line.<br /> | ||
+ | The whole text should scroll to left, right, up or down instead, if the cursor tries to pass the edges of the text area.<br /> | ||
+ | When Enter key is hit, if in insertmode, a new line is inserted after the current line and any text after the cursor in the line should be moved into it.<br /> | ||
+ | When Backspace key is hit at the beginning of the line, the content of the current line should be moved to the previous line, the and current line should be deleted. The cursor in this case should stand in front of the copied data. <br /> | ||
+ | :''Note that this will not happen if the sum of the length of the current and previous lines are more than FW_MAX_LINE_CHARS'' | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | bool editable()const; | ||
+ | </syntaxhighlight></big> | ||
+ | Always return true. | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | bool readOnly()const; | ||
+ | void readOnly(bool val); | ||
+ | </syntaxhighlight></big> | ||
+ | These two methods Get and Set the _readOnly attribute. | ||
+ | <big><syntaxhighlight lang="cpp"> | ||
+ | ~FWText(); | ||
+ | </syntaxhighlight></big> | ||
+ | It deallocates the allocated memory. (If any memory allocation is used). | ||
+ | |||
+ | =Compile, Build, testing= | ||
+ | ==Compile and build== | ||
+ | *Here is a sample of a make file on Linux, you can also find this '''makefile''' at svn://zenit.senecac.on.ca/oop344/trunk/C/Prj/makefile | ||
+ | |||
+ | <big><pre> | ||
+ | prj: iol.o fwborder.o fwfield.o fwlabel.o fwlineedit.o fwbutton.o fwcheck.o fwveditline.o fwdialog.o fwtext.o strarr.o testmains.o | ||
+ | c++ iol.o fwborder.o fwfield.o fwlabel.o fwlineedit.o fwbutton.o fwcheck.o fwveditline.o fwdialog.o fwtext.o strarr.o testmains.o \ | ||
+ | -lncurses -oprj | ||
+ | |||
+ | iol.o: iol.c iol.h | ||
+ | cc -c iol.c | ||
+ | |||
+ | fwborder.o: fwborder.cpp fwborder.h confw.hiol.h | ||
+ | c++ -c fwborder.cpp | ||
+ | |||
+ | fwfield.o: fwfield.cpp fwfield.h fwborder.h confw.h iol.h | ||
+ | c++ -c fwfield.cpp | ||
+ | |||
+ | fwlabel.o: fwlabel.cpp fwlabel.h fwfield.h fwborder.h confw.h iol.h | ||
+ | c++ -c fwlabel.cpp | ||
+ | |||
+ | fwlineedit.o: fwlineedit.cpp fwlineedit.h fwfield.h fwborder.h confw.h iol.h | ||
+ | c++ -c fwlineedit.cpp | ||
+ | |||
+ | fwbutton.o: fwbutton.cpp fwbutton.h fwfield.h fwborder.h confw.h iol.h | ||
+ | c++ -c fwbutton.cpp | ||
+ | |||
+ | fwcheck.o: fwcheck.cpp fwcheck.h fwlabel.h fwfield.h fwborder.h confw.h iol.h | ||
+ | c++ -c fwcheck.cpp | ||
+ | |||
+ | fwveditline.o: fwveditline.cpp fwveditline.h fwlineedit.h fwfield.h fwborder.h confw.h iol.h | ||
+ | c++ -c fwveditline.cpp | ||
+ | |||
+ | fwtext.o: fwtext.cpp fwtext.h fwlineedit.h strarr.h fwfield.h fwborder.h confw.h iol.h | ||
+ | c++ -c fwtext.cpp | ||
+ | |||
+ | strarr.o: strarr.cpp strarr.h | ||
+ | c++ -c strarr.cpp | ||
+ | |||
+ | fwdialog.o: fwdialog.cpp fwdialog.h fwfield.h fwborder.h confw.h iol.h | ||
+ | c++ -c fwdialog.cpp | ||
+ | |||
+ | testmains.o: testmains.cpp fwdialog.h strarr.h fwtext.h fwveditline.h fwcheck.h fwbutton.h fwlineedit.h fwlabel.h fwfield.h fwborder.h iol.h | ||
+ | c++ -c testmains.cpp | ||
+ | |||
+ | </pre></big> | ||
+ | |||
+ | ==Testing== | ||
+ | *All the test programs are saved at: svn://zenit.senecac.on.ca/oop344/trunk/C/Prj | ||
+ | *Test files names are '''Test*.cpp''' | ||
+ | *All test programs are compiled the executable is available on '''matrix.senecac.on.ca/~fardad.soleimanloo''' | ||
+ | *:to run the test programs, login to matrix.senecac.on.ca and login with your own user id and password, then at the command line type: '''~fardad.soleimanloo/tX''', replace the X with the number of the test. (i.e for test three, run: '''~fardad.soleimanloo/t3''') | ||
+ | *:Note that you should use [http://www.chiark.greenend.org.uk/~sgtatham/putty/ Putty] to login to matrix and set the keyboard to Xterm 6 | ||
+ | |||
+ | =Due Date= | ||
+ | *Due Nov 29, 23:59 | ||
+ | *: Tagged prj0.6 |
Latest revision as of 13:09, 17 April 2013
OOP344 | Weekly Schedule | Student List | Teams | Project | Student Resources
Contents
The Frame work
under construction!!!!
Your objective at this stage is to create a framework of classes designed to interact with the user. This user interface framework then can be used in development of any interactive application.
please note that the class definitions here are minimum requirement for the framework and you are free to add any enhancements or features you find useful. Obviously it would be wise the discuss these enhancements with your professor to make sure they are feasible.
Depending on the section you are in, you may have different scope in number of the classes you create. please double check your professor's notes on the project before you begin.
It is highly recommended to develop the classes in the order they are stated here. At each stage a tester program is provided to help you test your development. Executables of the test programs are available on matrix to show you how it is supposed to run.
Start by creating mock-up classes (class declaration and definition with empty methods that only compiles and don't do anything)
Each class MUST have its own header file to hold its declaration and "cpp" file to hold its implementation. To make sure you do not do circular includes follow these simple guidelines:
- Add recompilation safeguards to all your header files.
- Always use forward declaration if possible instead of including a class.
- Use includes only in files in which the actual header file code is used. avoid "just in case" includes.
General Internal Header file
The general header file holds the common setting and definition between all classes in the frame work.
#ifndef ___CONFW_H__
#define ___CONFW_H__
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE
#endif
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <string.h>
extern "C"{
#include "iol.h"
};
#define FW_BORDER_CHARS "/-\\|/-\\|"
#define FW_MAX_NO_FIELDS 100
#define FW_BUTTON_HIT 1
#define FW_MAX_LINE_CHARS (1024u)
#define FW_REFRESH -2
#define FW_FULL_FRAME -1
#define FW_NO_REFRESH 0
enum MessageStatus{ClearMessage,SetMessage};
#ifdef NO_HELPFUNC
# undef NO_HELPFUNC
#endif
#define NO_HELPFUNC ((void(*)(MessageStatus, FWDialog&))(0))
#ifdef NO_VALDFUNC
# undef NO_VALDFUNC
#endif
#define NO_VALDFUNC ((bool(*)(const char*, FWDialog&))(0))
#endif
File Names
Use the following rules to create filenames for your class.
- Each class MUST have its own header file and cpp file for implementation
- Use the class name for the name of the file but make sure it is all lowercase.
- For example FWBorder class should have fwborder.h and fwborder.cpp files for its implemetation
Classes
These classes encapsulate all the functions written in IOL library in an Object Oriented method:
Hierarchy
FWBorder | |---FWDialog | | |---FWField | |-------- FWLabel | | | |-------FWCheck | |-------FWMenuItem (Maybe?) | |-------- FWButton | | |-------- FWLineEdit | | | |-------FWValEdit | |-------- FWText | |-------- FWCheckList (Maybe?) |-------- FWMenu (Maybe?)
FWBorder
FWBorder is the base of all IO entities in our framework. It encapsulate a window or a container in witch IO Fields are to be placed and run. Also, It encapsulates a border, cordinates and size.
Class Definition
class FWBorder {
int _row;
int _col;
int _height;
int _width;
char _border[9];
bool _visible;
FWBorder* _container;
protected:
int absRow()const;
int absCol()const;
public:
FWBorder(int Row=-1, int Col=-1, int Width=-1,int Height=-1,
bool Visible = false,
const char* Border=FW_BORDER_CHARS,
FWBorder* Container = (FWBorder*)0);
virtual void draw(int refresh = FW_NO_REFRESH)const;
virtual ~FWBorder();
void visible(bool val);
bool visible()const;
void container(FWBorder* theContainer);
FWBorder* container();
bool fullscreen()const;
void row(int val);
int row()const;
void col(int val);
int col()const;
void size(int width, int height);
int height()const;
int width()const;
};
Properties
int _row, holds the relative coordinate of top row of this border with respect to its container.
int _col, same as _row, but for _col.
int _height, height of the entity.
int _width, width of the entity.
char _border[9], characters used to draw the border:
- _border[0], left top
- _border[1], top side
- _border[2], right top
- _border[3], right side
- _border[4], right bottom
- _border[5], bottom side
- _border[6], bottom left
- _border[7], left side
bool _visible; Indicates if the border surrounding the entity is to be drawn or not.
FWBorder* _container; holds the container (another FWBorder) which has opened this one (owner or container of the current FWBorder). _container will be NULL if this FWBorder does not have a container, in which case, it will be full screen and no matter what the values of row, col, width and height are, FWBorder will be Full Screen (no border will be drawn)
Methods
Protected
- int absRow()const;
- it returns the sum of row() of this border plus all the row()s of the _containters
- int absCol()const;
- it returns the sum of col() of this border plus all the col()s of the _containters
The following are the pseudo code to get absRow( ) and as well as absCol( ):
r = _row Cnt = container while(Cnt is not null)begin add Cnt.row to r set Cnt to Cnt.container end return r
These two methods return the absolute coordinates of the FWBorder instance. (the row an column with respect to left top corner of the screen). These two functions are used to draw the border on the screen.
public
FWBorder(int Row=0, int Col=0, int Width=0,int Height=0,
bool Visible = false,
const char* Border=FW_BORDER_CHARS,
FWBorder* Container = (FWBorder*)0);
Sets the corresponding attributes to the incoming values in the argument list.
void visible(bool val);
bool visible()const;
void container(FWBorder* theContainer);
FWBorder* container();
void row(int val);
int row()const;
void col(int val);
int col()const;
void size(int width, int height);
int height()const;
int width()const;
These Methods, set and get the corresponding attributes of the class
bool fullscreen()const;
Returns true if _container is null or else, it returns false;
virtual ~FWBorder();
An empty virtual destructor.
virtual void draw(int refresh = FW_NO_REFRESH)const;
If _container is null then it just clears the screen and exits.
Otherwise:
- If Refresh flag is set to FW_REFRESH, it will call the _container's draw, passing the same value as argument
- If the _visible flag is true, it will draw a box at _row and _col, with size of _width and _height using the _border characters and fills it with spaces. Otherwise it will just draw a box using spaces at the same location and same size.
Border Tester
FWField
This is an abstract class that is the base of any IO Field entity on a Dialog Box. It holds essential common attributes of a Fields (which some are inherited from border) and enforces implementation of essential methods by it children through pure virtual methods.
Forward declaration of FWDialog is needed for this class;
class FWField: public FWBorder{
protected:
void* _data;
public:
FWField(int Row = 0, int Col = 0,
int Width = 0, int Height =0,
void* Data = (void*) 0,
bool Bordered = false,
const char* Border=FW_BORDER_CHARS);
~FWField();
virtual int edit() = 0;
virtual bool editable() const = 0;
virtual void set(const void* data) = 0;
virtual void* data();
void container(FWDialog* theOwner);
FWDialog* container();
};
Attributes
void* _data;
Will hold the address of any type of data a FWField can hold.
Methods
FWField(int Row = 0, int Col = 0,
int Width = 0, int Height =0,
void* Data = (void*) 0,
bool Bordered = false,
const char* Border=FW_BORDER_CHARS);
Passes the corresponding attributes to it's parents constructor and then sets the _data attribute to the incoming Data argument.
~FWField();
An empty destructor
virtual int edit() = 0;
Enforces the children to implement an edit() method
virtual bool editable() const = 0;
Enforces the children to implement an editable() method that returns true if the class is to edit data and false if the class is to only display data.
virtual void set(const void* data) = 0;
Enforces the children to implement a set() method to set the _data attribute to the data the class is to work with.
virtual void* data();
Returns _data;
void container(FWDialog* theOwner);
Sets the _container attribute of FWBorder to theowner argument.
FWDialog* container();
Casts the return value of FWBorder::container() to a FWDialog* and returns it.
FWLabel
FWLabel is child of FWField (therefore inheriting FWBorder too) responsible to display a short character string on the display. This class is never editable
class FWLabel: public FWField{
int _length;
public:
FWLabel(const char *Str, int Row, int Col,
int Len = -1);
FWLabel(int Row, int Col, int Len);
~FWLabel();
void draw(int Refresh = FW_NO_REFRESH) const;
int edit();
bool editable()const;
void set(const void* str);
};
Attributes
int _length;
Holds the Length of the display area needed by iol_display.
Methods
FWLabel(const char *Str, int Row, int Col,
int Len = -1);
- Passes corresponding arguments to its parent constructor
- Sets _length to the Len attribute.
- Allocates enough memory for the size of data (that is _lentgth or the length of the Str if _length is zero or negative) and sets _data to point to it.
- Then it will copy the content of what Str is pointing.
FWLabel(int Row, int Col, int Len);
- Passes corresponding arguments to its parent constructor
- Sets _length to the Len attribute.
- Allocates Len + 1 bytes and sets it to be an empty string and then sets _data to point to it.
This constructor is used when FWLabel is used for messaging and does not need initial value.
~FWLabel();
Deallocates the memory pointed by _data;
void draw(int Refresh = FW_NO_REFRESH) const;
Ignores the Refresh argument and make a direct call to iol_display to display the _data at absRow() and absCol() upto _length characters.
int edit();
Since no editing is happening here, it just calls draw();
bool editable()const;
Returns False.
void set(const void* str);
copies the string pointed by str upto _length characters to _data.
FWDialog
FWDialog is a collection of several FWField; it organizes and groups FWFields for user entry and interaction
The following definition is just a suggestion for how to implement this class. You can change it under with your professors confirmation to a better way if you like.
Class Definition
class FWDialog: public FWBorder{
private:
int _fnum;
int _curidx;
FWField* _fld[FW_MAX_NO_FIELDS];
bool _dyn[FW_MAX_NO_FIELDS];
bool _editable;
public:
FWDialog(FWBorder *Container = (FWBorder*)0,
int Row = -1, int Col = -1,
int Width = -1, int Height = -1,
bool Borderd = false,
const char* Border=FW_BORDER_CHARS);
virtual ~FWDialog();
void draw(int fn = FW_NO_REFRESH)const;
int edit(int fn = FW_NO_REFRESH);
int add(FWField* field, bool dynamic = true);
int add(FWField& field, bool dynamic = false);
FWDialog& operator<<(FWField* field);
FWDialog& operator<<(FWField& field);
bool editable();
int fieldNum()const;
int curIndex()const;
FWField& operator[](unsigned int index);
FWField& curField();
};
Attributes
int _fnum;
Holds the number of FWFields added to FWDialog.
int _curidx;
Holds the index of the FWFields that is being edited now.
FWField* _fld[FW_MAX_NO_FIELDS];
An array of FWFields pointers. Initially all the elements of _fld is set to null. When a FWField is added to the form, it will be pointed by one of the elements of this array.
bool _dyn[FW_MAX_NO_FIELDS];
An array of boolean values exactly to the number of elements of _fld. When FWField number "n" is added to FWDialog and is pointed by _fld[n-1], the corresponding _dyn[n-1] indicate if the FWField held in _fld[n-1] is dynamically allocated or not. the _dyn flags will be used in the destructor as deallocation condition for each _fld element.
bool _editable;
Is set to true, if at least one of the FWFields in _fld is editable.
Methods
FWDialog(FWBorder *Container = (FWBorder*)0,
int Row = -1, int Col = -1,
int Width = -1, int Height = -1,
bool Borderd = false,
const char* Border=FW_BORDER_CHARS);
Passes all the arguments to its parent constructor and then sets the FWDialog to an empty dialog.
(Sets all the Field pointers to null, flags to false and numbers to zero)
virtual ~FWDialog();
Loops through all the field pointers and checks to see if any of them are dynamically allocated and deletes them. (it only deletes those fields that are flagged as dynamic)
void draw(int fn = FW_NO_REFRESH)const;
If fn is FW_REFRESH or FW_FULL_FRAME, it will call its parent draw with fn as its argument. Then It will draw all the Fields in the Dialog.
If fn is FW_NO_REFRESH, then it will just draw all the Fields in the Dialog.
If fn is a non-zero positive value, then it will only draw Field number fn in the dialog. (First added Field is field number one.)
int edit(int fn = FW_NO_REFRESH);
If FWDialog is not editable (all fields are non-editable), it will just display the Dialog and then waits for the user to enter a key and then terminates the function returning the key.
If fn is 0 or less, then before editing, the draw method is called with fn as its argument and then editing begins from the first editable Field.
If fn is greater than 0 then editing begins from the first editable key on or after Field number fn.
Note that fn is the sequence number of field and not the index. (First field number is one)
Start editing from field number fn;
Call the edit of each field and depending on the value returned, do the following:
- For ENTER_KEY, TAB_KEY and DOWN_KEY, go to next editable Field , if this is the last editable Field then restart from Field number one.
- For UP_KEY go to the previous editable Field, if there is no previous editable Field, go to the last editable Field in the Dialog.
- For any other key, terminate the edit function returning the character which caused the termination.
int add(FWField* field, bool dynamic = true);
Adds the FWField pointed by field to the Fields of the Dialog; by appending the value of the field pointer to the _fld array , setting the corresponding _dyn element to the value of dynamic argument and then increasing _fnum by one and returning it.
int add(FWField& field, bool dynamic = false);
Makes a direct call to the previous add() method, passing the address of the field argument and the value of the dynamic argument and returning what it returns.
FWDialog& operator<<(FWField* field);
Makes a direct call the first add() method returning a reference of the owner (the FWDialog);
FWDialog& operator<<(FWField& field);
Makes a direct call the second add() method returning a reference of the owner (the FWDialog);
bool editable();
If at least one editable field exist in the Dialog, it returns true, otherwise, it returns false;
int fieldNum()const;
Returns number of fields added to the Dialog.
int curIndex()const;
Returns the index of the Field that was just being edited.
FWField& operator[](unsigned int index);
Returns the reference of the Field with incoming index. (Note that here, the first field index is 0)
FWField& curField();
Returns the reference of the Field that was just being edited.
Dialog and Label Tester
FWLineEdit
Class Definition
class FWLineEdit: public FWField{
bool _dyn;
int _maxdatalen;
int* _insertmode;
int _curpos;
int _offset;
public:
FWLineEdit(char* Str, int Row, int Col, int Width,
int Maxdatalen, int* Insertmode,
bool Bordered = false,
const char* Border=FW_BORDER_CHARS);
FWLineEdit(int Row, int Col, int Width,
int Maxdatalen, int* Insertmode,
bool Bordered = false,
const char* Border=FW_BORDER_CHARS);
~FWLineEdit();
void draw(int Refresh = FW_NO_REFRESH)const;
int edit();
bool editable()const;
void set(const void* Str);
};
FWLineEdit(char* Str, int Row, int Col, int Width,
int Maxdatalen, int* Insertmode,
bool Bordered = false,
const char* Border=FW_BORDER_CHARS);
LineEdit, sets the Field's _data to the value of str. If LineEdit is instantiated with this constructor then it will edit an external string provided by the caller function of LineEdit. LineEdit in this case is not creating any dynamic memory, therefore _dyn is set to false (therefore the destructor will not attempt to deallocate the memory pointed by _data).
The location (row and col) and Bordered are directly passed to the parent (FWField) and str is passed as data to the parent constructor. Unlike Label, LineEdit could have border or not so depending on this (Bordered being true or false) the Height is set to 3 or 1 respectfully.
(hint: use ? : operator to pass the proper value to FWField's constructor)
FWLineEdit(int Row, int Col, int Width,
int Maxdatalen, int* Insertmode,
bool Bordered = false,
const char* Border=FW_BORDER_CHARS);
Works exactly like the previous constructor with one difference; since no external data is passed to be edited here, this constructor must allocate enough dynamic memory to accommodate editing of Maxdatalen characters. Then make it an empty string and set Fields's _data to point to it. Make sure _dyn is set to true in this case, so the destructor knows that it has to deallocate the memory at the end.
~FWLineEdit();
If _dyn is true, it will deallocate the character array pointed by Fields's _data
void draw(int Refresh = FW_NO_REFRESH)const;
If the Border is visible, it will first call Border's draw passing Refreshas an argument to it.
Then it will make a direct call to iol_display to show the data kept in Field's _data.
The values used for the arguments of iol_display are:
- str: address of string pointed by _data + the value of _offset
- row: absRos() (add one if border is visible)
- col: absCol() (add one if border is visible)
- len: width() (reduce by two is border is visible')
int edit();
Makes and direct call to, and returns iol_edit(). For the coordinates and width arguments follow the same rules as the draw function. For the rest of the arguments of iol_edit, use the attributes of FWLineEdit.
bool editable()const;
Always return true;
void set(const void* Str);
Copies the characters pointed by Str into the memory pointed by Field's _data up to _maxdatalen characters.
Dialog and Line editor Tester
FWButton
Button is a child of FWField. It displays a small piece of text (usually one word or two) and accepts one key hit entry. When in edit mode, to indicate the editing mode, it will surround the text with squared brackets.
Class Definition
class FWButton: public FWField{
public:
FWButton(const char *Str, int Row, int Col,
bool Bordered = true,
const char* Border=FW_BORDER_CHARS);
~FWButton();
void draw(int Refresh = FW_NO_REFRESH) const;
int edit();
bool editable()const;
void set(const void* str);
};
Methods
FWButton(const char *Str, int Row, int Col,
bool Bordered = true,
const char* Border=FW_BORDER_CHARS);
When creating a Button, allocate enough memory to hold the contents of the Str and set Field's _data to point to it. Then copy the content of Str into the newly allocated memory.
Pass all the arguments directly to Field's constructor.
For Field size (width and hight) do the following:
For width: Set width to the length of Str + 2 (adding 2 for surrounding brackets) or if the Button is bordered set width to the length of Str + 4 (adding 2 for surrounding brackets and 2 for the borders).
For height: Set the height to 1 or if the Button is bordered, set the height to 3.
~FWButton();
Deallocates the allocated memory pointed by Field's _data.
void draw(int Refresh = FW_NO_REFRESH) const;
- First calls Border's draw()
use iol_display to display the Button's text (pointed by Field's _data)
- If not bordered
- display the text at absRow() and absCol()
- If bordered
- display the text at absRow()+1 and absCol()+2
int edit();
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.
When user hits a key, if the key is ENTER_KEY or SPACE, return FW_BUTTON_HIT (defined in confw.h) otherwise return the entered key.
Make sure the surrounding characters are replaced with spaces before exiting the edit() method.
bool editable()const;
Always returns true;
void set(const void* str);
Reallocate memory for new text set it to content of str:
- 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.
Button Tester
FWCheck
FWCheck class is a flagged Label. FWCheck prints a checkbox and a Label in front of it and waits for user entry to possibly toggle the checkbox and exit.
Class Definition
class FWCheck : public FWLabel {
int _flag;
int _radio;
char _format[4];
public:
FWCheck(bool Checked,const char* Format, const char* Text, int Row, int Col, bool IsRadio = false);
void draw(int Refresh = FW_NO_REFRESH) const;
int edit();
bool editable()const;
void set(const void* flag);
void *data();
bool checked()const;
void checked(bool val);
};
Attributes
int _flag;
int _radio;
char _format[4];
- _flag holds the status of the Checkbox (0: unchecked or 1: checked).
- _radio dictates the behavior of the Checkbox as a radio-button, or a check-mark.
- _format holds the characters, the Checkbox is drawn with (i.e. "[X]", "(O)", "<*>", etc...).
Methods
FWCheck(bool Checked,const char* Format, const char* Text, int Row, int Col, bool IsRadio = false);
To create a FWCheck, pass Text, Row and Col + 4 to Parents Str, Row, Col. (added 4 to Col to make space for the checkmark at left). Store Checked, IsRadio and Format in class attributes for future use.
void draw(int Refresh = FW_NO_REFRESH) const;
First call Label's draw passing Refresh as argument.
Then display a checkbox using iol_displayflag() using _format and _flag at absRow() and absCol().
(make sure there is a space between the checkmark and the Label text)
int edit();
Direct call and return of iol_flag, using same arguments used in draw();
bool editable()const;
Always returns true;
void set(const void* flag);
Set the _flag to the boolean pointed by flag attribute.
void *data();
Returns address of _flag
bool checked()const;
Return true if _flag is not zero.
void checked(bool val);
Sets _flag to 1 if val is true, or zero if val is false.
Button Tester
FWValEdit
ValEdit is a LineEdit that uses two remote functions (using pointer to functions) to provide help and validation service in addition to what LineEdit does.
Class Definition
class FWValEdit: public FWLineEdit{
void (*_help)(MessageStatus, FWDialog&);
bool (*_validate)(const char*, FWDialog&);
public:
FWValEdit(char* Str, int Row, int Col, int Width,
int Maxdatalen, int* Insertmode,
bool (*Validate)(const char* , FWDialog&) = NO_VALDFUNC,
void (*Help)(MessageStatus, FWDialog&) = NO_HELPFUNC,
bool Bordered = false,
const char* Border=FW_BORDER_CHARS);
FWValEdit(int Row, int Col, int Width,
int Maxdatalen, int* Insertmode,
bool (*Validate)(const char* , FWDialog&) = NO_VALDFUNC,
void (*Help)(MessageStatus, FWDialog&) = NO_HELPFUNC,
bool Bordered = false,
const char* Border=FW_BORDER_CHARS);
int edit();
};
Attributes
void (*_help)(MessageStatus, FWDialog&);
bool (*_validate)(const char*, FWDialog&);
Pointers to keep the address of possible help and validation function.
Note that if these two are NULL, then ValEdit works exactly like LineEdit
Methods
FWValEdit(char* Str, int Row, int Col, int Width,
int Maxdatalen, int* Insertmode,
bool (*Validate)(const char* , FWDialog&) = NO_VALDFUNC,
void (*Help)(MessageStatus, FWDialog&) = NO_HELPFUNC,
bool Bordered = false,
const char* Border=FW_BORDER_CHARS);
FWValEdit(int Row, int Col, int Width,
int Maxdatalen, int* Insertmode,
bool (*Validate)(const char* , FWDialog&) = NO_VALDFUNC,
void (*Help)(MessageStatus, FWDialog&) = NO_HELPFUNC,
bool Bordered = false,
const char* Border=FW_BORDER_CHARS);
They Pass the arguments to corresponding parents constructor.
Then they Set _validate and _help attributes to their corresponding values in argument list.
int edit();
If the container() is NULL then this function works exactly like LineEdit::edit().
If the container() is not NULL:
- If _help function exist it calls the function passing MessageStatus::SetMessage and container()'s reference as arguments.
- Calls LineEdit's edit()
- If validation function exists and the terminating key of LineEdit's edit() is a navigation key(see below)
- It will call the validation function on the Field's _data, if the data is valid, it goes to next step, otherwise it will repeat calling LineEdit's edit().
- After validation is done, if _help function exists, it will recall the help function using MessageStatus::ClearMessage and contianer()'s reference as arguments.
- It will return the terminating key
Navigation keys are Up key, Down key, Tab key or Enter key.
MessageStatus is enumerated in confw.h'
Validated Line editor Tester
FWText
The FWText class splits a string of text into series if strings at newline characters, then starts editing them in a text area one string at a time. Each string in this array of strings represents a line in text. The lines can scroll left and right (already implemented in iol_edit) and up and down during the edit if needed. at any time by calling the data() method the array of strings is converted back to a newline separated and null terminated array of characters (Converted back to text) and returned.
class FWText:public FWField{
AnArrayOfStrings _lines; // see below
bool _readOnly;
int _curpos;
int _fieldlen;
int _maxdatalen;
int* _insertmode;
int _offset;
int _lcurpos;
int _loffset;
public:
FWText(int Row, int Col, int Width, int Height, bool Readonly,
int* Insertmode, const char* Border=FW_BORDER_CHARS);
FWText(const char* Str, int Row, int Col, int Width, int Height, bool Readonly,
int* Insertmode, const char* Border=FW_BORDER_CHARS);
void draw(int Refresh = FW_NO_REFRESH)const;
void set(const void *Str);
void *data();
int edit();
bool editable()const;
bool readOnly()const;
void readOnly(bool val);
~FWText();
};
Attributes
AnArrayOfStrings _lines;
Could be one the following:
- A two dimensional array of characters: char _lines[max_number_of_lines][max_number_of_characters_in_line+1];
- In this case you text size is limited to the max_number_of_lines and can not grow more than that.
- A dynamic array of strings: StrArr _lines;
- A Doubly Linked List (Queue) of strings StrQue
If you found any bugs or problems with StrQue or StrArr, do not modify it yourself but instead, please blog about it and send an email to [me] and I will take care of updating it.
You can also find the code for StrQue and it's tester program in class notes repo: (svn://zenit.senecac.on.ca/oop344/trunk/C/13-Nov12).
bool _readOnly;
Keeps the status of the text being read only, or editable. (note that when read only, you can still scroll the text to left and right or up and down, but you can't modify the text).
This flag is passed to iol_edit for the same reason.
int _curpos;
int _fieldlen;
int _maxdatalen;
int* _insertmode;
int _offset;
Variables to be used with iol_edit to edit the lines of text.
int _lcurpos;
Line Cursor Position; this variable keeps track of which line of text the cursor is on. _lcurpos is zero, if the cursor is on the fist line appearing in the Border.
int _loffset;
Offset Of the First Line; this variable keeps track of which line is the first appearing in the border. _loffset is zero, if the first string (line) of the string array is appearing on the fist line of the Border.
_lcurpos and _loffset have the same responsibility as _curpos, and _offset, but only for lines of the text. So as the left and right scrolling is done by manipulating _offset and _curpos, up and down scrolling of lines in the text are done by manipulating _loffset and _lcurpose
Methods
FWText(int Row, int Col, int Width, int Height, bool Readonly,
int* Insertmode, const char* Border=FW_BORDER_CHARS);
Sets all the attributes to their proper/corresponding values
- Note that FWText is always bordered
If dynamic array of strings is used, initial text is allocated and set to an empty text.
FWText(const char* Str, int Row, int Col, int Width, int Height, bool Readonly,
int* Insertmode, const char* Border=FW_BORDER_CHARS);
Works exactly like the previous constructor, but also it will call the set method of FWText to split the incoming text (Str) at newline characters into an array of strings.
void draw(int Refresh = FW_NO_REFRESH)const;
- Calls its parents draw, to draw the border.
- Using iol_display, it prints lines of text from index _loffset, up to height()-2 times.
- Note that each line is printed from _offset character using absRow() and absCol(), up o width()-2 characters
void set(const void *Str);
Converts the newline delimited array of characters (the text) into an array of strings.
Set starts with the first string in the array of strings and copies the characters of the array to the current string until it reaches a newline character.
Then it will null terminate the current string and go to the next string in the array of strings and repeats the same over and over until it reaches the end of the text.
- Note that if FW_MAX_LINE_CHARS is reached before getting to the newline character, the current string is null terminated and copying continues into the next one.
void *data();
Converts the array of strings, back to a single string of text and returns it.
data() first calculates the size of the whole text including the newline characters at the end of each line. Then it will allocated enough memory to hold it all.
Finally, it will concatenate all the strings back into the allocated memory adding a newline character to the end of each of them and returns it.
int edit();
Draws the text area and then starts the editing from the first line.
The whole text should scroll to left, right, up or down instead, if the cursor tries to pass the edges of the text area.
When Enter key is hit, if in insertmode, a new line is inserted after the current line and any text after the cursor in the line should be moved into it.
When Backspace key is hit at the beginning of the line, the content of the current line should be moved to the previous line, the and current line should be deleted. The cursor in this case should stand in front of the copied data.
- Note that this will not happen if the sum of the length of the current and previous lines are more than FW_MAX_LINE_CHARS
bool editable()const;
Always return true.
bool readOnly()const;
void readOnly(bool val);
These two methods Get and Set the _readOnly attribute.
~FWText();
It deallocates the allocated memory. (If any memory allocation is used).
Compile, Build, testing
Compile and build
- Here is a sample of a make file on Linux, you can also find this makefile at svn://zenit.senecac.on.ca/oop344/trunk/C/Prj/makefile
prj: iol.o fwborder.o fwfield.o fwlabel.o fwlineedit.o fwbutton.o fwcheck.o fwveditline.o fwdialog.o fwtext.o strarr.o testmains.o c++ iol.o fwborder.o fwfield.o fwlabel.o fwlineedit.o fwbutton.o fwcheck.o fwveditline.o fwdialog.o fwtext.o strarr.o testmains.o \ -lncurses -oprj iol.o: iol.c iol.h cc -c iol.c fwborder.o: fwborder.cpp fwborder.h confw.hiol.h c++ -c fwborder.cpp fwfield.o: fwfield.cpp fwfield.h fwborder.h confw.h iol.h c++ -c fwfield.cpp fwlabel.o: fwlabel.cpp fwlabel.h fwfield.h fwborder.h confw.h iol.h c++ -c fwlabel.cpp fwlineedit.o: fwlineedit.cpp fwlineedit.h fwfield.h fwborder.h confw.h iol.h c++ -c fwlineedit.cpp fwbutton.o: fwbutton.cpp fwbutton.h fwfield.h fwborder.h confw.h iol.h c++ -c fwbutton.cpp fwcheck.o: fwcheck.cpp fwcheck.h fwlabel.h fwfield.h fwborder.h confw.h iol.h c++ -c fwcheck.cpp fwveditline.o: fwveditline.cpp fwveditline.h fwlineedit.h fwfield.h fwborder.h confw.h iol.h c++ -c fwveditline.cpp fwtext.o: fwtext.cpp fwtext.h fwlineedit.h strarr.h fwfield.h fwborder.h confw.h iol.h c++ -c fwtext.cpp strarr.o: strarr.cpp strarr.h c++ -c strarr.cpp fwdialog.o: fwdialog.cpp fwdialog.h fwfield.h fwborder.h confw.h iol.h c++ -c fwdialog.cpp testmains.o: testmains.cpp fwdialog.h strarr.h fwtext.h fwveditline.h fwcheck.h fwbutton.h fwlineedit.h fwlabel.h fwfield.h fwborder.h iol.h c++ -c testmains.cpp
Testing
- All the test programs are saved at: svn://zenit.senecac.on.ca/oop344/trunk/C/Prj
- Test files names are Test*.cpp
- All test programs are compiled the executable is available on matrix.senecac.on.ca/~fardad.soleimanloo
- to run the test programs, login to matrix.senecac.on.ca and login with your own user id and password, then at the command line type: ~fardad.soleimanloo/tX, replace the X with the number of the test. (i.e for test three, run: ~fardad.soleimanloo/t3)
- Note that you should use Putty to login to matrix and set the keyboard to Xterm 6
Due Date
- Due Nov 29, 23:59
- Tagged prj0.6