NRAO Home  >  Green Bank  |  Wiki Topic:    GB > Software > SoftwareReviewFeb04 > DEAP > DEAPUsage > DEAPRequests > DEAPUpdates > DEAPExamples > DEAPProgrammersManual
   Changes | Index | Contents | Search | Statistics | Go

Programmer's Manual for the Data Extraction and Analysis Program (DEAP)

  Main     Usage     Programmer's Manual     Requests     Updates     Examples  


DEAP Application Framework

DEAP is intended to provide plotting functionality independent of the DEAP application. One of the design goals was to make it easy to embed DEAP in any application while retaining all the functionality of the stand-alone application. Because of this, we can use DEAP in a variety of applications, such as GbtFitsMonitor, LogView, Astrid, and dcmon. The framework resides in DEAP's gui/framework package.

The primary mechanism for embedding DEAP is derived from other graphical embedding frameworks and uses Panels and Frames. The intent is to re-use panel functionality in different applications and also to allow different panels to co-exist in the same application. For example, LogView hosts both a DEAPPanel and a separate selection panel. A future version will probably also include a tabular display panel.

The Frame class provides a basic UI shell. Panels customize the Frame interface for Panel-specific functionality. This works through cycles of activation and deactivation. In the beginning, the Frame must be told to activate a panel through the ActivatePanel method. ActivatePanel allows a new panel to take control of the top-level UI by deactivating the old/existing panel and activating the new/given panel.

Activating a Panel in the Frame causes the ActivateSite method of the Panel to be called. ActivateSite notifies the Panel of its containing Frame and gives the Panel an opportunity to customize the Frame in any manner necessary.

A corresponding Panel method - DeactivateSite - gives the Panel an opportunity to undo any customizations, but usually you do not need to implement this method because the default clean-up behavior in the Frame is sufficient.

There is not much point in enumerating Frame methods because we're not interested in them. We won't be implementing any interesting derived Frame classes.

The available Panel methods are the accessors GetSite and SetSite, the events ActivateSite and DeactivateSite, and UpdateMenus. There is an important distinction between ActivateSite and UpdateMenus. ActivateSite customizes the Frame and is able to add or remove menu items in the Frame. This is a one-time activity. UpdateMenus is called every time the user accesses the menus, and it is used to reflect the current state of the application. For example, the "Save" menu option may only be available when the application is "dirty" and has changed state since the last save.

Note that we now have a containment hierarchy in addition to an inheritance hierarchy. A Panel is contained in a Frame, but it is not derived from Frame. We can, however, use the containment hierarchy in much the same way as we use the inheritance hierarchy. In general, Frame methods are available to the Panel transparently, and this is made possible by an implementation of getattr in the Panel. The significance of this is the Panel can call GetToolBar() or GetStatusBar() in order to make customizations, and does not have to execute any maneuvers such as GetFrame().GetStatusBar(). The Panel does not need to be concerned about it's containing object, and we'll soon see that this is an important distinction.

The key point is that one layer of containment is not usually very interesting. You could write that application without any help from the DEAP framework. The real strength of the framework comes out when we want to nest panels as much as necessary. So, getting away from concrete classes, Panel defines an interface (ActivateSite, DeactivateSite) for contained objects while Site defines an interface (ActivatePanel, DeactivatePanel) for containing objects. The Frame class implements the Site interface, but the Panel class implements both the Site interface and the Panel interface. This allows nesting.

In an application with nested Panels, the ActivatePanel method propagates up through the containment hierarchy until it hits the Frame, and the ActivateSite method propagates down through the containment hierarchy until it hits the innermost Panel. All of this is provided in the gui.framework.Panel class.

A consequence of the nesting behavior is that all nested Panels get a chance to customize the UI from the inside-out. That is to say, your derived Panel class overrides ActivateSite. The overridden method calls its parent's ActivateSite, and the default implementation activates the contained Panel. Then, after the contained panel is activated (the superclass method completes), the containing panel has an opportunity to further customize the UI. It's turtles all the way down.

In general, you don't have to pay much attention to the Site/Panel hierarchy. Even the innermost nested Panel class can transparently call Frame methods to customize the UI. There are, however, two places where the illusion breaks down. One, in order to catch and handle events on the Frame, such as a menu selection, the Panel has to explicitly access the Frame:

EVT_WHATEVER(self.GetFrame(), self.OnWhatever)

Also, because of the inside-out order of UI customization, containers need to know something about the behavior of their children in order to prevent conflicting customizations. The best way to work around this (i.e., to not care about what the contained objects are doing) is to always do customizations relative to the IDs defined in gui.framework.Frame.

Frame and, especially, Panel are the core parts of the framework. Two other classes are Notebook and Application. Notebook is designed to work in the context of the Site/Panel interfaces and will always tell its containing object (Site) to activate the currently selected panel.

Application provides only a convenient way of accessing options. By deriving your application from gui.framework.Application and initializing the superclass with an array of potential config files, any code in the application can use wxGetApp().GetOption to read those config files.

And here's how you put all this together. Do all your real work in a derived Panel class. Override ActivateSite, DeactivateSite, and UpdateMenus as necessary, but be sure to always call the superclass methods first when overriding them.

Create a stub derived Frame class that knows how to instantiate your derived Panel class. If it is appropriate, use or derive a Notebook to host your Panel(s). With or without a Notebook, the most important thing you need to do is call ActivatePanel with your first active panel in order to hook-up all the plumbing discussed above.

Create a stub Application class that knows how to instantiate your derived Frame class and where to find your config file, if appropriate.

Then you're good to go.

Topic DEAPProgrammersManual . { Edit | Attach | Ref-By | Printable | Diffs | r1.8 | > | r1.7 | > | r1.6 | More }
Revision r1.8 - 13 May 2004 - 19:42 GMT - AmyShelton
Parents: SoftwareReviewFeb04 > DEAP > DEAPUsage > DEAPRequests > DEAPUpdates > DEAPExamples
Content copyright © 1999-2007 by the contributing authors.
All material on this collaboration platform is the property of the contributing authors.