diff --git a/graphics/twm4nx/Makefile b/graphics/twm4nx/Makefile index 71337ad1f..aef1c17e5 100644 --- a/graphics/twm4nx/Makefile +++ b/graphics/twm4nx/Makefile @@ -55,7 +55,7 @@ STACKSIZE = $(CONFIG_TWM4NX_STACKSIZE) ASRCS = CSRCS = CXXSRCS = cbackground.cxx cfonts.cxx cicon.cxx ciconmgr.cxx -CXXSRCS += ciconwidget.cxx cinput.cxx cmenus.cxx cresize.cxx +CXXSRCS += ciconwidget.cxx cinput.cxx cmenus.cxx cmainmenu.cxx cresize.cxx CXXSRCS += cwindow.cxx cwindowevent.cxx cwindowfactory.cxx CXXSRCS += twm4nx_cursor.cxx MAINSRC = ctwm4nx.cxx diff --git a/graphics/twm4nx/src/ciconmgr.cxx b/graphics/twm4nx/src/ciconmgr.cxx index d1cd7e038..145142ae0 100644 --- a/graphics/twm4nx/src/ciconmgr.cxx +++ b/graphics/twm4nx/src/ciconmgr.cxx @@ -157,7 +157,7 @@ bool CIconMgr::initialize(FAR const char *prefix) if (!createButtonArray()) { - twmerr("ERROR: Failed to button array\n"); + twmerr("ERROR: Failed to create button array\n"); CWindowFactory *factory = m_twm4nx->getWindowFactory(); factory->destroyWindow(m_window); @@ -440,8 +440,8 @@ void CIconMgr::sort(void) break; } - if (std::strcmp(tmpwin1->cwin->getWindowName(), - tmpwin2->cwin->getWindowName()) > 0) + NXWidgets::CNxString windowName = tmpwin1->cwin->getWindowName(); + if (windowName.compareTo(tmpwin2->cwin->getWindowName()) > 0) { // Take it out and put it back in @@ -466,16 +466,16 @@ void CIconMgr::sort(void) bool CIconMgr::event(FAR struct SEventMsg *eventmsg) { - bool ret = true; + bool success = true; switch (eventmsg->eventID) { default: - ret = false; + success = false; break; } - return ret; + return success; } /** @@ -542,6 +542,10 @@ bool CIconMgr::createIconManagerWindow(FAR const char *prefix) return false; } + // Hide the window until we complete the configuration + + m_window->hideWindow(); + // Free any temporary name strings if (allocName != (FAR char *)0) @@ -595,6 +599,9 @@ bool CIconMgr::createIconManagerWindow(FAR const char *prefix) return false; } + // Now show the window in all its glory + + m_window->showWindow(); m_window->synchronize(); return true; } @@ -690,7 +697,8 @@ void CIconMgr::insertEntry(FAR struct SWindowEntry *wentry, { // Insert the new window in name order - if (strcmp(cwin->getWindowName(), tmpwin->cwin->getWindowName()) < 0) + NXWidgets::CNxString windowName = cwin->getWindowName(); + if (windowName.compareTo( tmpwin->cwin->getWindowName()) > 0) { wentry->flink = tmpwin; wentry->blink = tmpwin->blink; diff --git a/graphics/twm4nx/src/cmainmenu.cxx b/graphics/twm4nx/src/cmainmenu.cxx new file mode 100644 index 000000000..bc4311b8e --- /dev/null +++ b/graphics/twm4nx/src/cmainmenu.cxx @@ -0,0 +1,243 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/include/cmainmenu.cxx +// Twm4Nx main menu class +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +///////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +///////////////////////////////////////////////////////////////////////////// +// Implementation Class Definition +///////////////////////////////////////////////////////////////////////////// + +using namespace Twm4Nx; + +/** + * CMainMenu Constructor + * + * @param twm4nx The Twm4Nx session + */ + +CMainMenu::CMainMenu(FAR CTwm4Nx *twm4nx) +{ + m_twm4nx = twm4nx; // Cache the Twm4Nx session instance + m_mainMenu = (FAR CMenus *)0; // The main menu instance + m_appHead = (FAR struct SMainMenuItem *)0; // The head of the main menu item list + m_appTail = (FAR struct SMainMenuItem *)0; // The tail of the main menu item list +} + +/** + * CMainMenu Destructor + */ + +CMainMenu:: ~CMainMenu(void) +{ + if (m_mainMenu != (FAR CMenus *)0) + { + delete m_mainMenu; + } +} + +/** + * CMainMenu Initializer. This function performs the parts of the + * initialization that may fail. + * + * @return True if the main menu was properly initialized. false is + * return on any failure. + */ + +bool CMainMenu::initialize(void) +{ + // Create the main menu + + m_mainMenu = new CMenus(m_twm4nx); + if (m_mainMenu == (FAR CMenus *)0) + { + gerr("ERROR: Failed to create the CMenus instance\n"); + return false; + } + + NXWidgets::CNxString menuName("Main Menu"); + if (!m_mainMenu->initialize(menuName)) + { + gerr("ERROR: Failed to initialize the CMenus instance\n"); + delete m_mainMenu; + m_mainMenu = (FAR CMenus *)0; + return false; + } + + return true; +} + +/** + * Register one main menu item + * + * @param app An instance of a class that derives from IApplication + * @return True if the menu item was properly added to the main menu. + * false is return on any failure. + */ + +bool CMainMenu::addApplication(FAR IApplication *app) +{ + // Allocate a new main menu entry + + FAR struct SMainMenuItem *mmitem = + (FAR struct SMainMenuItem *)malloc(sizeof(struct SMainMenuItem)); + + if (mmitem == (FAR struct SMainMenuItem *)0) + { + gerr("ERROR: Failed to allocate the main menu entry\n"); + return false; + } + + mmitem->flink = NULL; + mmitem->blink = NULL; + mmitem->app = app; + + // Add the new menu item to the main menu + + FAR NXWidgets::CNxString appName; + app->getName(appName); + + if (!m_mainMenu->addMenuItem(appName, app->getSubMenu(), + app->getEventHandler(), app->getEvent())) + { + gerr("ERROR: addMenuItem failed\n"); + std::free(mmitem); + return false; + } + + // Insert the new entry into the list of main menu items + + insertEntry(mmitem); + return true; +} + +/** + * Handle MAIN MENU events. + * + * @param eventmsg. The received NxWidget WINDOW event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + +bool CMainMenu::event(FAR struct SEventMsg *eventmsg) +{ + bool success = true; + + switch (eventmsg->eventID) + { + case EVENT_MAINMENU_SELECT: // Main menu selection +#warning Missing logic + success = false; + + default: + success = false; + break; + } + + return success; +} + +/** + * Put an allocated entry into the main menu in name order + * + * @param mmitem The entry to insert + */ + +void CMainMenu::insertEntry(FAR struct SMainMenuItem *mmitem) +{ + // Inserted the new menu item at the tail of the list + + mmitem->flink = NULL; + mmitem->blink = m_appTail; + + if (!m_appHead) + { + m_appHead = mmitem; + m_appTail = mmitem; + } + else + { + m_appTail->flink = mmitem; + m_appTail = mmitem; + } +} + +/** + * Remove an entry from an main menu + * + * @param mmitem the entry to remove + */ + +void CMainMenu::removeEntry(FAR struct SMainMenuItem *mmitem) +{ + FAR struct SMainMenuItem *prev = mmitem->blink; + FAR struct SMainMenuItem *next = mmitem->flink; + + if (!prev) + { + m_appHead = next; + } + else + { + prev->flink = next; + } + + if (!next) + { + m_appTail = prev; + } + else + { + next->blink = prev; + } + + mmitem->flink = NULL; + mmitem->blink = NULL; +} diff --git a/graphics/twm4nx/src/cmenus.cxx b/graphics/twm4nx/src/cmenus.cxx index 2b4b96586..feb288cf9 100644 --- a/graphics/twm4nx/src/cmenus.cxx +++ b/graphics/twm4nx/src/cmenus.cxx @@ -56,6 +56,7 @@ #include #include +#include "graphics/nxwidgets/cnxstring.hxx" #include "graphics/nxwidgets/cnxfont.hxx" #include "graphics/nxwidgets/clistbox.hxx" #include "graphics/nxwidgets/cwidgeteventargs.hxx" @@ -122,10 +123,11 @@ CMenus::~CMenus(void) * CMenus Initializer. Performs the parts of the CMenus construction * that may fail. * + * @param name The name of the menu * @result True is returned on success */ -bool CMenus::initialize(FAR const char *name) +bool CMenus::initialize(FAR NXWidgets::CNxString &name) { // Open a message queue to NX events. @@ -138,13 +140,9 @@ bool CMenus::initialize(FAR const char *name) return false; } - // Save the menu name + // Clone the menu name - m_menuName = strdup(name); - if (m_menuName == (FAR char *)0) - { - return false; - } + m_menuName = name; // Create the menu window @@ -177,11 +175,11 @@ bool CMenus::initialize(FAR const char *name) * \param event The event to generate on menu item selection */ -bool CMenus::addMenuItem(FAR const char *text, FAR CMenus *subMenu, +bool CMenus::addMenuItem(FAR NXWidgets::CNxString &text, FAR CMenus *subMenu, FAR CTwm4NxEvent *handler, uint16_t event) { twminfo("Adding menu text=\"%s\", subMenu=%p, event=%04x\n", - text, subMenu, event); + text->getCharArray(), subMenu, event); // Allocate a new menu item entry @@ -195,13 +193,7 @@ bool CMenus::addMenuItem(FAR const char *text, FAR CMenus *subMenu, // Clone the item name so that we have control over its lifespan - item->text = std::strdup(text); - if (item->text == (FAR char *)0) - { - twmerr("ERROR: strdup of item text failed\n"); - std::free(item); - return false; - } + item->text = text; // Save information about the menu item @@ -552,13 +544,10 @@ bool CMenus::setMenuWindowSize(void) curr != NULL; curr = curr->flink) { - if (curr->text != (FAR char *)0) + nxgl_coord_t stringlen = menuFont->getStringWidth(curr->text); + if (stringlen > maxstring) { - nxgl_coord_t stringlen = menuFont->getStringWidth(curr->text); - if (stringlen > maxstring) - { - maxstring = stringlen; - } + maxstring = stringlen; } } @@ -711,7 +700,8 @@ bool CMenus::popUpMenu(FAR struct nxgl_point_s *pos) return false; } - m_popUpMenu->addMenuItem("TWM Windows", (FAR CMenus *)0, + NXWidgets::CNxString windowName("TWM Windows"); + m_popUpMenu->addMenuItem(windowName, (FAR CMenus *)0, (FAR CTwm4NxEvent *)0, EVENT_SYSTEM_NOP); FAR CWindowFactory *factory = m_twm4nx->getWindowFactory(); @@ -745,10 +735,10 @@ bool CMenus::popUpMenu(FAR struct nxgl_point_s *pos) FAR CWindow *tmpcwin1 = swin->cwin; for (int i = 0; i < nWindowNames; i++) { - FAR const char *windowName1 = tmpcwin1->getWindowName(); - FAR const char *windowName2 = windowNames[i]->getWindowName(); + FAR NXWidgets::CNxString windowName1 = tmpcwin1->getWindowName(); + FAR NXWidgets::CNxString windowName2 = windowNames[i]->getWindowName(); - if (std::strcmp(windowName1, windowName2) < 0) + if (windowName1.compareTo(windowName2) < 0) { FAR CWindow *tmpcwin2; tmpcwin2 = tmpcwin1; @@ -762,8 +752,9 @@ bool CMenus::popUpMenu(FAR struct nxgl_point_s *pos) for (int i = 0; i < nWindowNames; i++) { - m_popUpMenu->addMenuItem(windowNames[i]->getWindowName(), - (FAR CMenus *)0, (FAR CTwm4NxEvent *)0, + NXWidgets::CNxString itemName = windowNames[i]->getWindowName(); + m_popUpMenu->addMenuItem(itemName, (FAR CMenus *)0, + (FAR CTwm4NxEvent *)0, EVENT_WINDOW_DEICONIFY); } @@ -929,13 +920,6 @@ void CMenus::cleanup(void) { next = curr->flink; - // Free the menu item text - - if (curr->text != (FAR char *)0) - { - std::free(curr->text); - } - // Free any subMenu if (curr->subMenu != (FAR CMenus *)0) @@ -948,11 +932,4 @@ void CMenus::cleanup(void) delete curr; } - // Free allocated memory - - if (m_menuName != (FAR char *)0) - { - std::free(m_menuName); - m_menuName = (FAR char *)0; - } } diff --git a/graphics/twm4nx/src/ctwm4nx.cxx b/graphics/twm4nx/src/ctwm4nx.cxx index c4d2d8199..9390f56e0 100644 --- a/graphics/twm4nx/src/ctwm4nx.cxx +++ b/graphics/twm4nx/src/ctwm4nx.cxx @@ -76,6 +76,7 @@ #include "graphics/twm4nx/ciconwidget.hxx" #include "graphics/twm4nx/ciconmgr.hxx" #include "graphics/twm4nx/cmenus.hxx" +#include "graphics/twm4nx/cmainmenu.hxx" #include "graphics/twm4nx/cresize.hxx" #include "graphics/twm4nx/cfonts.hxx" #include "graphics/twm4nx/twm4nx_widgetevents.hxx" @@ -127,6 +128,7 @@ CTwm4Nx::CTwm4Nx(int display) m_iconmgr = (FAR CIconMgr *)0; m_factory = (FAR CWindowFactory *)0; m_fonts = (FAR CFonts *)0; + m_mainMenu = (FAR CMainMenu *)0; m_resize = (FAR CResize *)0; #if !defined(CONFIG_TWM4NX_NOKEYBOARD) || !defined(CONFIG_TWM4NX_NOMOUSE) @@ -244,7 +246,7 @@ bool CTwm4Nx::run(void) // factory is needed by the Icon Manager which is instantiated below. m_factory = new CWindowFactory(this); - if (m_factory == (CWindowFactory *)0) + if (m_factory == (FAR CWindowFactory *)0) { cleanup(); return false; @@ -254,7 +256,7 @@ bool CTwm4Nx::run(void) // need by the Icon Manager which is instantiated next. m_fonts = new CFonts(this); - if (m_fonts == (CFonts *)0) + if (m_fonts == (FAR CFonts *)0) { cleanup(); return false; @@ -271,7 +273,7 @@ bool CTwm4Nx::run(void) // Create the Icon Manager m_iconmgr = new CIconMgr(this, 4); - if (m_iconmgr == (CIconMgr *)0) + if (m_iconmgr == (FAR CIconMgr *)0) { cleanup(); return false; @@ -286,7 +288,22 @@ bool CTwm4Nx::run(void) // Cache a CIcon instance for use across the session m_icon = new CIcon(this); - if (m_icon == (CIcon *)0) + if (m_icon == (FAR CIcon *)0) + { + cleanup(); + return false; + } + + // Create and initialize a CMainMenu instance for use across the session + + m_mainMenu = new CMainMenu(this); + if (m_mainMenu == (FAR CMainMenu *)0) + { + cleanup(); + return false; + } + + if (!m_mainMenu->initialize()) { cleanup(); return false; @@ -295,7 +312,7 @@ bool CTwm4Nx::run(void) // Cache a CResize instance for use across the session m_resize = new CResize(this); - if (m_resize == (CResize *)0) + if (m_resize == (FAR CResize *)0) { cleanup(); return false; @@ -458,6 +475,12 @@ bool CTwm4Nx::dispatchEvent(FAR struct SEventMsg *eventmsg) } break; + case EVENT_RECIPIENT_MAINMENU: // Main menu related event + { + ret = m_mainMenu->event(eventmsg); + } + break; + case EVENT_RECIPIENT_WINDOW: // Window related event case EVENT_RECIPIENT_TOOLBAR: // Toolbar related event case EVENT_RECIPIENT_BORDER: // Window border related event @@ -545,6 +568,14 @@ void CTwm4Nx::cleanup() m_factory = (CWindowFactory *)0; } + // Free the session CMainMenu instance + + if (m_mainMenu != (CMainMenu *)0) + { + delete m_mainMenu; + m_mainMenu = (CMainMenu *)0; + } + // Free the session CResize instance if (m_resize != (CResize *)0) diff --git a/graphics/twm4nx/src/cwindow.cxx b/graphics/twm4nx/src/cwindow.cxx index cac91b4ed..91a1d9003 100644 --- a/graphics/twm4nx/src/cwindow.cxx +++ b/graphics/twm4nx/src/cwindow.cxx @@ -215,11 +215,11 @@ bool CWindow::initialize(FAR const char *name, if (name == (FAR const char *)0) { - m_name = std::strdup(GNoName); + m_name.setText(GNoName); } else { - m_name = std::strdup(name); + m_name.setText(name); } // Do initial clip to the maximum window size @@ -1527,12 +1527,4 @@ void CWindow::cleanup(void) delete m_iconBitMap; m_iconBitMap = (FAR NXWidgets::CRlePaletteBitmap *)0; } - - // Free memory - - if (m_name != (FAR char *)0) - { - std::free(m_name); - m_name = (FAR char *)0; - } } diff --git a/include/graphics/twm4nx/ciconwidget.hxx b/include/graphics/twm4nx/ciconwidget.hxx index d7efa73fd..ac5ca0fac 100644 --- a/include/graphics/twm4nx/ciconwidget.hxx +++ b/include/graphics/twm4nx/ciconwidget.hxx @@ -63,6 +63,7 @@ namespace NXWidgets { class IBitmap; // Forward reference + class CNxString; // Forward reference class CNxWidget; // Forward reference class CWidgetStyle; // Forward reference class CWidgetControl; // Forward reference diff --git a/include/graphics/twm4nx/cmainmenu.hxx b/include/graphics/twm4nx/cmainmenu.hxx new file mode 100644 index 000000000..1d153e6b9 --- /dev/null +++ b/include/graphics/twm4nx/cmainmenu.hxx @@ -0,0 +1,149 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/graphics/twm4nx/include/cmainmenu.hxx +// Twm4Nx main menu class +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef __APPS_INCLUDE_GRAPHICS_TWM4NX_CMAINMENU_HXX +#define __APPS_INCLUDE_GRAPHICS_TWM4NX_CMAINMENU_HXX + +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// + +#include + +///////////////////////////////////////////////////////////////////////////// +// Implementation Class Definition +///////////////////////////////////////////////////////////////////////////// + +namespace Twm4Nx +{ + class CTwm4Nx; // Forward Reference + class CMenus; // Forward Reference + class IApplication; // Forward Reference + struct SEventMsg; // Forward Reference + + /** + * This structure describes on Main Menu item. + */ + + struct SMainMenuItem + { + FAR struct SMainMenuItem *flink; /**< Forward link */ + FAR struct SMainMenuItem *blink; /**< Backward link */ + FAR IApplication *app; /**< Application information */ + }; + + /** + * The Twm4Nx main menu is present on a left click anwyere on the + * background (except for icons that also lie on the background). It + * supports starting of applications that are not inherently part of + * Twm4Nx. A registration method is provided that uses an instance of + * a class that derives from Twm4Nx::IApplication to provide all necessary + * support for a menu item. + */ + + class CMainMenu : public CTwm4NxEvent + { + private: + FAR CTwm4Nx *m_twm4nx; /**< Cached Twm4Nx session instance */ + FAR CMenus *m_mainMenu; /**< The main menu instance */ + FAR struct SMainMenuItem *m_appHead; /**< The head of the main menu item list */ + FAR struct SMainMenuItem *m_appTail; /**< The tail of the main menu item list */ + + /** + * Put an allocated entry into the main menu in name order + * + * @param mmitem The entry to insert + */ + + void insertEntry(FAR struct SMainMenuItem *mmitem); + + /** + * Remove an entry from an main menu + * + * @param mmitem the entry to remove + */ + + void removeEntry(FAR struct SMainMenuItem *mmitem); + + public: + + /** + * CMainMenu Constructor + * + * @param twm4nx The Twm4Nx session + */ + + CMainMenu(FAR CTwm4Nx *twm4nx); + + /** + * CMainMenu Destructor + */ + + ~CMainMenu(void); + + /** + * CMainMenu Initializer. This function performs the parts of the + * initialization that may fail. + * + * @return True if the main menu was properly initialized. false is + * return on any failure. + */ + + bool initialize(void); + + /** + * Register one main menu item + * + * @param app An instance of a class that derives from IApplication + * @return True if the menu item was properly added to the main menu. + * false is return on any failure. + */ + + bool addApplication(FAR IApplication *app); + + /** + * Handle MAIN MENU events. + * + * @param eventmsg. The received NxWidget WINDOW event message. + * @return True if the message was properly handled. false is + * return on any failure. + */ + + bool event(FAR struct SEventMsg *eventmsg); + }; +} + +#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_CMAINMENU_HXX diff --git a/include/graphics/twm4nx/cmenus.hxx b/include/graphics/twm4nx/cmenus.hxx index ba3952038..f7e95b263 100644 --- a/include/graphics/twm4nx/cmenus.hxx +++ b/include/graphics/twm4nx/cmenus.hxx @@ -52,6 +52,7 @@ #include "graphics/nxwidgets/cwidgeteventhandler.hxx" #include "graphics/nxwidgets/cwidgeteventargs.hxx" +#include "graphics/nxwidgets/cnxtkwindow.hxx" #include "graphics/twm4nx/ctwm4nxevent.hxx" @@ -83,7 +84,6 @@ namespace NXWidgets { - class CNxTkWindow; // Forward reference class CListBox; // Forward reference class CWidgetEventArgs; // Forward reference class CWidgetEventArgs; // Forward reference @@ -100,7 +100,7 @@ namespace Twm4Nx FAR struct SMenuItem *flink; /**< Forward link to next menu item */ FAR struct SMenuItem *blink; /**< Backward link previous menu item */ FAR CMenus *subMenu; /**< Menu root of a pull right menu */ - FAR char *text; /**< The text string for the menu item */ + FAR NXWidgets::CNxString text; /**< The text string for the menu item */ FAR CTwm4NxEvent *handler; /**< Application event handler */ uint16_t index; /**< Index of this menu item */ uint16_t event; /**< Menu selection event */ @@ -118,7 +118,7 @@ namespace Twm4Nx FAR struct SMenuItem *m_activeItem; /**< The active menu item */ FAR struct SMenuItem *m_menuHead; /**< First item in menu */ FAR struct SMenuItem *m_menuTail; /**< Last item in menu */ - FAR char *m_menuName; /**< The name of the menu */ + NXWidgets::CNxString m_menuName; /**< The name of the menu */ nxgl_coord_t m_entryHeight; /**< Menu entry height */ uint16_t m_nMenuItems; /**< Number of items in the menu */ uint8_t m_menuDepth; /**< Number of menus up */ @@ -271,10 +271,10 @@ namespace Twm4Nx * @result True is returned on success */ - bool initialize(FAR const char *name); + bool initialize(FAR NXWidgets::CNxString &name); /** - * Add an item to a root menu + * Add an item to a menu * * \param text The text to appear in the menu * \param subMenu The menu root if it is a pull-right entry @@ -283,7 +283,7 @@ namespace Twm4Nx * \param event The event to generate on menu item selection */ - bool addMenuItem(FAR const char *text, FAR CMenus *subMenu, + bool addMenuItem(FAR NXWidgets::CNxString &text, FAR CMenus *subMenu, FAR CTwm4NxEvent *handler, uint16_t event); /** diff --git a/include/graphics/twm4nx/ctwm4nx.hxx b/include/graphics/twm4nx/ctwm4nx.hxx index 2957063e3..3d96dfbf8 100644 --- a/include/graphics/twm4nx/ctwm4nx.hxx +++ b/include/graphics/twm4nx/ctwm4nx.hxx @@ -87,6 +87,7 @@ namespace Twm4Nx class CIconMgr; // Forward reference class CFonts; // Forward reference class CWindow; // Forward reference + class CMainMenu; // Forward reference class CResize; // Forward reference class CWindowFactory; // Forward reference class CResize; // Forward reference @@ -115,6 +116,7 @@ namespace Twm4Nx FAR CIconMgr *m_iconmgr; /**< The Default icon manager */ FAR CWindowFactory *m_factory; /**< The cached CWindowFactory instance */ FAR CFonts *m_fonts; /**< The cached Cfonts instance */ + FAR CMainMenu *m_mainMenu; /**< The cached CMainMenu instance */ FAR CResize *m_resize; /**< The cached CResize instance */ #if !defined(CONFIG_TWM4NX_NOKEYBOARD) || !defined(CONFIG_TWM4NX_NOMOUSE) @@ -275,7 +277,8 @@ namespace Twm4Nx /** * Return the session's CWindowFactory instance. * - * @return The contained instance of the CWindow instance this session. + * @return The contained instance of the CWindow instance this + * session. */ inline FAR CWindowFactory *getWindowFactory(void) @@ -286,7 +289,8 @@ namespace Twm4Nx /** * Return the session's CFonts instance. * - * @return The contained instance of the CMenus instance for this session. + * @return The contained instance of the CFonts instance for this + * session. */ inline FAR CFonts *getFonts(void) @@ -294,6 +298,18 @@ namespace Twm4Nx return m_fonts; } + /** + * Return the session's CMainMenu instance. + * + * @return The contained instance of the CMainMenu instance for this + * session. + */ + + inline FAR CMainMenu *getMainMenu(void) + { + return m_mainMenu; + } + /** * Return the session's CResize instance. * diff --git a/include/graphics/twm4nx/ctwm4nxevent.hxx b/include/graphics/twm4nx/ctwm4nxevent.hxx index e172db822..c5ddde154 100644 --- a/include/graphics/twm4nx/ctwm4nxevent.hxx +++ b/include/graphics/twm4nx/ctwm4nxevent.hxx @@ -34,23 +34,19 @@ // ///////////////////////////////////////////////////////////////////////////// -#ifndef __APPS_INCLUDE_GRAPHICS_TWM4NX_CTWM4NXEVNT_HXX -#define __APPS_INCLUDE_GRAPHICS_TWM4NX_CTWM4NXEVNT_HXX +#ifndef __APPS_INCLUDE_GRAPHICS_TWM4NX_CTWM4NXEVENT_HXX +#define __APPS_INCLUDE_GRAPHICS_TWM4NX_CTWM4NXEVENT_HXX -/**************************************************************************** - * Included Files - ****************************************************************************/ +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// #include #include -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Implementation Class Definition - ****************************************************************************/ +///////////////////////////////////////////////////////////////////////////// +// Implementation Class Definition +///////////////////////////////////////////////////////////////////////////// namespace Twm4Nx { @@ -88,4 +84,4 @@ namespace Twm4Nx }; } -#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_CTWM4NXEVNT_HXX +#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_CTWM4NXEVENT_HXX diff --git a/include/graphics/twm4nx/cwindow.hxx b/include/graphics/twm4nx/cwindow.hxx index 5550b116f..57bc3558d 100644 --- a/include/graphics/twm4nx/cwindow.hxx +++ b/include/graphics/twm4nx/cwindow.hxx @@ -108,6 +108,7 @@ namespace NXWidgets { + class CNxString; // Forward reference class CImage; // Forward reference class CLabel; // Forward reference struct SRlePaletteBitmap; // Forward reference @@ -132,7 +133,7 @@ namespace Twm4Nx // Primary Window - FAR char *m_name; /**< Name of the window */ + NXWidgets::CNxString m_name; /**< Name of the window */ FAR NXWidgets::CNxTkWindow *m_nxWin; /**< The contained NX primary window */ uint16_t m_zoom; /**< Window zoom: ZOOM_NONE or EVENT_RESIZE_* */ bool m_modal; /**< Window zoom: ZOOM_NONE or EVENT_RESIZE_* */ @@ -383,7 +384,7 @@ namespace Twm4Nx * Get the name of the window */ - inline FAR const char *getWindowName(void) + inline NXWidgets::CNxString getWindowName(void) { return m_name; } diff --git a/include/graphics/twm4nx/iapplication.hxx b/include/graphics/twm4nx/iapplication.hxx new file mode 100644 index 000000000..9818da1f0 --- /dev/null +++ b/include/graphics/twm4nx/iapplication.hxx @@ -0,0 +1,172 @@ +///////////////////////////////////////////////////////////////////////////// +// apps/include/graphics/twm4nx/iapplication.hxx +// Application/Main Menu Interface +// +// Copyright (C) 2019 Gregory Nutt. All rights reserved. +// Author: Gregory Nutt +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// 3. Neither the name NuttX nor the names of its contributors may be +// used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef __APPS_INCLUDE_GRAPHICS_TWM4NX_IAPPLICATION_HXX +#define __APPS_INCLUDE_GRAPHICS_TWM4NX_IAPPLICATION_HXX + +///////////////////////////////////////////////////////////////////////////// +// Included Files +///////////////////////////////////////////////////////////////////////////// + +#include +#include + +///////////////////////////////////////////////////////////////////////////// +// Abstract Base Classes +///////////////////////////////////////////////////////////////////////////// + +namespace NXWidgets +{ + class CNxString; // Forward reference +} + +namespace Twm4Nx +{ + class CTwm4Nx; // Forward reference + class CMenus; // Forward reference + class CTwm4NxEvent; // Forward reference + + /** + * Defines the interface of an application to the Main Menu. "Built-In" + * applications are started via CMainMenu. This interface class defines + * the interface requirements to add an application to the Main Menu. + */ + + class IApplication + { + public: + /** + * A virtual destructor is required in order to override the + * IApplication destructor. We do this because if we delete + * IApplication, we want the destructor of the class that inherits from + * IApplication to run, not this one. + */ + + virtual ~IApplication(void) + { + } + + /** + * Return the name of the application. This is the string that will + * appear in the Main Menu item. + * + * @param name The name of the application. + */ + + virtual void getName(const NXWidgets::CNxString &text) = 0; + + /** + * Return any submenu item associated with the menu entry. If a non- + * null value is returned, then this sub-menu will be brought up when + * the menu entry is selected. Otherwise, the start() method will be + * called. These two behaviors are mutually exlusive. + * + * NOTE: Both the start() and getSubMenu() return values are ignored + * if the event() method returns an event with recipient = + * EVENT_RECIPIENT_APP. In that case, the application will be fully + * responsible for handling the menu selection event. + * + * @return. A reference to any sub-menu that should be brought up if + * the menu item is selected. This must be null if the menu item + * does not bring up a sub-menu + */ + + virtual FAR CMenus *getSubMenu(void) = 0; + + /** + * This is the application start up function. This function will be + * called when its menu entry has been selected in order to start the + * application unless the behavior of the menu item is to bring up a + * sub-menu. In that case, this start-up function is never called. + * + * The Main Menu runs on the main Twm4Nx thread so this function will, + * typically, create a new thread to host the application. + * + * NOTE: Both the start() and getSubMenu() return values are ignored + * if the event() method returns an event with recipient = + * EVENT_RECIPIENT_APP. In that case, the application will be fully + * responsible for handling the menu selection event. + * + * @param twm4nx The Twm4Nx session object. Use with care! The CTwm4Nx + * logic runs on a different thread and some of the methods of the + * class may not be thread safe. + */ + + virtual void start(FAR CTwm4Nx *twm4nx) = 0; + + /** + * External applications may provide their own event handler that runs + * when the the menu item is selection. If so, then this method will + * return the instance of CTwm4NxEvent that will handle the event. + * + * NOTE: This handler is only used if the event returned by getEvent is + * destined for recipient EVENT_RECIPIENT_APP. Otherwise, the event + * handling is handling internally by Twm4Nx and this method will never + * be called. + * + * This method may return null in that case. It would be an error if + * this method returned null but the event() method returned a event + * destined for EVENT_RECIPIENT_APP. + * + * @return. A reference to an instance of the CTwm4NxWevent handler + * class or NULL if the event will be handled by Twm4Nx (i.e., the + * recipient is not EVENT_RECIPIENT_APP). + */ + + virtual FAR CTwm4NxEvent *getEventHandler(void) = 0; + + /** + * Get the Twm4Nx event that will be generated when the menu item is + * selected. All returned values are ignored unless the event recipient + * is EVENT_RECIPIENT_APP. Otherwise, the event EVENT_MAINMENU_SELECT + * is used and any subsequent menu item action, either bringing up + * a sub-menu or starting an application, will be performed by CMainMenu. + * + * This method may return zero in that case. It would be an error if + * this method returned an event with EVENT_RECIPIENT_APP but the + * getEventHandler() method returned null. + * + * @return. Either, (1) an event with recipient = EVENT_RECIPIENT_APP + * that will be generated when menu item is selected, or (2) any other + * value (preferabley zero) that indicates that standard, built-in + * event handling should be used. + */ + + virtual uint16_t getEvent(void) = 0; + }; +} + +#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_IAPPLICATION_HXX diff --git a/include/graphics/twm4nx/twm4nx_widgetevents.hxx b/include/graphics/twm4nx/twm4nx_widgetevents.hxx index 4a7a6e4cd..c69e031e0 100644 --- a/include/graphics/twm4nx/twm4nx_widgetevents.hxx +++ b/include/graphics/twm4nx/twm4nx_widgetevents.hxx @@ -87,11 +87,12 @@ namespace Twm4Nx EVENT_RECIPIENT_ICONWIDGET = 0x2000, /**< Icon Widget event */ EVENT_RECIPIENT_ICONMGR = 0x3000, /**< Icon Manager event */ EVENT_RECIPIENT_MENU = 0x4000, /**< Menu related event */ - EVENT_RECIPIENT_WINDOW = 0x5000, /**< Window related event */ - EVENT_RECIPIENT_TOOLBAR = 0x6000, /**< Toolbar related event */ - EVENT_RECIPIENT_BORDER = 0x7000, /**< Window border related event */ - EVENT_RECIPIENT_RESIZE = 0x8000, /**< Window resize event */ - EVENT_RECIPIENT_APP = 0x9000, /**< App received event via CTwn4NxEvent */ + EVENT_RECIPIENT_MAINMENU = 0x5000, /**< Menu related event */ + EVENT_RECIPIENT_WINDOW = 0x6000, /**< Window related event */ + EVENT_RECIPIENT_TOOLBAR = 0x7000, /**< Toolbar related event */ + EVENT_RECIPIENT_BORDER = 0x8000, /**< Window border related event */ + EVENT_RECIPIENT_RESIZE = 0x9000, /**< Window resize event */ + EVENT_RECIPIENT_APP = 0xa000, /**< App received event via CTwn4NxEvent */ EVENT_RECIPIENT_MASK = 0xf000, /**< Used to isolate recipient */ }; @@ -130,38 +131,42 @@ namespace Twm4Nx EVENT_MENU_TITLE = 0x4005, /**< REVISIT: Really an action not an event */ EVENT_MENU_ROOT = 0x4006, /**< REVISIT: Popup root menu */ + // Recipient == MAINMENU + + EVENT_MAINMENU_SELECT = 0x5000, /**< Main menu item selection */ + // Recipient == WINDOW - EVENT_WINDOW_POLL = 0x5000, /**< Poll window for widget events */ - EVENT_WINDOW_FOCUS = 0x5001, /**< Enter modal state */ - EVENT_WINDOW_UNFOCUS = 0x5002, /**< Exit modal state */ - EVENT_WINDOW_RAISE = 0x5003, /**< Raise window to the top of the heirarchy */ - EVENT_WINDOW_LOWER = 0x5004, /**< Lower window to the bottom of the heirarchy */ - EVENT_WINDOW_DEICONIFY = 0x5005, /**< De-iconify and raise window */ - EVENT_WINDOW_DRAG = 0x5006, /**< Drag window */ - EVENT_WINDOW_DELETE = 0x5007, /**< Delete window */ + EVENT_WINDOW_POLL = 0x6000, /**< Poll window for widget events */ + EVENT_WINDOW_FOCUS = 0x6001, /**< Enter modal state */ + EVENT_WINDOW_UNFOCUS = 0x6002, /**< Exit modal state */ + EVENT_WINDOW_RAISE = 0x6003, /**< Raise window to the top of the heirarchy */ + EVENT_WINDOW_LOWER = 0x6004, /**< Lower window to the bottom of the heirarchy */ + EVENT_WINDOW_DEICONIFY = 0x6005, /**< De-iconify and raise window */ + EVENT_WINDOW_DRAG = 0x6006, /**< Drag window */ + EVENT_WINDOW_DELETE = 0x6007, /**< Delete window */ // Recipient == TOOLBAR - EVENT_TOOLBAR_GRAB = 0x6000, /**< Click on title widget */ - EVENT_TOOLBAR_UNGRAB = 0x6001, /**< Release click on title widget */ - EVENT_TOOLBAR_MENU = 0x6002, /**< Toolbar menu button released */ - EVENT_TOOLBAR_MINIMIZE = 0x6003, /**< Toolbar minimize button released */ - EVENT_TOOLBAR_RESIZE = 0x6004, /**< Toolbar resize button released */ - EVENT_TOOLBAR_TERMINATE = 0x6005, /**< Toolbar delete button released */ + EVENT_TOOLBAR_GRAB = 0x7000, /**< Click on title widget */ + EVENT_TOOLBAR_UNGRAB = 0x7001, /**< Release click on title widget */ + EVENT_TOOLBAR_MENU = 0x7002, /**< Toolbar menu button released */ + EVENT_TOOLBAR_MINIMIZE = 0x7003, /**< Toolbar minimize button released */ + EVENT_TOOLBAR_RESIZE = 0x7004, /**< Toolbar resize button released */ + EVENT_TOOLBAR_TERMINATE = 0x7005, /**< Toolbar delete button released */ // Recipient == BORDER // Recipient == RESIZE - EVENT_RESIZE_START = 0x8000, /**< Start window resize */ - EVENT_RESIZE_VERTZOOM = 0x8001, /**< Zoom vertically only */ - EVENT_RESIZE_HORIZOOM = 0x8002, /**< Zoom horizontally only */ - EVENT_RESIZE_FULLZOOM = 0x8003, /**< Zoom both vertically and horizontally */ - EVENT_RESIZE_LEFTZOOM = 0x8004, /**< Zoom left only */ - EVENT_RESIZE_RIGHTZOOM = 0x8005, /**< Zoom right only */ - EVENT_RESIZE_TOPZOOM = 0x8006, /**< Zoom top only */ - EVENT_RESIZE_BOTTOMZOOM = 0x8007, /**< Zoom bottom only */ + EVENT_RESIZE_START = 0x9000, /**< Start window resize */ + EVENT_RESIZE_VERTZOOM = 0x9001, /**< Zoom vertically only */ + EVENT_RESIZE_HORIZOOM = 0x9002, /**< Zoom horizontally only */ + EVENT_RESIZE_FULLZOOM = 0x9003, /**< Zoom both vertically and horizontally */ + EVENT_RESIZE_LEFTZOOM = 0x9004, /**< Zoom left only */ + EVENT_RESIZE_RIGHTZOOM = 0x9005, /**< Zoom right only */ + EVENT_RESIZE_TOPZOOM = 0x9006, /**< Zoom top only */ + EVENT_RESIZE_BOTTOMZOOM = 0x9007, /**< Zoom bottom only */ // Recipient == APP // All application defined events must (1) use recepient == EVENT_RECIPIENT_APP,