Building a Simple Editor Part 1

From EDM2
Revision as of 10:50, 11 June 2018 by Ak120 (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Written by Gordon Zeglinski

Introduction

The Open Class Library (IOCL) that ships with VisualAge C++ allows the programmer to quickly develop applications. "Fancy" features such as Linkbars, fly-over help, etc. can easily be added to applications. In this issue, we revisit the simple editor created several issues ago, and add some bells and whistles to it.

Linkbars, Linkbars, Everywhere Linkbars

Just about every application has a Linkbar. Creating one without some pre-existing Linkbar control can be a daunting task. Fortunately adding a Linkbar to an IOCL based application is a snap. The ILinkbar class is an easy way to add Linkbars to your applications.

Often, this class will be inherited by the application specific Linkbar as follows:

class EditLinkbarSet:public ILinkbar{

public:
   EditLinkbarSet(IFrameWindow *wnd);
   ~EditLinkbarSet();

protected:

   //define items that appear on Linkbar here
   ILinkbarButton       bLoad,
                        bSave;
};

Additionally, the IOCL provides a specialized button class for use in Linkbars. This button class allows Linkbars to display text only, bitmap only or text and bitmap buttons. Linkbars can contain controls other than buttons. But for this example, we will only add in two buttons. The constructor for the EditLinkbarSet is shown below.

EditLinkbarSet::EditLinkbarSet(IFrameWindow *wnd):
                ILinkbar(
                    1111,                       //Linkbar ID
                    wnd,                        //frame to attach to
                    aboveClient,                //position above client & below menu
                    false,                      //don't group with other Linkbars
                    defaultStyle()              //use the default style
                ),
                bLoad(
                    MenLoad,                    //same ID as for the menu item load
                    this,                       //Linkbar is parent & owner of this
                    this,                       // button
                    IRectangle(),               //initial position
                    ILinkbarButton::defaultStyle()  //use default style
                ),
                bSave(
                    MenSave,                    //same ID as for the menu item save
                    this,
                    this,
                    IRectangle(),
                    ILinkbarButton::defaultStyle()
                )
 {
   bLoad.setBitmap(IC_ID_OPEN);         //set the bitmap to standard open bitmap
   bLoad.setText("Open");               //set the text to Open

   bSave.setBitmap(IC_ID_SAVE);         //set the bitmap to standard save bitmap
   bSave.setText("Save");               //set the text to Save

   addAsLast(&bLoad);                   //add the buttons
   addAsLast(&bSave);                   //-----
 }

That's all there is to creating a Linkbar! There's a few things to note though. By default, all ILinkbarButtons use the standard style. This means that they all have the same appearance. Displaying long text in a standard button is impossible. To remove the standard style by changing the button style to ILinkbarButton::defaultStyle()&~ILinkbarButton::standardFormat.

To add the Linkbar to the editor window, we have to make the following changes. First, we must add a data member to the Editor class to store the instance pointer to the Linkbar.

class Editor:public ICommandHandler{

public:
   Editor();
   ~Editor();

protected:
   Boolean        command(ICommandEvent &event);

   IFrameWindow   *frame;
   IMultiLineEdit *editwin;
   IString        FileName;

   EditLinkbarSet *Linkbar;
};

Then we must add code to constructor and destructor to create and destroy the Linkbar. The changes are shown below.

Editor::Editor(){
   frame=new IFrameWindow(1, IFrameWindow::titleBar|
                             IFrameWindow::sizingBorder|
                             IFrameWindow::minimizeButton|
                             IFrameWindow::maximizeButton|
                             IFrameWindow::windowList|
                             IFrameWindow::menuBar|
                             IFrameWindow::systemMenu);

   handleEventsFor(frame);

   editwin=new IMultiLineEdit(10,frame,frame);

   frame->setClient(editwin);
   Linkbar=new EditLinkbarSet(frame);      //create the Linkbar
   frame->show();
}

Editor::~Editor(){
   delete editwin;
   delete Linkbar;                         //destroy the Linkbar
   delete frame;
}

Help Me: Fly-over Help and Other Fun Stuff

Now that we have a working Linkbar, users usually expect fly-over help and/or a status area to tell them what the buttons do. Adding these features is a simple task. Because these features are related to the Linkbar, I'll add support for them to the EditLinkbarSet class. The new class definition follows

class EditLinkbarSet:public ILinkbar{

public:
   EditLinkbarSet(IFrameWindow *wnd);
   ~EditLinkbarSet();

protected:
   IInfoArea            area;

   ILinkbarButton       bLoad,
                        bSave;

   IFlyText             flytext;
   IFlyOverHelpHandler  flyHand;
};

Note the order in which the data members are declared.

I've noticed that the order in which the data members are declared matched the order in which they are initialized in the constructor. The initialization order specified in the constructor is NOT followed. This will affect the TAB order of controls in canvas controls in addition to data members that use other data members in their initialization code.

The new constructor for EditLinkbarSet follows.

EditLinkbarSet::EditLinkbarSet(IFrameWindow *wnd):
                ILinkbar(
                    1111,
                    wnd,
                    aboveClient,
                    false,
                    defaultStyle()
                ),
                area(          //add an info area to the bottum of the frame
                    wnd,
                    1112
                ),
                bLoad(
                    MenLoad,
                    this,
                    this,
                    IRectangle(),
                    ILinkbarButton::defaultStyle()
                ),
                bSave(
                    MenSave,
                    this,
                    this,
                    IRectangle(),
                    ILinkbarButton::defaultStyle()
                ),
                flytext(    //create the fly over text window
                    1113,
                    this
                ),
                flyHand(       //create the help handler
                    &flytext,   //put fly over help in here
                    &area       //put the long descriptions in the infoarea
                )
 {
   bLoad.setBitmap(IC_ID_OPEN);
   bLoad.setText("Open");

   bSave.setBitmap(IC_ID_SAVE);
   bSave.setText("Save");

   addAsLast(&bLoad);
   addAsLast(&bSave);

   //set the bases in the string table
   flyHand.setFlyTextStringTableOffset( FlyBase );
   flyHand.setLongStringTableOffset( LongBase );
   //start handling flyover for the Linkbar
   flyHand.handleEventsFor(this);
 }

The fly-over help handler loads string from the string resource table. The string it loads for a particular control is based on the control's ID number and the particular table offset (see the included .rc file for an example). It is possible to have a short text phrase for the fly-over window and a longer, more descriptive phrase for the status area.

Once the appropriate entries are added to the string table in the .rc file, and the new code is compiled, we have working fly-over help. All the source for both NT and OS/2 VAC++ is included in oops_src.zip.

Wrapping Things Up

We've seen that adding a Linkbar, fly-over help and an info-area to an application is easy using the IOCL. Although there's a few tricks that have to be looked out for, they are not a hinderance to quickly adding these nifty features to an application.