From f937077b0ee0aed94af8e6c3f1e789ed2064d952 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 28 May 2019 08:53:00 -0600 Subject: [PATCH] apps/graphics/twm4nx/README.txt: Add an overview of how to create Twm4Nx applications. --- graphics/twm4nx/README.txt | 170 +++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) diff --git a/graphics/twm4nx/README.txt b/graphics/twm4nx/README.txt index 29c535eb3..40b0d8723 100644 --- a/graphics/twm4nx/README.txt +++ b/graphics/twm4nx/README.txt @@ -208,3 +208,173 @@ Issues: that results in a large line spacing on the display and, hence, fewer lines visible in the small window. This is latter issues is a problem with the fonts not Twm4Nx, however. + +Adding Twm4Nx Applications +========================== + + Application Factories and the Main Menu + --------------------------------------- + The original TWM supported a .twmrc in which you could describe application + programs supported on the desktop. Currently no such start-up file is + available for Twm4Nx. Rather, all applications must be added via run-time + interfaces. And overview of these interfaces is provided in this + paragraph. + + Currently, there are only two applications developed for Twm4Nx: (1) An + NxTerm hosting NSH that is analogous to an XTerm hosting the Bash shell + in a Unix environment, and (2) a touchscreen calibration application. + Let's focus instead on the NxTerm application as an example because the + touchscreen calibration is a rather unusual beast. + + These example applications can be found at: apps/graphics/twm4nx/apps and + apps/include/graphics/twm4nx/apps + + In short, adding an application involves a "Factory Object" that is + hooked into the Main Menu. A Factory Object is an object that is used + to create other object instances. The way in which the Factory Object + is represented is purely a decision of the application developer. One + option, however, is to use the pure virtual base class IApplicationFactory + as defined in apps/include/graphics/twm4nx/iapplication.hxx. This base + class provides only a single method: + + bool initialize(FAR CTwm4Nx *twm4nx); + + where CTwm4Nx is the Twm4NX session instance that allows the class + implementation to interact with session specific resources. Multiple + sessions would be required, for example, if the platform supported + multiple displays. + + In practice, the application factory implementation class inherits from + the following base classes: + + 1. IApplicationFactory. Provides the common initialize() method. + 2. IApplication. Provides the information for the application's entry + in the Main Menu + 3. CTwm4NxEvent. Hooks the application factory into the Twm4Nx event + notification system. + + Initialization consists of instantiating the application factory instance + and calling its IApplicationFactory::initialize() method. The application + factory instance is a singleton that must persist for the life of the + session. For the NxTerm application factory, this is done in + apps/graphics/twm4nx/src/twm4nx_main.c like: + + CNxTermFactory nxtermFactory; + success = nxtermFactory.initialize(twm4nx); + + In addition to general initialization, the IApplicationFactory::initialize() + method must register a new entry with the main menu. You can see an + example of this in apps/graphics/twm4nx/apps/cnxterm.c: + + FAR CMainMenu *cmain = twm4nx->getMainMenu(); + return cmain->addApplication(this); + + The argument to the CMainMenu::addApplication() method is of type + IApplication *. Remember, however, that our application implementation + class inherited from IApplication. + + The IApplication pure virtual base class is also defined in + apps/include/graphics/twm4nx/iapplication.hxx. It essentially describes + what the Main Menu logic should do when the menu item is selected. It + includes these methods: + + 1. getName(). Provides the name string that will be shown in the + Main Menu for this selection. + 2. getSubMenu(). One possibility is that selecting the Main Menu item + is that it may bring up yet another sub-menu of options. + 3. getEventHandler(). Returns an instance of CTwm4NxEvent that is used + to route menu selection events. Remember that our application + factory inherits from CTwm4NxEvent so this function only needs to + return the 'this' pointer. + 4. getEvent(). Provides the event ID that will be used in the event + notification. The returned value must conform to the description + in apps/include/graphics/twm4nx/twm4nx_events.hxx. In particular, + the recipient of the event must be EVENT_RECIPIENT_APP. + + The Twm4Nx application is then started when the application factory's + CTwm4NxEvent::event() method is called with the specified event. + + Application Windows + ------------------- + How the application factory starts an application instance is purely up + to the application designer. Typically this would include starting a + new application task. General characteristics of an application include: + + 1. It probably should inherit from CTwm4NxEvent so that it can receive + events from the system. + 2. To create the window, it must instantiate and initialize an instance + of CWindow. + 3. It must configure application events to receive notifications from + Twm4Nx. + + To create an application window, the application must call the + CWindowFactory::createWindow() method. For the NxTerm example, this looks + like: + + NXWidgets::CNxString name("NuttShell"); + + uint8_t wflags = (WFLAGS_NO_MENU_BUTTON | WFLAGS_HIDDEN); + + FAR CWindowFactory *factory = m_twm4nx->getWindowFactory(); + m_nxtermWindow = factory->createWindow(name, &CONFIG_TWM4NX_NXTERM_ICON, + (FAR CIconMgr *)0, wflags); + + The window factory is another factory that creates and manages window + instance. The createWindow() method requires four parameters: + + 1. The name of the window. This is the name that is show in the window + toolbar and may be the same name as was used in the Main Menu entry. + 2. A reference to the the Icon image associated with the window. This + is the image that is show on the desktop when the window is + iconified. It is of type NXWidgets::SRlePaletteBitmap. + 3. A pointer to the Icon Manager instance that this window belongs with. + This can be NULL to use the default Twm4Nx Icon Manager. + 4. A set of flags that describe properties of the windows. + + The flag values are defined byte WFLAGS_* definitions provided in + apps/include/graphics/twm4nx/cwindow.hxx: + + 1. WFLAGS_NO_MENU_BUTTON Omit the menu button from the toolbar + 2. WFLAGS_NO_DELETE_BUTTON Omit the delete button from the toolbar + 3. WFLAGS_NO_RESIZE_BUTTON Omit the resize button from the toolbar + 4. WFLAGS_NO_MINIMIZE_BUTTON Omit the minimize button from the toolbar + 5. WFLAGS_NO_TOOLBAR Omit the toolbar altogether + 6. WFLAGS_ICONMGR This window is an icon manager + 7. WFLAGS_MENU This window is a menu window + 8. WFLAGS_HIDDEN Start with the window hidden + + Once the CWindow is instantiated, events needed by the application can + be configured as is done in the NxTerm application: + + struct SAppEvents events; + events.eventObj = (FAR void *)this; + events.redrawEvent = EVENT_NXTERM_REDRAW; + events.resizeEvent = EVENT_NXTERM_RESIZE; + events.mouseEvent = EVENT_NXTERM_XYINPUT; + events.kbdEvent = EVENT_NXTERM_KBDINPUT; + events.closeEvent = EVENT_NXTERM_CLOSE; + events.deleteEvent = EVENT_NXTERM_DELETE; + + bool success = m_nxtermWindow->configureEvents(events); + + Again, recall that the application inherits from CTwm4NxEvent. So passing + 'this' as the event object above assures that the specific events are + routed to the application instance. + + Drawing in the application window can be performed using that facilities + of NXWidgets using the NXWidgets::CGraphicsPort associated with the + window. The NxTerm application does not perform any drawing, however; + that drawing is performed by the NxTerm driver. + + The NXWidgets::CGraphicsPort can be obtained from a CWindow instance, + say m_window, like: + + FAR NXWidgets::CWidgetControl *control = m_window->getWidgetControl(); + NXWidgets::CGraphicsPort *port = control->getGraphicsPort(); + + That CGraphicsPort is then passed to the widget constructor, binding the + widget to that window and forcing all widget drawing to occur within the + window. + + Obviously, a lot more could be written about drawing, much more than can + be addressed in this README file.