Tutorial Part 3 Source Code

Up: GEOS SDK TechDocs| Up | NextTutorial Part 3: Adding Procedural Code

Here is the source code for the application discussed in this chapter. Pieces of the code which have been added or changed from that in the previous chapter are called out in bold.

TUTORIAL.GP

# Permanent name: This is required by Glue to set the permanent name
# and extension of the geode. The permanent name of a library is what
# goes in the imported library table of a client geode (along with the
# protocol number). It is also what Swat uses to name the patient.
#
name     tutorial.app
# Long filename: this name can displayed by the system. "EC " is
# prepended to this when the error-checking version is linked by Glue.
#
longname "Tutorial Sample Application"
# Token: The four-letter name is used by the system to locate the
# icon for this application in the token database. The tokenid
# number corresponds to the manufacturer ID of the program's author
# for uniqueness of the token. Since this is a sample application, we
# use the manufacturer ID for the SDK, which is 8.
#
tokenchars "TUTO"
tokenid    8
# Specify geode type: This geode is an application, and will have
# its own process (thread).
#
type   appl, process, single
# Specify class name for application thread. Messages sent to the
# application thread (a.k.a. "process" when specified as the output
# of a UI object) will be handled by this process class.
#
class  TutorialProcessClass
# Specify application object. This is the object that serves as
# the top-level UI object in the application.
#
appobj TutorialApp
# Specify for which platform this application will be compiled.
# Glue uses this to make sure that the libraries we are using
# (listed below) are available for this platform.
# In this case, the specified platform is the Nokia 9000i Communicator
#
platform n9000v20
# Heapspace: This is roughly the non-discardable memory usage
# (in paragraphs (16 bytes/paragraph)) of the application and any
# transient libraries that it depends on, plus an additional
# amount for thread activity. To find the heapspace for an
# application, use the Swat "heapspace" command.
#
heapspace 3K
# Libraries: list which libraries are used by the application.
# The foam library is for the Nokia 9000i Communicator only.
#
library geos
library ui
library foam
# Resources: list all resource blocks which are used by the
# application whose allocation flags can't be inferred by Glue.
# Usually this is needed only for object blocks, fixed code
# resources, or data resources that are read-only. Standard
# discardable code resources do not need to be mentioned.
#
resource APPRESOURCE ui-object
resource INTERFACE   ui-object
#
# Any classes that we define in our application must be exported
# here for glue to process them.
#
export TutorialViewClass

TUTORIAL.GOC

/********************************************************************
 *		Include Files
 *******************************************************************/
    @include <stdapp.goh>
    @include <foam.goh>
/********************************************************************
 *		Constants
 *******************************************************************/
      /*
       * These constants are used in the TutorialDraw function.
       */
    #define TEXT_POINT_SIZE  48.0 /* point size */
    #define TEXT_ROTATION   -15   /* angle of rotation (degrees) */
    #define TEXT_X_POSITION  30   /* x position, in document coords */
    #define TEXT_Y_POSITION   0   /* y position, in document coords */
/********************************************************************
 *		Class Definitions
 *******************************************************************/
      /*
       * Here we define "TutorialProcessClass" as a subclass of the
       * system provided "GenProcessClass". As this application is
       * launched, an instance of this class will be created, and
       * will handle all application-related events (messages). The
       * application thread will be responsible for running this
       * object, meaning that whenever this object handles a message,
       * we will be executing in the application thread.
       *
       * You will find no object in this file declared to be of this
       * class. Instead, it is specified as the class for the
       * application thread in "tutorial.gp".
       */
    @class TutorialProcessClass, GenProcessClass;
      /*
       * Define messages for this class here. Most commonly, UI
       * objects will send these messages to the application thread
       * when they've been activated by the user.
       */
    @endc; /* end of class definition */

      /*
       * We subclass GenViewClass here because we need to
       * intercept a message for our GenView object.
       */
    @class TutorialViewClass, GenViewClass;
    @endc; /* end of class definition */
/********************************************************************
 *		Class Declarations
 *******************************************************************/
      /*
       * Each object class requires a "class record" be stored in
       * fixed memory for it. The class record is used by the GEOS
       * message system for the delivery of messages sent to an
       * object of the class. The class record needs to be defined
       * in the file where the objects of that class are defined.
       * The @classdecl GOC directive tells GOC to create the class
       * record here.
       *
       * The neverSaved flag is necessary because ProcessClass
       * objects are hybrid objects. It tells the system that no
       * object of this class will ever be loaded from or stored to
       * a state file.
       */
    @classdecl TutorialProcessClass, neverSaved;
    @classdecl TutorialViewClass;
/********************************************************************
 *		UI Object Resources
 *******************************************************************/

/********************************************************************
 *		AppResource Resource
 *******************************************************************/
@start AppResource;

  /*
   *    Application Object
   *
   * The very top-level generic object of an application MUST be
   * a GenApplication object. The tutorial.gp file contains the "appobj"
   * statement which indicates that this "TutorialApp" object is in
   * fact the top-level UI object.
   *
   * This object should be in its own resource, as it is all that
   * need be in memory when the application is iconified. As such,
   * its resource should be as small as possible.
   *
   * FoamSubApplicationClass is for the Nokia 9000i Communicator
   * only. It adds special behavior for that platform.
   */
@object FoamSubApplicationClass TutorialApp = {
      /*
       * While the application object isn't shown on the screen,
       * it has a list of VisMonikers for three purposes:
       *   1) The GenPrimary (see below) inherits the moniker
       *      when it comes up on screen.
       *   2) When GeoManager needs to display an icon for the
       *      application, and there's none for it in the Token
       *      Database, it launches the app and sends a message
       *      to the application object to install its list of
       *      monikers in the token database under the
       *      application's token.
       *   3) When the GenPrimary is minimized, it uses the most
       *      appropriate graphical moniker from this list for the
       *      application's icon. If there's an abbreviated-text
       *      moniker in the list, that's used as the icon title.
       *      Else any regular-text moniker is used.
       */
    GI_visMoniker = list { @TutorialTextMoniker };

      /*
       * The GenApplication object has at least one child:
       * the main application window.
       */
    GI_comp = @TutorialPrimary;

      /*
       * The main window should appear on-screen when the application
       * is launched, so place it on the GAGCNLT_WINDOWS GCN list.
       * This causes the application object to bring it on-screen at
       * the appropriate time.
       */
    gcnList( MANUFACTURER_ID_GEOWORKS, GAGCNLT_WINDOWS ) = @TutorialPrimary;
}

@visMoniker TutorialTextMoniker = "C Tutorial";
@localize "Program Title";

@end AppResource;
/********************************************************************
 *		Interface Resource
 * This resource is for miscellaneous UI objects.
 *******************************************************************/
@start Interface;

  /*
   *    Primary window
   *
   * Every application has at least one GenPrimary object.
   * This object serves as the main window of the application.
   * Inside this window, various UI components, such as menus
   * or lists, can be placed.
   */
@object GenPrimaryClass TutorialPrimary  = {
		/*
		 * This window has two children:
		 * the GenView object and the Close button (see below).
		 */
	GI_comp = @TutorialView, @TutorialCloseTrigger;
}

  /*
   *    GenView object
   *
   * This GenView object creates a window where the application can
   * display portions of the document as necessary. As we want this
   * window to be scrollable, the specific UI will create scroll
   * bars with which the user can interact. Whenever a portion of
   * the window needs to be redrawn, the GenView object will
   * invalidate a portion of the window, causing a MSG_META_EXPOSED
   * to be sent to the application. The application will draw the
   * document into the window as requested. The window keeps track
   * of a mask, which is used to clip the application's drawing
   * operations, so that only the invalid portion of the window is
   * drawn to.
   */
@object TutorialViewClass TutorialView = {
      /*
       * Make view scrollable in X and Y and ensure that it never
       * gets larger than the thing being displayed within it.
       */
    GVI_horizAttrs = @default | GVDA_SCROLLABLE
                              | GVDA_NO_LARGER_THAN_CONTENT;
    GVI_vertAttrs  = @default | GVDA_SCROLLABLE
                              | GVDA_NO_LARGER_THAN_CONTENT;

      /*
       * When the contents of this view (i.e. the document) must be
       * updated, the UI should send a MSG_META_EXPOSED to the
       * TutorialProcessClass object.
       */
    GVI_content = process;

      /*
       * Specify the dimensions of the document being displayed
       * within the view.
       */

    GVI_docBounds = {
        0,
        0,
        1000,
        1000
    };
}
	/*
	 *    Close trigger
	 *
	 * On certain systems we should provide a way to exit the
	 * application. On the Nokia 9000i Communicator we have a
	 * close trigger like this one.
	 */
@object ComplexMonikerClass TutorialCloseTrigger = {
	ComplexMoniker = GenTriggerClass;
	CMI_topText = CMT_CLOSE;

		/*
		 * The next two instance fields are part of the
		 * GenTriggerClass. They specify the recipient object
		 * and the message that will be sent to that object
		 * when this trigger is activated.
		 */
	GTI_destination = @TutorialApp;
	GTI_actionMsg = MSG_FSA_RETURN_TO_LAUNCHER;

		/*
		 * The specific UI uses this combination of hints
		 * to place this trigger on the right side of the
		 * Nokia 9000i Communicator's screen.
		 */
	HINT_SEEK_MENU_BAR;
	HINT_SEEK_REPLY_BAR;
	HINT_SEEK_SLOT = 3;
}
@end Interface;
/********************************************************************
 *		Function Definitions
 *******************************************************************/

/********************************************************************
 *              TutorialDraw
 ********************************************************************
 * SYNOPSIS:	 Redraws the entire document, given a graphics state
 *		 through which to draw.
 * CALLED BY:	 (INTERNAL) TutorialProcess::MSG_META_EXPOSED
 * RETURNS:      void
 * SIDE EFFECTS: Various aspects of the gstate are altered.
 * STRATEGY:     First set the font used by this gstate. Then
 *               set the text color. Using the constant angle lets
 *               rotate the gstate. To finish up, draw the text
 *               text to the gstate.
 *******************************************************************/
void


TutorialDraw( GStateHandle gstate )
  /*
   * gstate - GState to draw to.
   */
{




      /*
       * First change some of the default GState values,
       * such as font and point size.
       */
    GrSetFont( gstate, FID_DTC_URW_SANS, MakeWWFixed( TEXT_POINT_SIZE ) );


      /*
       * Apply a rotation to the transformation matrix,
       * so the text will be drawn at an angle.
       */
    GrApplyRotation( gstate, MakeWWFixed( TEXT_ROTATION ) );


      /*
       * Draw some text onto the document.
       */
    GrDrawText( gstate, TEXT_X_POSITION, TEXT_Y_POSITION,
                "The quick brown fox jumps over the lazy dog.",
                0 );
} /* TutorialDraw */
/********************************************************************
 *		Code for TutorialProcessClass
 *******************************************************************/

/********************************************************************
 *              MSG_META_EXPOSED
 ********************************************************************
 * SYNOPSIS:	 Redraw the recently-exposed portion of the View.
 *               See the Objects Reference book for more information
 *               on this message and its parameters.
 * PARAMETERS:	 WindowHandle win
 * RETURNS:      void
 * SIDE EFFECTS: The invalid region of the window is cleared out.
 * STRATEGY:	 This message is sent by the windowing system when a
 *	    	 portion of the GenView has become invalid, either
 *	    	 because a window that was obscuring it has been moved,
 *	    	 or because someone called GrInvalRect. We redraw the
 *               entire document, after telling the graphics system
 *               we're drawing to the invalid portion of the window.
 *
 *******************************************************************/


@method TutorialProcessClass, MSG_META_EXPOSED
{
      /*
       * gstate - This is a handle to the graphics state
       *          that we'll use to draw to the view.
       */
    GStateHandle gstate;


      /*
       * Get a default graphics state that we can use while drawing.
       */
    gstate = GrCreateState( win );


      /*
       * Start a window update. This tells the windowing system
       * that we are in the process of drawing to the invalid portion
       * of this window. GrBeginUpdate/GrEndUpdate are necessary only
       * when handling MSG_META_EXPOSED. For drawing at other times,
       * all you need do is create a graphics state and draw through it.
       */
    GrBeginUpdate( gstate );

      /*
       * Draw the pattern into the window (pass the GState). Breaking
       * the exposure and general drawing into two routines allows the
       * display to be updated by other routines without having to
       * invalidate the window.
       */
    TutorialDraw( gstate );



      /*
       * Now indicate that we are done drawing to the invalid area
       * and free the gstate.
       */
    GrEndUpdate( gstate );
    GrDestroyState( gstate );
} /* MSG_META_EXPOSED */

/* This is here to work around a bug in the Borland C 5.0 compiler. */
@method TutorialProcessClass, MSG_GEN_PROCESS_CLOSE_APPLICATION
{

    return( @callsuper() );
}
/********************************************************************
 *		Code for TutorialViewClass
 *******************************************************************/

/********************************************************************
 *              MSG_META_KBD_CHAR
 ********************************************************************
 * SYNOPSIS:     We intercept this message to add the scrolling
 *               behavior to the GenView. Normally this would work
 *               in GEOS but the Nokia 9000i Communicator has the
 *               scrolling disabled in GenViewClass.
 * PARAMETERS:   word character
 *               word flags
 *               word state
 * RETURNS:      void
 * SIDE EFFECTS: none
 * STRATEGY:     We first check the parameters to see if this
 *               keypress is one we are interested in. It has to be
 *               a "control" key, and must not be a key release
 *               (i.e. the user released the key after holding it).
 *               If both of these conditions are true we can then
 *               use a switch statement to see which key is being
 *               pressed and send the appropriate message to the
 *               GenView object.
 *******************************************************************/


@method TutorialViewClass, MSG_META_KBD_CHAR
{
      /*
       * theChar - A copy of the character with only the
       *           low byte. The high byte of character
       *           has some extra flags we don't need here.
       */
    byte        theChar;

      /*
       * Arrow keys and scroll buttons are control characters.
       * We handle first press and repeat presses of those keys.
       */
    if ( ( ( character >> 8 ) == CS_CONTROL ) &&
         ( flags & ( CF_FIRST_PRESS | CF_REPEAT_PRESS ) ) ) {
        theChar = character & 0xFF;

        switch ( theChar ) {

        case VC_PREVIOUS:
              /* This handles the Page Up key. */
            @send self::MSG_GEN_VIEW_SCROLL_PAGE_UP();
            break;

        case VC_UP:
              /* This handles the up arrow key. */
            @send self::MSG_GEN_VIEW_SCROLL_UP();
            break;

        case VC_NEXT:
              /* This handles the down arrow key. */
            @send self::MSG_GEN_VIEW_SCROLL_PAGE_DOWN();
            break;

        case VC_DOWN:
              /* This handles the up arrow key. */
            @send self::MSG_GEN_VIEW_SCROLL_DOWN();
            break;

        case VC_RIGHT:
              /* This handles the right arrow key. */
            @send self::MSG_GEN_VIEW_SCROLL_RIGHT();
            break;

        case VC_LEFT:
              /* This handles the left arrow key. */
            @send self::MSG_GEN_VIEW_SCROLL_LEFT();
            break;

        default:

              /*
               * Pass on other control chars to default handler.
               */
            @callsuper();
        } /* switch */
    } else {
          /*
           * Pass on all other chars to default handler.
           */
        @callsuper();
    }
} /* MSG_META_KBD_CHAR */

Up: GEOS SDK TechDocs| Up | Next:Tutorial Part 3: Adding Procedural Code