Open main menu

CDOT Wiki β

The CIO Framework - OOP344 20131

Revision as of 21:41, 4 March 2013 by Chun Chen (talk | contribs) (CLineEdit Help/Questions Blogs)


OOP344 | Weekly Schedule | Student List | Teams | Project | Student Resources
Under construction!

Objective

Your objective at this stage is to create series of core classes designed to interact with the user. These Core Classes then can be used in development of any interactive application.

Please note that the class definitions here are minimum requirement for the Core Classes and you are free to add any enhancements or features you find useful. However make sure that you discuss these enhancements with your team and professor to make sure they are feasible before implementation.

It is highly recommended to develop the classes in the order they are stated here. You must create your own tester programs for each class (if possible); However, close to due date of each release, a tester program may be provided to help you verify the functionality of your classes. If tester programs are provided, then executables of the test programs will be available on matrix to show you how it is supposed to run.

Tips

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 header-file.
  • Use includes only in files in which the actual header file code is used.
  • Avoid "just in case" includes.

CUI General Header file (cuigh.h)

The general header file holds the common setting and definition between all the Core Classes. Review this header file at each stage of the project for changes.

#ifndef ___CUIGH_H__
#define ___CUIGH_H__
namespace cio{ 
  #ifndef _CRT_SECURE_NO_DEPRECATE
  #define _CRT_SECURE_NO_DEPRECATE
  #endif
  #ifndef _CRT_SECURE_NO_WARNINGS
  #define _CRT_SECURE_NO_WARNINGS
  #endif
 
  #define C_INITIAL_NO_FIELDS 50
  #define C_DIALOG_EXPANSION_SIZE 20
  #define C_BUTTON_HIT 1
  #define C_MAX_LINE_CHARS  (1024u)

  #define C_REFRESH -2
  #define C_FULL_FRAME -1
  #define C_NO_FRAME 0

  #define C_BORDER_CHARS  "/-\\|/-\\|"
  enum CDirection {centre, left, right, up, down};

}
#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 CFrame class should have cframe.h and cframe.cpp files for its implementation.

Hierarchy

CFrame
 |
 |---CDialog
 |
 |
 |---CField
       |
       |-------- CLabel
       |
       |
       |-------- CButton
       |
       |
       |-------- CLineEdit
       |         |
       |         |-------CValEdit
       |
       |-------- CText
       |
       |
       |-------- CCheckMark
       |
       |
       |-------- CCheckList 
       |
       |
       |-------- CMenuItem  
       |
       |
       |-------- CMenu 

Issues, Releases and Due Dates

  • Issue Name Format
    Issue and branch name format:

V.V_Name
example; issue: Add Text Class to the project (issue 2.9.1) issue and branch name on gitub: 2.9.1_AddTextClass

0.2 Milestone

  1. Add Console Class to the repo and test it with cio_test.cpp and Test1Frame.cpp.
  2. Create Mock-up classes
    1. CLabel Mock-up Class (issue 2.2)
    2. CDialog Mock-up Class (issue 2.3)
    3. CLineEdit Mock-up Class (issue 2.4)
    4. CButton Mock-up Class (issue 2.5)

Details

0.2 milestone details

Due Date

Thursday Feb, 14th, 23:59

0.3 Milestone

  1. Apply changes to CDialog, cuigh.h and update and test your related mock-ups. (issue 3.1)
  2. CLabel Implementation (issue 3.2)
  3. CDialog Implementation (issue 3.3)
  4. CLineEdit Implementation (issue 3.4)
  5. CButton Implementation (issue 3.5)

Details

Due Date

Wednesday March, 6th, 23:59

CFrame

The code for this class is provided in your repository. You must understand and use it to develop your core classes in your repository.

CFrame class is responsible to create a frame or structure in which all user interface classes contain themselves in. It can draw a border around it self or be border-less. CFrame also, before displaying itself on the screen, will save the area it is about to cover, so it can redisplay them to hide itself.

CFrame is base of all objects in our user interface system.

#include "cuigh.h"

class CFrame{
  int _row;      // relative row of left top corner to the container frame or the screen if _frame is null
  int _col;      // relative col of left top corner to the container frame or the screen if _frame is null
  int _height;   
  int _width;
  char _border[9];  // border characters
  bool _visible;    // is bordered or not
  CFrame* _frame;   // pointer to the container of the frame (the frame, surrounding this frame)
  char* _covered;   // pointer to the characters of the screen which are covered by this frame, when displayed
  void capture();   // captures and saves the characters in the area covered by this frame when displayed and sets 
                    // _covered to point to it
  void free();      // deletes dynamic memory in the _covered pointer
protected:
  int absRow()const;    
  int absCol()const;    
public:
  CFrame(int Row=-1, int Col=-1, int Width=-1,int Height=-1,
    bool Visible = false,
    const char* Border=C_BORDER_CHARS,
    CFrame* Frame = (CFrame*)0);
  
  virtual void draw(int fn=C_FULL_FRAME);
  virtual void move(CDirection dir);
  virtual void move();
  virtual void hide();

  virtual ~CFrame();
  
  /* setters and getters: */

  bool fullscreen()const;

  void visible(bool val);
  bool visible()const;

  void frame(CFrame* theContainer);
  CFrame* frame();
  
  void row(int val);
  int row()const;

  void col(int val);
  int col()const;

  void height(int val);
  int height()const;

  void width(int val);
  int width()const;

  void refresh();
};

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.
CFrame* _frame; holds the container (another CFrame) which has opened this one (owner or container of the current CFrame). _frame will be NULL if this CFrame 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, CFrame will be Full Screen (no border will be drawn)
char* _covered; is a pointer to a character array that hold what was under this frame before being drawn. When the CFrame wants to hide itself, it simple copies the content of this array back on the screen on its own coordinates.

Methods and Constructors

Private Methods

void capture();
if _covered pointer is not pointing to any allocated memory, it will call the iol_capture function to capture the area that is going to be covered by this frame and keeps its address in _covered.

Protected Methods

  • int absRow()const; calculates the absolute row (relative to the left top corner of the screen) and returns it.
    it returns the sum of row() of this border plus all the row()s of the _frames
  • int absCol()const; calculates the absolute column(relative to the left top corner of the screen) and returns it.
    it returns the sum of col() of this border plus all the col()s of the _frames

Public Methods

  CFrame(int Row=-1, int Col=-1, int Width=-1,int Height=-1,
    bool Visible = false,
    const char* Border=C_BORDER_CHARS,
    CFrame* Frame = (CFrame*)0);
Sets the corresponding attributes to the incoming values in the argument list and set _covered to null
  virtual void draw(int fn=C_FULL_FRAME);
  • First it will capture() the coordinates it is supposed to cover
  • If frame is fullscreen() then it just clears the screen and exits.

Otherwise:

  • 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.


  virtual void move(CDirection dir);

First it will hide the Frame, then adjust the row and col to move to the "dir" direction and then draws the Frame back on screen.

  virtual void hide();

using iol_restore()it restores the characters behind the Frame back on screen. It will also free the memory pointed by _covered;

  virtual ~CFrame();

It will make sure allocated memories are freed.

  bool fullscreen()const;
  void visible(bool val);
  bool visible()const;
  void frame(CFrame* theContainer);
  CFrame* frame();
  void row(int val);
  int row()const;
  void col(int val);
  int col()const;
  void height(int val);
  int height()const;
  void width(int val);
  int width()const;

These functions set and get the attributes of the CFrame.

CFrame Student Resources

CFrame Help/Questions Blogs

CFrame Blog Posts

CField

CField is an abstract base class that encapsulates the commonalities of all Input Outputs Console Fields which are placeable on a CDialog. All Fields could be Framed, therefore a CField is inherited from CFrame.

#include "cframe.h"
class CDialog;
class CField : public CFrame{
protected:
  void* _data;
public:
  CField(int Row = 0, int Col = 0,
         int Width = 0, int Height =0,
         void* Data = (void*) 0,
         bool Bordered = false,
         const char* Border=C_BORDER_CHARS);
  ~CField();
  virtual int edit() = 0;
  virtual bool editable() const = 0;
 
 
  virtual void set(const void* data) = 0;
  virtual void* data()const;    //<== check this, not sure
  
  void container(CDialog* theContainer);
  CDialog* container();
};

Attributes

  void* _data;

Will hold the address of any type of data a CField can hold.

Constructors and Methods

  CField(int Row = 0, int Col = 0,
         int Width = 0, int Height =0,
         void* Data = (void*) 0,
         bool Bordered = false,
         const char* Border=C_BORDER_CHARS);

Passes the corresponding attributes to it's parents (CFrame) constructor and then sets the _data attribute to the incoming Data argument. Also using container(CDialog* theContainer) it set the container to NULL.

  ~CField();

Empty Destructor

  virtual int edit() = 0;
  virtual bool editable() const = 0;
  virtual void set(const void* data) = 0;

Pure virtual methods to enforce the children to implement;

  • an edit() method
  • an editable() method that returns true if the class is to edit data and false if the class is to only display data.
  • a set() method to set the _data attribute to the data the class is to work with.
  virtual void* data() const;  <--- Check this not sure....

Returns _data.

  void container(CDialog* theContainer);

Casts "theContainer" to a CFrame pointer and passes it to CFrame::frame(CFrame*) method; (to set the frame of CDialog)

  CDialog* container();

Casts the return value of CFrame::frame() to a CDialog pointer and returns it.

CField Student Resources

CField Help/Questions Blogs

CField Blog Posts

CLabel

A readonly Field that encapsulates console.display() function. (i.e it is responsible to display a short character string on the display) CLabel although, by inheritance is Frame, but it is never bordered.

#include "cfield.h"
class CLabel :  public CField{
   // for length of the field:
   //  Use void CFrame::width(int) to store length, and int CFrame::width() to retrieve the length

 public:
   CLabel(const CLabel& L);
   CLabel(const char *Str, int Row, int Col,
     int Len = 0);
   CLabel(int Row, int Col, int Len);
   ~CLabel();
   void draw(int fn=C_NO_FRAME) ;
   int edit();
   bool editable()const;
   void set(const void* str);
};

Attributes

No attributes, (use Cframe attributes)

Constructors / Destructor

   CLabel(const char *Str, int Row, int Col,
     int Len = 0);

passes the Row and Col to the CField constructor and then; if len is zero, it will allocate enough memory to store the string pointed by Str and then copies the Str into it. if len > 0, then it will allocate enough memory to store len chars, copying only len characters of str. In any way, the allocated memory is pointed by _data. Also it will set the width to the length of the memory allocated.

   CLabel(int Row, int Col, int Len);

Works exactly like the previous constructor, but len in this case can not be zero. (no validation required) and the string pointed by _data will be set to an empty string.

   CLabel(const CLabel& L);

Copies a CLabel safely to guaranty there is no memory leak.

   ~CLabel();

makes sure that memory pointed by _data is deallocated before the object is destroyed.

Methods

   void draw(int fn=C_NO_FRAME) ;

makes a direct call to console.display(), passing _data for the string to be printed and absRow() and absCol() for row and col and _length for len. this function ignores the argument fn.

   int edit();

calls draw, returning 0.

   bool editable()const;

always return false.

   void set(const void* str);

if width() is greater than zero, it will copy the string pointed by str into the string pointed by _data upto width characters. if width() is zero,
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.

CLabel Student Resources

CLabel Help/Questions Blogs

CLabel Blog Posts

CDialog

Organizes CField objects on the screen, displays them and then lets the user edit them one by one.

#include "cuigh.h"
#include "cframe.h"
namespace cio{
  class CField;
  class CDialog: public CFrame{
    private:
    int _fnum;
    int _curidx;
    CField** _fld;
    bool* _dyn;
    bool _editable;
    unsigned int _fldSize;
    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;

    CField& operator[](unsigned int index);
    CField& curField();
  };
}

Attributes

  int _fnum;

Holds the number of Fields added to the Dialog

  bool _editable;

will be set to true if any of the Fields added are editable. This is optional because it depends on how you are going to implement the collection of CFields:

  int _curidx;

Holds the index of the Field that is currently being edited.

  CField** _fld;

Dynamic array of CField pointers to hold the address of the CField objects added to the screen. The initial size of the array allocation is defined in cuigh.h under C_INITIAL_NO_FIELDS.

  bool* _dyn;

A dynamic bool array that holds series of booleans to the exact number of fields, and each boolean here will hold false if the corresponding field pointed by _fld is allocated dynamically or not. The initial size of the array allocation is defined in cuigh.h under C_INITIAL_NO_FIELDS.
This array will later on be used by destructor to decide which object is dynamic and to be deleted.

  unsigned int _fldSize;

Holds the current length of _fld and _dyn.
When adding a field to dialog if _fum reaches _fldSize, then the size of _fld and _dyn is expanded by C_DIALOG_EXPANSION_SIZE, defined in cuigh.h

Constructors/Destructors

  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);

The constructor passes all the incoming arguments to the corresponding arguments of the apparent constructor CFrame.
Then it will set all called attributes to their default values and then sets all the field pointers (_fld) to NULL. It also sets all the dynamic (_dyn) flags to false.

  virtual ~CDialog();

The destructor will loop through all the field pointers and if the corresponding dynamic flag is true then it will delete the field pointed to by the field pointer.

Methods

  void draw(int fn = C_FULL_FRAME);

If fn is C_FULL_FRAME, it will call its parent draw. Then It will draw all the Fields in the Dialog.
If fn is Zero, 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 = C_FULL_FRAME);

If CDialog 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:

  1. 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.
  2. 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.
  3. For any other key, terminate the edit function returning the character which caused the termination.
  int add(CField* field, bool dynamic = true);

First, this function will check the value of _fnum. If _fnum has reached _fldSize, (_fld and _dyn arrays are full) it will expand _fld and _dyn by C_DIALOG_EXPANSION_SIZE (defined in cuigh.h) to make room for more CField.
Then, it adds the CField pointed by field to the Fields of the Dialog; by appending the value of the field pointer after the last added field in the _fld array , setting the corresponding _dyn element to the value of dynamic argument and then increasing _fnum by one and returning the index of added Field in the CDialog object.
important note:
Make sure that add() sets the container of the added CField to this CDialog object, using the container() method of CField
Also make sure, if size of _fld and _dyn are expanded, then _fldSize is also increased.

  int add(CField& field, bool dynamic = false);

Makes a direct call to the first add method.

  CDialog& operator<<(CField* field);

Makes a direct call to the first add method, ignoring the second argument and then returns the owner (current CDialog).

  CDialog& operator<<(CField& field);

Makes a direct call to the second add method, ignoring the second argument and then returns the owner (current CDialog).

  bool editable();

Returns _editable;

  int fieldNum()const;

returns _fnum.

  int curIndex()const;

returns _curidx;

  CField& operator[](unsigned int index);

Returns the reference of the Field with incoming index. (Note that here, the first field index is 0)

  CField& curField();

Returns the reference of the Field that was just being edited.

CDialog Student Resources

CDialog Help/Questions Blogs

CDialog Blog Posts

CLineEdit

ClineEdit encapsulates the console.edit() function of Console class.

#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;

    void  set(const void* Str);
  };
}

Attributes

  bool _dyn;

_dyn is set to true if the object dynamically allocated memory and is responsible to free it at destruction time.

  int _maxdatalen;

no comment!

  bool* _insertmode;

points to the location of input method (insert or overstrike)

  int _curpos;

current position of cursor

  int _offset;

current offset

Constructors / Destructor

  CLineEdit(char* Str, int Row, int Col, int Width,
    int Maxdatalen, int* Insertmode, 
    bool Bordered = false,
          const char* Border=C_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 (CField) 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 Height value to CField's constructor)

  CLineEdit(int Row, int Col, int Width,
    int Maxdatalen, int* Insertmode, 
    bool Bordered = false,
          const char* Border=C_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.

  ~CLineEdit();

If _dyn is true, it will deallocate the character array pointed by Fields's _data

Methods

  void draw(int Refresh = C_FULL_FRAME);

It will first call Frame's draw passing Refresh as an argument to it.
Then it will make a direct call to console.display() to show the data kept in Field's _data.
The values used for the arguments of console.display() are:

  • str: address of string pointed by _data + the value of _offset
  • row: absRow() (add one if border is visible)
  • col: absCol() (add one if border is visible)
  • len: width() (reduce by two if border is visible')
  int edit();

Makes a direct call to, and returns console.edit(). For the coordinates and width arguments follow the same rules as the draw function. For the rest of the arguments of console.edit(), use the attributes of CLineEdit.

  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.

CLineEdit Student Resources

CLineEdit Help/Questions Blogs

  • Does anyone know that what value I have to assign to _offset and _curpos for CLineEdit attribute since there is no value passed by the constructor? Chun Chen

CLineEdit Blog Posts

CButton

Button is a child of CField. 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.

#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 rn=C_FULL_FRAME);
     int edit();
     bool editable()const;
     void set(const void* str);
   };
}

Attributes

This class does not have any attributes of its own!

Constructor / Destructor

   CButton(const char *Str, int Row, int Col, 
            bool Bordered = true,
            const char* Border=C_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.

   virtual ~CButton();

Deallocates the allocated memory pointed by Field's _data.

Methods

   void draw(int fn=C_FULL_FRAME);

Draws the Button with border around it if it is Bordered. Note that there should be a space before and after of the text that will be used to surround the text with "[" and "]"
hint:

  • First calls Frame's draw(fn) (passing the fn argument to the parents draw)
Use console.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 C_BUTTON_HIT (defined in cuigh.h) otherwise return the entered key.

   void set(const void* 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.

   bool editable()const;

Always returns true

CButton Student Resources

CButton Help/Questions Blogs

CButton Blog Posts