Difference between revisions of "Console UI Core Classes - OOP344 20121"

From CDOT Wiki
Jump to: navigation, search
(CDialog)
(R0.2)
Line 45: Line 45:
 
this tester is already in your trunk:<br />
 
this tester is already in your trunk:<br />
 
[svn://zenit.senecac.on.ca/oop344/trunk/cioTesters/Test1Frame.cpp Test1Frame.cpp]
 
[svn://zenit.senecac.on.ca/oop344/trunk/cioTesters/Test1Frame.cpp Test1Frame.cpp]
 +
==R0.2==
 +
Dialog and Labels
 +
===To Do===
 +
Complete the coding of CField, CLabel and CDialog and then test the project using Test2DialogAndLabel.cpp.<br/>
 +
Workload estimate out of 100:
 +
* CLabel  20%
 +
* CDialog  80%
 +
# First start with creating mockup classes (create the classes with empty methods that do nothing but compiles), you should have 6 files for headers and cpp code, and add them to trunk.
 +
# considering the percentage of the workload, assign tasks to each team member.
 +
# Each team member branch the trunk to start their work.
 +
# communicate with your team members and keep updating your code with their additions, (remember that you have access to their branches)
 +
# keep regular IRC meetings ( you can invite me to your meetings too for advice and help)
 +
# When all done, merge back the additions to trunk.
 +
# Do final test and tag it to R0.2
 +
 +
===Due Date===
 +
Friday Feb 24th. 23:59
 +
===Tester===
 +
*[svn://zenit.senecac.on.ca/oop344/trunk/cioTesters/Test2DialogAndLabel.cpp Test2DialogAndLabel.cpp ]
 +
*: on OSX, you can emulate XTerm keyboard settings using [http://iterm.sourceforge.net/ iTerm]/[http://www.iterm2.com/#/section/home ITerm 2]
 +
*: on Matrix, $~fardad.soleimanloo/t2 runs the demo for the test
 +
====Makefile for test 2 on matrix====
 +
*create a file in the root of cio call it '''"makefile"''' and copy the content below:
 +
*: make sure the lines starting with c++ are tabbed once.
 +
*: then at command line issue the command '''"make"''' to complie; the name of the executable will be '''prjexe'''
 +
<big><pre>
 +
t2: console.o cframe.o cfield.o cdialog.o clabel.o Test2DialogAndLabel.o
 +
c++  bconsole.o console.o cframe.o cfield.o cdialog.o clabel.o \
 +
Test2DialogAndLabel.o -lncurses -oprjexe
 +
 +
bconsole.o :bconsole.h bconsole.cpp
 +
c++ -c bconsole.cpp
 +
 +
console.o: console.cpp console.h bconsole.h
 +
c++ -c console.cpp
 +
 +
cframe.o: cframe.cpp cframe.h cuigh.h console.h bconsole.h
 +
c++ -c cframe.cpp
 +
 +
cfield.o: cfield.cpp cfield.h cuigh.h cframe.h console.h bconsole.h
 +
c++ -c cfield.cpp
 +
 +
cdialog.o: cdialog.cpp cdialog.h cfield.h cuigh.h cframe.h console.h bconsole.h
 +
c++ -c cdialog.cpp
 +
 +
clabel.o: clabel.cpp clabel.h cfield.h cframe.h cuigh.h console.h bconsole.h
 +
c++ -c clabel.cpp
 +
 +
Test2DialogAndLabel.o: Test2DialogAndLabel.cpp clabel.h cdialog.h cframe.h cuigh.h cfield.h console.h bconsole.h
 +
c++ -c Test2DialogAndLabel.cpp
 +
</pre></big>
 +
 
==CField==
 
==CField==
 
Note: The code for this class is provided. You must understand and use it to develop your core classes.
 
Note: The code for this class is provided. You must understand and use it to develop your core classes.

Revision as of 16:01, 15 February 2012

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

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.

Student Resources

Help/Question

  • N/A

Releases and Due Dates

R0.1

To Do

checkout your repository using userids and passwords received through your learn.senecac.on.ca email
Note that the trunk holds several files that are the base of your project.
Then in the Checked out directory:

  1. Create a directory in branches. Name of this directory must be your seneca email id (NOT YOUR WHOLE EMAIL ADDRESS, ONLY THE ID) (done in lab)
    From now on, this directory will be called Your Workspace
  2. In your workspace create a direcotry called console and add the files you submitted for your console assignment to it. (done in lab)
  3. using svn command, add, add all the newly created directories and their files to svn (done in lab)
  4. commit the repository with the message (comment) "Initial branch creation" (done in lab)
  5. After doing this with all your team members present (Online or face to face), Browse your Console code as a group and choose the best version from them and manually copy and add it to trunk
    Any of the group members can do this, but it would be nice if you do this when everyone is present (only one copy of console.cpp and console.h should get copied in trunk)
  6. If further changes to console.cpp or console.h are needed, apply them too
  7. Compile your code with Test1Frame.cpp and make sure it works properly
  8. After fixing possible bugs recompile and make sure everything is ok and runs properly
  9. tag the trunk under R0.1 in tags directory

Due Date

Fri Feb 17, 11:59

Exercise

To prepare and learn how to contribute and also gain mark for your next release do the following exercise.

Tester

this tester is already in your trunk:
Test1Frame.cpp

R0.2

Dialog and Labels

To Do

Complete the coding of CField, CLabel and CDialog and then test the project using Test2DialogAndLabel.cpp.
Workload estimate out of 100:

  • CLabel 20%
  • CDialog 80%
  1. First start with creating mockup classes (create the classes with empty methods that do nothing but compiles), you should have 6 files for headers and cpp code, and add them to trunk.
  2. considering the percentage of the workload, assign tasks to each team member.
  3. Each team member branch the trunk to start their work.
  4. communicate with your team members and keep updating your code with their additions, (remember that you have access to their branches)
  5. keep regular IRC meetings ( you can invite me to your meetings too for advice and help)
  6. When all done, merge back the additions to trunk.
  7. Do final test and tag it to R0.2

Due Date

Friday Feb 24th. 23:59

Tester

Makefile for test 2 on matrix

  • create a file in the root of cio call it "makefile" and copy the content below:
    make sure the lines starting with c++ are tabbed once.
    then at command line issue the command "make" to complie; the name of the executable will be prjexe
t2: console.o cframe.o cfield.o cdialog.o clabel.o Test2DialogAndLabel.o
	c++  bconsole.o console.o cframe.o cfield.o cdialog.o clabel.o \
Test2DialogAndLabel.o -lncurses -oprjexe

bconsole.o :bconsole.h bconsole.cpp
	c++ -c bconsole.cpp

console.o: console.cpp console.h bconsole.h
	c++ -c console.cpp

cframe.o: cframe.cpp cframe.h cuigh.h console.h bconsole.h
	c++ -c cframe.cpp

cfield.o: cfield.cpp cfield.h cuigh.h cframe.h console.h bconsole.h
	c++ -c cfield.cpp

cdialog.o: cdialog.cpp cdialog.h cfield.h cuigh.h cframe.h console.h bconsole.h
	c++ -c cdialog.cpp

clabel.o: clabel.cpp clabel.h cfield.h cframe.h cuigh.h console.h bconsole.h
	c++ -c clabel.cpp

Test2DialogAndLabel.o: Test2DialogAndLabel.cpp clabel.h cdialog.h cframe.h cuigh.h cfield.h console.h bconsole.h
	c++ -c Test2DialogAndLabel.cpp

CField

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

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();
 
  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 constructor and then sets the _data attribute to the incoming Data argument.

  ~CField();

Empty Destructor

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

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

Returns _data.

  void container(CDialog* theContainer);
  CDialog* container();

Sets and Gets the _frame attribute of CFrame by calling CFrame::frame() method. Make sure to cast The CDialog to CFrame when setting and cast CFrame to CDialog when getting!

CLabel

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

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

 public:
   CLabel(const CLabel& L);
   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 in a string. In any way, the allocated memory is pointed by _data

   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 _length is greater than zero, it will copy the string pointed by str into the string pointed by _data upto _length characters. if _length is zero,
It will delete the memory pointed by _data and reallocates enough memory for str and copies the string pointed by str into the newly allocated memory pointed by _data.

CDialog

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

#include "cuigh.h"
#include "cframe.h"
namespace cio{
  class CField;
  class CDialog: public CFrame{
    private:
    int _fnum;
    int _curidx;
    CField* _fld[C_MAX_NO_FIELDS];
    bool _dyn[C_MAX_NO_FIELDS];
    bool _editable;
    public:
    CDialog(CFrame *Container = (CFrame*)0,
             int Row = -1, int Col = -1, 
             int Width = -1, int Height = -1, 
             bool Borderd = false,
             const char* Border=C_BORDER_CHARS);
    virtual ~CDialog();
    void draw(int fn = C_FULL_FRAME);
    int edit(int fn = C_FULL_FRAME);

    int add(CField* field, bool dynamic = true);
    int add(CField& field, bool dynamic = false);
    CDialog& operator<<(CField* field);
    CDialog& operator<<(CField& field);

    bool editable();
    int fieldNum()const;
    int curIndex()const;

    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[C_MAX_NO_FIELDS];

Array of CField pointers to hold the address of the CField objects added to the screen. The maximum number of CFields that can be added to this CDialog is C_MAX_NO_FIELDS. Remove this restriction for additional mark.

  bool _dyn[C_MAX_NO_FIELDS];

Holds series of boolean 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. This array will later on be used by destructor to decide which object is dynamic and to be deleted.

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 called a 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 not C_FULL_FRAME, 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);

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 it 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

  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.