BREW Scheduler Supporting vCalendar Appendix- 7 / 7 -
Note
The BREW Scheduler Supporting vCalendar application goes through the fundamentals of programming a scheduler with SophiaFramework UNIVERSE. and also demonstrates how to use the TemplateApp class as base for more sophisticated applications.
* This appendix assumes readers have already gone through both the HelloWorld and Cartoon tutorials.
SyncScheduler Class Overview
SyncScheduler Header File
SyncScheduler is an SFRApplication, meaning it uses the GUI Framework; it also inherits the VCalendar class.
It creates a single instance of VcalCollection which can be accessed anywhere in the application thanks to the VCalCollectionPtr GetVCalCollection() function.
The rest of the header file is simply the code from the TemplateApp.hpp file with no modifications.
* The TemplateApp class declares standard functions to calculate coordinates for UI components, to open/close those components and event handlers to act upon those them.
SyncScheduler Constructor
The SyncScheduler constructor uses the code of the TemplateApp constructor with only minor modifications.
The class name TemplateApp is replaced with the name SyncScheduler, and a line of code is added to read the index file data into VCalCollection. The standard TemplateApp constructor code registers all the event handlers and creates the SoftkeyWindow along with the MainWindow.
SyncScheduler Event Handlers
The first four event handlers of the SyncScheduler class have no code defining their behavior since no special instructions need be performed to handle APP_START, APP_STOP, APP_RESUME or APP_SUSPEND.
OnSoftkeySHP() handles a "Soft Key 2" event by invoking a menu event that is handled by the OpenStandardMenu() function.
Calculation of UI Component Position
The TemplateApp class defines three standard SFXRectangle functions to calculate the positions of windows ( CalculateWindowPosition() ), dialogs ( CalculateDialogPosition() ) and menus ( CalculateMenuPosition() ).
These functions modify SFXRectangle objects through various SFXRectangle functions ( GetContentWorld(), SetSize(), Offset(), Inflate(), etc ) and return a rectangle with the desired dimensions and coordinates.
Open/Close Dialogs
The TemplateApp class defines functions to open/close standard and custom dialogs.
The OpenDialog() function uses exception handling to check if the dialog is valid, and registers an event handler ( procedure ), to handle dialog events.
If it is a standard dialog, the SoftkeyWindow's Initialize function is used to initialize the dialog, register it to the SoftkeyWindow, set its labels and bind it to the SoftkeyWindow through the Bind() function.
The standard dialog is closed by calling the SoftkeyWindow's Terminate() function and the DialogHandler(). A custom dialog also has a handler registered to it ( procedure ), but its implementation is left to the developer.
The custom dialog is closed by calling the DialogHandler().
Open/Close Standard Menu
The OpenStandardMenu() function works in much the same way as the OpenStandardDialog() function.
It registers handlers for both menu events ( procedure ) and soft key events ( OnSoftkeySHP ), and initializes the menu with the SoftkeyWindow's Initialize() function. The menu's soft keys are registered, their labels set and it is bound to the SoftkeyWindow.
The CloseStandardMenu() function terminates the standard menu by calling the SoftkeyWindow's Terminate() function and the MenuHandler().
Get VCalCollection
The GetVCalCollection function returns a reference to an instance of VCalCollection.
MainWindow Class Overview
MainWindow Header File
The MainWindow header file keeps the code from TemplateApp's MainWindow, but adds to it variables to keep track of cursor position ( SFXDate _cursor ), the width and height of a single box cell ( SInt16 _boxSizeX, _boxSizeY ), a variable to keep track of the left end of the calendar ( _callLeft ), and a variable to save each day's backgroundcolor ( _DayBackGroundColor ).
Two additional variables are declared to represent the total number of displayed schedules for the current day ( _totalshow ) and for the deciding the colors of the schedule arrows ( _showcursor ).
The drawing ( OnRenderContent ) and Key ( OnKey ) handlers are declared on top of the standard TemplateApp handlers. And four functions that encapsulate the calendar drawing procedures are declared.
MainWindow Constructor
The MainWindow constructor adds code to register the drawing and key handlers, on top of registering the standard handlers.
It also initializes the _boxSize, _calLeft, _cursor and the _showcursor member variables.
The Drawing Handler
-
OnRenderContent gets the attributes of the current cursor position through the SFXDate GetYear(), GetMonth() and GetDay() functions. It also obtains the current date through the SFXDate CurrentDate() function and saves it in _current.
The frame of the calendar is drawn by the DrawCalendarLine() function, which receives as its arguments the dimensions of the screen rectangle and a graphics object.
The year and the month are drawn at the top right corner of the page and are formatted by the SFXAnsiString Format() function. The date can be displayed as month/day/year or day/month/year depending on the value of the mdyStyle variable set in the PreferenceDialog. Switch statements are used to obtain the word name of each month and to add the proper postfix to the day number.
An abbreviation for each day of the week is drawn by the DrawDaysOfWeek() function, which also has the screen dimensions and a graphics object as parameters. Each individual day's date and the cursor position are drawn by the DrawDate() function, which adds the parameter _current on top of the screen dimensions and graphics object.
If any schedules exists within VCalCollection for the given day, they are drawn in the lower portion of the screen by the DrawContent() function.
Drawing Calendar Frame
DrawCalendarFrame() first sets the SFXLine variables varLine and holLine. These two variables are then used to draw the calendar's columns and rows through loops.
The lines are actually drawn using the SFXGraphics DrawLine() function and are translated to the next column/row by the SFXLine Offset() function.
Drawing the Days of the Week
The DrawDayOfWeek() function declares an ACharConst array youbi to save an abbreviation for each day of the week starting with Sunday.
The SFXRectangle calRect is initialized to the coordinates of the top left cell in the calendar, and with dimensions _boxSize. A loop is used to draw the rectangle for each day with its background color, the day abbreviation and shift calRect to the next cell.
Drawing the Date Portion of the Calendar
The DrawDate() function, creates an SFXDate variable tempDate that is to be used for drawing procedures.
tempDate is set to _cursor, in order to obtain the current month, and its day field is set to the first day of the month.
The day of the week is saved in the SInt16 dayOfWeek variable, after being obtained by the SFXDate GetDayOfWeek() function and adjusted.
The SFXRectangle calRect used for drawing is set to the position of the leftmost day on the second line of the calendar and the current day's attributes are obtained.
The last day of the current month is determined by subtracting one day ( SubDay() ) from the first day of the next month, and checking the value with the GetDay() function.
A for-loop is used to draw all the days of the month. If the loop index corresponds to the current day, then that cell is filled with the color that represents the current day, and if the index corresponds to the day the cursor points to, then that cell is filled with a specific color.
If the current day has a schedule ( GetVCalCollection()->IsDataExist() ), then it is marked in the top left corner of the cell.
The day of the month number is drawn with the DrawText() function. If the current index corresponds to the end of the week, then calRect is moved six _boxSize spaces to the left and one _boxSize down, which brings it to the first day of the following week. Else calRect is moved one _boxSize to the right, meaning the next day.
Drawing the Schedule Part of the Calendar
If the current day has schedules, the VCalCollection is obtained through the GetVCalCollection function.
A rectangle used to display the schedule, calRect, is prepared. The current day's index within the VCalCollection is obtained through the VCalCollection GetIndex() function, and the number of schedules for that day are obtained through the GetNumberOfVCal() function.
Two scroll arrows ( arrowup and arrowdown ) are created and can be drawn with one of two possible colors. One color corresponding to red indicates an arrow that can be clicked, the other corresponding to grey indicates an arrow that cannot be clicked.
A loop is used to draw each one of the day's schedules temporarily saved in the SFXAnsiString bottomString. bottomString displays the schedule number, the time, and the summary for each schedule in a specific format. The schedule time ( date ) is obtained through the GetStartDate() function and displayed in standard time format.
The schedules are drawn in such a way that only the first two schedules will initially be visible, and the user will have to scroll down to see any additional schedules.
Key Handler
The key handler OnKey handles mainly directional key events. A "Left" or "Right" key press respectively subtracts or adds a day to the _cursor value.
While an "Up" or "Down" key press respectively subtracts or adds seven days to the _cursor value ( representing the following week ).
Pressing the "Select" key creates a new OneDayWindow
The "2" key and the "8" key respectively scroll the current day's schedules up and down.
TemplateApp Handlers
-
The rest of the MainWindow.cpp file defines handlers for the soft keys and their options. These handlers are unchanged from the TemplateApp application, so we will only go over them broadly.
The first handler is for the soft keys themselves OnSoftkey. If "Soft Key 1" is pressed, a new SFRMultiDialog dialog is created displaying the string "Are You Done". This dialog has "Cancel" or "Ok" options, and is opened through the SyncScheduler OpenStandardDialog() function.
The handler function FromSoftKey1 is registered to handle this dialog's events.
If "Soft Key 2" is pressed, a new SFRTextMenu is created and two options are added to it using the AppenItem() function, "Environmental Settings" and "Version".
The SyncScheduler OpenStandardMenu() function is used to open the menu, and the handler function FromSoftkey2 is registered to it.
FromSoftkey1 handles 3 different kind of events. If the "Ok" button is pressed, the CloseStandardDialog() function of the SyncScheduler class is called to close the dialog, and the SFRApplication Terminate() function terminates the application. A "Cancel" button press, or pressing the "clear" key, both call the CloseStandardDialog() function.
FromSoftkey2 handles four events. If the "Preferences" option is selected, a new PreferenceDialog is created, and the handler function FromPreference is registered to it.
While the "Version" option creates a new VersionDialog and registers the handler function FromVersion to it. Both a "Cancel" key press and a "Clear" key press are handled by calling the CloseStandardMenu() function.
FromPreference and FromVersion handle all events the same way, by calling the CloseCustomDialog() and CloseCustomMenu() functions.
PreferenceDialog Class Overview
-
The PreferenceDialog header starts off with the TemplateApp application code, but adds to it four SFRRadiobuttonControlPtrs, and handler functions for the "OK" button, the "Cancel" button and the Softkey 1 "Finish" option.
It uses the SFRPlainDialog constructor to create a plain dialog with PlainDialog behavior and attributes. Then initializes the soft keys by calling the SoftkeyWindow's Initialize() function.
Assuming no errors have occurred, a new SFRTabControl tab is created along with a new SFRTabPane pane. The three soft keys are registered, labeled and bound.
The PreferenceDialog destructor calls the terminate function of the SoftKeyWindow to end the PreferenceDialog.
The soft key handler, OnSoftkey, handles a "Soft Key 1" event by creating the same "Are you done?" SFRMultiDialog as all the other windows. A "Soft Key 2" event is handled by invoking the equivalent "Ok" dialog event.
The OnButtonControlOK handler updates SyncScheduler's OPTION_LONGDATE and OPTION_MDY variables with the values of the _radioLongdate and _radioMDY controls. It then closes the PreferenceDialog by invoking an SREVT_RESPONDER_TERMINATE event.
OnButtonControlCancel simply terminates the PreferenceDialog by invoking an SREVT_RESPONDER_TERMINATE event.
VersionDialog Class Overview
The VersionDialog source code is very similar to that of the PreferenceDialog.
-
After calling the SFRTitleDialog constructor, it sets the soft keys by calling the SoftkeyWindow's Initialize() function.
A drawing handler is registered ( OnRender ), and an instance of the SFBShell is obtained to call the LoadResImage() function. A rectangle with the desired dimensions and the coordinates of the "Ok" button SFRButtonControl are prepared and used within the constructor.
A handler for the "Ok" button, OnOk, is registered and the button's focus is set.
"Soft Key 3" is registered, labeled and bound. The VersionDialog destructor calls the terminate() function of the SoftKeyWindow to end the version dialog.
The drawing handler OnRender calls the SFRTitleDialog's ContentHandler to update the contents area. It then modifies the SFXRectangle rect to accommodate the button at the bottom of the image. And once _image's attributes have been obtained through the GetInfo() function and saved in the AEEImageInfo variable info, the SFXGraphics DrawImage() function is used to draw the image.
The "Ok" button handler OnOk, handles an Ok button press by invoking the equivalent Ok event.
SoftkeyWindow Class Overview
The SoftkeyWindow class in its entirety is exactly the same as the SoftkeyWindow class found in the TemplateApp application. Therefore, this overview will be brief and will not go into unnecessary detail.
SoftkeyWindow Header File
SoftkeyWindow.hpp starts off by declaring two enum types, one for a user's soft key event, and one to represent each soft key.
A struct itemRec is declared to hold attributes relating to a soft key. An SFXList variable cast as an ItemRecPtr _item and an SFXResponderPtr _bind are declared to manage ItemRec objects.
A number of public functions are declared to Bind(), Register(), Unregister(), Initialize() and Terminate() the SoftkeyWindow.
A drawing and key handler, as well as DrawButton() and Find() function are declared as private.
SoftkeyWindow Constructor
The SoftkeyWindow constructor sets up an SFXRectangle with the dimensions of the bottom portion of the screen and sets its color.
SoftkeyWindow Bind
The Bind() function makes the SFRResponderPtr _bind point to the responder it has as its argument.
SoftkeyWindow Register and Unregister
The Register() function accepts a reference to a responder which is to be registered. It also receives an SoftkeyEnum index parameter used to identofy the softkey.
If this index parameter is valid, and assuming the reference to the responder is valid, the softkey's label is set and it is enabled.
If the reference to the responder is not valid, then index is set to a new ItemRec object, all its possible soft keys are given blank labels and are disabled. Following this, the particular softkey corresponding to the index that was passed in the argument has its label set and is enabled.
The Unregister() bassically undoes what the Register() function did. It calls the function Remove() upon all the responders that were registered and then deletes them. It then sets the responder pointer _bind to NULL.
SoftkeyWindow Event Handlers
Drawing Handler
After calling the Find() function to search for the item that is to be drawn, OnRender sets up an SFXRectangle rect with the dimensions of a softkey "button". Then depending on which softkey it is, rect is shifted by a given amount and drawn with the proper label.
If the item was found, then the proper USEREVT_SOFTKEY event is invoked depending on which softkey was pressed.
OnSoftkey
OnSoftkey gets a reference to the front responder, and if the event was not a combo-box menu event, it attempts to find an item in this responder.
OneDayWindow Class Overview
OneDayWindow Header File
The OneDayWindow header file declares three SInt16 variables to manage the cursor and displayed lines ( _displine, _cursor and _maxline ).
Two SInt32 variables ( _index and _number ) along with an SFXDate variable ( _date ) are declared to manage VCalendar information.
The rest of the file declares constructors, destructors, drawing and key handlers. It registers the soft keys, and binds them to the OneDayWindow.
OneDayWindow Constructor
A plain window is generated using the SFRPlainWindow constructor, and its coordinates given by the SyncScheduler CalculateWindowPosition() function.
After registering the drawing and key handlers, it obtains a reference to the VCalCollection through the GetVCalCollection() function and saves it in vCalCollection. All member variables are then initialized.
OneDayWindow Drawing Handler
OnRenderContent first prepares an SFXRectangle rect that is to be used in drawing procedures and uses it as an argument to the SFXGraphics DrawText() function to draw the very first line of the window displaying the string "NEW".
For all other lines, an offset is used representing an indentation. An Enumerator is used to shuffle through all the schedules contained within that day's VCalCollection.
The time components along with the summary are obtained, and the schedule is drawn.
OnRenderContent also draws a triangular cursor that points to the currently selected line.
OneDayWindow Key Handler
-
Within the key handler OnKey, a "clear" key press invokes an SREVT_RESPONDER_TERMINATE event and ends the OneDayWindow.
A "Select Key" press while the _cursor is equal to zero, meaning there are currently no schedules for that day, creates a new CreateWindow where a schedule may be entered.
If the _cursor is not zero, a reference to the data for that day contained in VCalCollection is obtained and a new ModifyWindow is created.
A "Down" key press moves the cursor down (++_cursor) and the displayed line (++_displine) down one, except if the cursor was already at the bottom of the screen, the the entire screen is shifted down, and _cursor and _displine values are set to 0 (top of the screen).
The exact opposite procedure is used to handle "Up" key presses.
A "Soft key 1" press event is handled by generating a new MultiDialog dialog giving the option to end the application or cancel.
dialog's parameters are set using the ParamRec variable param. Dialog is opened using SyncScheduler's OpenStandardDialog() function, and its events are handled by the handler function FromSoftkey1.
FromSoftkey1 closes dialog if the "Escape" or "Cancel" events are received, and terminates the application if the "OK" event was received.
DataInputWindow Class Overview
DataInputWindow Header File
DataInputWindow.hpp declares 3 SFREditBoxControlsPtrs for inputing hours, minutes and content.
Two SFRButtonControlPtrs are declared to point to the "Ok" and "Cancel" buttons. Labels for the SFREditBoxControls are stored in three SFRLabelControlPtrs.
An SInt16 variable _fontHeight saves the font height and an SFXDateConst _date saves the current day's date.
A virtual void function MakeData() is declared to update _vcal. A drawing handler (OnRenderContent), a key handler (OnKey) are declared as well as handlers for the OK and Cancel buttons (OnOkButtonControl and OnCancelButtonControl).
An SFRResponderPtr next and the handler function OnEditboxHandler are declared to automatically transfer control from one edit box to another.
Two other classes are declared, one to generate a window where new schedule entries can be entered and one where existing schedule entries can be modified.
DataInputWindow Constructor
An SFXRectangle rect is used for the placement of the SFREditBoxControls. The thickness of rect is set to that of _fontHeight. Its position on the screen is obtained by starting off with the constant rectangle screenRect, and adjusting it by the various menu margins.
After these modifications, the coordinates of the label control _labelDate are set to be the top left corner of the screen. _labelDate is set to point to a new SFRLabelControl whose string parameter is the variable date ( formatted with the Format() function ).
rect is then shifted down by _fontHeight plus MENU_SPACE, and its size modified through the SetSize() function. These are now the coordinates of the SFREditboxControl pointed to by _textHour. The input mode of this edit box is set to AEE_TM_NUMBERS through use of the SetInputMode() function. This setting is used to deal with numbers representing time values. The handler OnEditBoxHandler is registered to _textHour. The rectangle rect is then shifted to the right by the AddX() function, and an SFRLabelControl (with the label 'H') pointed to by _labelHour is created at this position.
This exact process is repeated for both the _textMinute and _textContent edit boxes. Furthermore, the "OK" and "Cancel" buttons are also created in a very similar way, except that they use SFRButtonControls and do not require separate labels. An OK button handler (OnOKButtonControl) and a Cancel button handler (OnCancelButtonControl) are assigned to their respective buttons.
DataInputWindow Event Handlers
Drawing Handler
The drawing handler simply calls the SFRPlainWindow's ContentHandler().
Key Handler
If any edit boxes are being targeted while the "Clear key is pressed, that box's target status is set to false and the focus is given to the next responder. If no edit boxes are being targeted, then the window is closed by invoking an SREVT_RESPONDER_TERMINATE event. Any directional key press shifts the responder focus in the respective direction.
OK Button Handler
The "OK" button handler, OnOkButtonControl, converts the string contained in _textHour to an integer and after checking its validity (in the range 0 to 24), it sets the SFXDate variable start's hour value to it. The same process is repeated for _textMinute. It then obtains the summary from the _textContent variable and then all the information to the MakeData() function. This overloaded function is called depending on the type of window from which it was called (CreateWindow or ModifyWindow). Finally an SRP16_TERMINATE_INVOKE event is invoked to close both the current window and the one in the background. The focus is then shifted to the oneDayWindow.
CancelButton Handler
The uot;"Cancel&q button handler, OnCancelButtonControl simply invokes an SFEVT_RESPONDER_TERMINATE event to end the DataInputWindow.
Window Types
A CreateWindow gives a user a fresh DataInputWindow with empty text boxes to enter information for a new schedule. The ModifyWindow displays a preexisting schedule, and allows users to modify its fields. The makeData() function saves the schedule data to VCalCollection using the append function for new schedukes, and the update function for preexisting ones.
Edit Box Handler
When the user has finished inputting text in an edit box, the OnEditboxHandler automatically sets the current edit boxe's target status to false, and gives focus to the next responder.