diff --git a/graphics/nxwidgets/src/cbuttonarray.cxx b/graphics/nxwidgets/src/cbuttonarray.cxx index 769555eac..0d25d455a 100644 --- a/graphics/nxwidgets/src/cbuttonarray.cxx +++ b/graphics/nxwidgets/src/cbuttonarray.cxx @@ -125,11 +125,62 @@ CButtonArray::~CButtonArray(void) delete [] m_buttonText; } +/** + * Resize the array of buttons. Button labels will be removed and will + * have to be reapplied in the new geometry. + * + * @param buttonColumns The number of buttons in one row of the button array + * @param buttonRows The number of buttons in one column of the button array + * @param buttonWidth The width of one button + * @param buttonHeight The height of one button + */ + +bool CButtonArray::resizeArray(uint8_t buttonColumns, uint8_t buttonRows, + nxgl_coord_t buttonWidth, nxgl_coord_t buttonHeight) +{ + setRaisesEvents(false); + disableDrawing(); + + // Delete the current array of CNxString instances + + delete [] m_buttonText; + + // Update configuration + + m_buttonRows = buttonRows; + m_buttonColumns = buttonColumns; + m_buttonWidth = buttonWidth; + m_buttonHeight = buttonHeight; + + // Reset the cursor position if necessary + + if (m_cursorColumn >= m_buttonColumns) + { + m_cursorColumn = m_buttonColumns - 1; + } + + if (m_cursorRow >= m_buttonRows) + { + m_cursorRow = m_buttonRows - 1; + } + + // Allocate the new text array + + m_buttonText = new CNxString[m_buttonRows * m_buttonColumns]; + + // And go active again with a resized button array (with no labels) + + enableDrawing(); + redraw(); + setRaisesEvents(true); + return true; +} + /** * Returns the string shown in the label. * * @param column The column index of the button of interest -* @param row The row index of the button of interest + * @param row The row index of the button of interest * @return The label's text. */ diff --git a/graphics/nxwidgets/src/cnxstring.cxx b/graphics/nxwidgets/src/cnxstring.cxx index 21491e78a..692ed2d93 100644 --- a/graphics/nxwidgets/src/cnxstring.cxx +++ b/graphics/nxwidgets/src/cnxstring.cxx @@ -731,6 +731,13 @@ int CNxString::compareTo(const CNxString &string) const getLength()); } +int CNxString::compareTo(FAR const char *string) const +{ + return memcmp((FAR const char*)m_text, + (FAR const char*)string, + getLength()); +} + /** * Allocate memory for the string. * diff --git a/graphics/twm4nx/README.txt b/graphics/twm4nx/README.txt index 4fd37844c..fa79de369 100644 --- a/graphics/twm4nx/README.txt +++ b/graphics/twm4nx/README.txt @@ -45,4 +45,6 @@ STATUS 4. Widget events are only partially integrated. A lot more needs to be done. A partial change to the event system that hints at the redesign is in place but it is far from complete. + 2019-04-26: Added button arrays for implementation of Icon Manager. + Integrated event handling into CWindows and CIconMgr. diff --git a/graphics/twm4nx/src/ciconmgr.cxx b/graphics/twm4nx/src/ciconmgr.cxx index 507d1329b..997a59ca1 100644 --- a/graphics/twm4nx/src/ciconmgr.cxx +++ b/graphics/twm4nx/src/ciconmgr.cxx @@ -52,6 +52,8 @@ #include "graphics/nxwidgets/cnxwindow.hxx" #include "graphics/nxwidgets/cnxfont.hxx" +#include "graphics/nxwidgets/cnxstring.hxx" +#include "graphics/nxwidgets/cbuttonarray.hxx" #include #include @@ -81,17 +83,17 @@ using namespace Twm4Nx; * @param ncolumns The number of columns this icon manager has */ -CIconMgr::CIconMgr(CTwm4Nx *twm4nx, int ncolumns) +CIconMgr::CIconMgr(CTwm4Nx *twm4nx, uint8_t ncolumns) { m_twm4nx = twm4nx; // Cached the Twm4Nx session m_head = (FAR struct SWindowEntry *)0; // Head of the winow list m_tail = (FAR struct SWindowEntry *)0; // Tail of the winow list m_active = (FAR struct SWindowEntry *)0; // No active window m_window = (FAR CWindow *)0; // No icon manager Window - m_columns = ncolumns; - m_currows = 0; - m_curcolumns = 0; - m_count = 0; + m_maxColumns = ncolumns; // Max columns per row + m_nrows = 0; // No rows yet + m_ncolumns = 0; // No columns yet + m_nWindows = 0; // No windows yet } /** @@ -100,14 +102,19 @@ CIconMgr::CIconMgr(CTwm4Nx *twm4nx, int ncolumns) CIconMgr::~CIconMgr(void) { - // Free memory allocations - // Free the icon manager window if (m_window != (FAR CWindow *)0) { delete m_window; } + + // Free the button array + + if (m_buttons != (FAR NXWidgets::CButtonArray *)0) + { + delete m_buttons; + } } /** @@ -171,25 +178,16 @@ bool CIconMgr::add(FAR CWindow *cwin) wentry->active = false; wentry->down = false; wentry->cwin = cwin; - - FAR CFonts *fonts = m_twm4nx->getFonts(); - FAR NXWidgets::CNxFont *iconManagerFont = fonts->getIconManagerFont(); - - wentry->me = m_count; - wentry->pos.x = -1; - wentry->pos.y = -1; + wentry->pos.x = -1; + wentry->pos.y = -1; // Insert the new entry into the list insertEntry(wentry, cwin); - // The height of one row is determined (mostly) by the fond height + // The height of one row is determined (mostly) by the font height - int rowHeight = iconManagerFont->getHeight() + 10; - if (rowHeight < (CONFIG_TWM4NX_ICONMGR_IMAGE.width + 4)) - { - rowHeight = CONFIG_TWM4NX_ICONMGR_IMAGE.width + 4; - } + nxgl_coord_t rowHeight = getRowHeight(); // Increase the icon window size @@ -200,13 +198,13 @@ bool CIconMgr::add(FAR CWindow *cwin) } else { - windowSize.h = rowHeight * m_count; + windowSize.h = rowHeight * m_nWindows; m_window->setWindowSize(&windowSize); } // Increment the window count - m_count++; + m_nWindows++; // Pack the windows @@ -238,155 +236,25 @@ void CIconMgr::remove(FAR struct SWindow *win) removeEntry(wentry); - // Destroy the button array widget -#warning Missing logic - // Destroy the window CWindowFactory *factory = m_twm4nx->getWindowFactory(); factory->destroyWindow(wentry->cwin); - m_count -= 1; + m_nWindows--; std::free(wentry); pack(); } } -/** - * Move the pointer around in an icon manager - * - * @param dir one of the following: - * - EVENT_ICONMGR_FORWARD: Forward in the window list - * - EVENT_ICONMGR_BACK: Backward in the window list - * - EVENT_ICONMGR_UP: Up one row - * - EVENT_ICONMGR_DOWN: Down one row - * - EVENT_ICONMGR_LEFT: Left one column - * - EVENT_ICONMGR_RIGHT: Right one column - */ - -void CIconMgr::move(int dir) -{ - if (!m_active) - { - return; - } - - int curRow = m_active->row; - int curCol = m_active->col; - - int rowIncr = 0; - int colIncr = 0; - bool gotIt = false; - - FAR struct SWindowEntry *wentry = (FAR struct SWindowEntry *)0; - - switch (dir) - { - case EVENT_ICONMGR_FORWARD: - if ((wentry = m_active->flink) == (FAR struct SWindowEntry *)0) - { - wentry = m_head; - } - - gotIt = true; - break; - - case EVENT_ICONMGR_BACK: - if ((wentry = m_active->blink) == (FAR struct SWindowEntry *)0) - { - wentry = m_tail; - } - - gotIt = true; - break; - - case EVENT_ICONMGR_UP: - rowIncr = -1; - break; - - case EVENT_ICONMGR_DOWN: - rowIncr = 1; - break; - - case EVENT_ICONMGR_LEFT: - colIncr = -1; - break; - - case EVENT_ICONMGR_RIGHT: - colIncr = 1; - break; - } - - // If gotIt is false ast this point then we got a left, right, up, or down, - // command. - - int newRow = curRow; - int newCol = curCol; - - while (!gotIt) - { - newRow += rowIncr; - newCol += colIncr; - - if (newRow < 0) - { - newRow = m_currows - 1; - } - - if (newCol < 0) - { - newCol = m_curcolumns - 1; - } - - if (newRow >= (int)m_currows) - { - newRow = 0; - } - - if (newCol >= (int)m_curcolumns) - { - newCol = 0; - } - - // Now let's go through the list to see if there is an entry with this - // new position. - - for (wentry = m_head; wentry != NULL; wentry = wentry->flink) - { - if (wentry->row == newRow && wentry->col == newCol) - { - gotIt = true; - break; - } - } - } - - if (!gotIt) - { - gwarn("WARNING: unable to find window (%d, %d) in icon manager\n", - newRow, newCol); - return; - } - - // raise the frame so the icon manager is visible -} - /** * Pack the icon manager windows following an addition or deletion */ void CIconMgr::pack(void) { - FAR CFonts *fonts = m_twm4nx->getFonts(); - FAR NXWidgets::CNxFont *iconManagerFont = fonts->getIconManagerFont(); - struct nxgl_size_s colsize; - - colsize.h = iconManagerFont->getHeight() + 10; - if (colsize.h < (CONFIG_TWM4NX_ICONMGR_IMAGE.height + 4)) - { - colsize.h = CONFIG_TWM4NX_ICONMGR_IMAGE.height + 4; - } + colsize.h = getRowHeight(); struct nxgl_size_s windowSize; if (!m_window->getWindowSize(&windowSize)) @@ -395,13 +263,13 @@ void CIconMgr::pack(void) return; } - colsize.w = windowSize.w / m_columns; + colsize.w = windowSize.w / m_maxColumns; int rowIncr = colsize.h; int colIncr = colsize.w; int row = 0; - int col = m_columns; + int col = m_maxColumns; int maxcol = 0; FAR struct SWindowEntry *wentry; @@ -411,10 +279,9 @@ void CIconMgr::pack(void) wentry != (FAR struct SWindowEntry *)0; i++, wentry = wentry->flink) { - wentry->me = i; - if (++col >= (int)m_columns) + if (++col >= (int)m_maxColumns) { - col = 0; + col = 0; row += 1; } @@ -424,11 +291,11 @@ void CIconMgr::pack(void) } struct nxgl_point_s newpos; - newpos.x = col * colIncr; - newpos.y = (row - 1) * rowIncr; + newpos.x = col * colIncr; + newpos.y = (row - 1) * rowIncr; - wentry->row = row - 1; - wentry->col = col; + wentry->row = row - 1; + wentry->col = col; // If the position or size has not changed, don't touch it @@ -446,53 +313,85 @@ void CIconMgr::pack(void) } } - maxcol += 1; - m_currows = row; - m_curcolumns = maxcol; + maxcol++; - // The height of one row is determined (mostly) by the fond height + // Check if there is a change in the dimension of the button array - int rowHeight = iconManagerFont->getHeight() + 10; - if (rowHeight < (CONFIG_TWM4NX_ICONMGR_IMAGE.width + 4)) + if (m_nrows != row && m_ncolumns != maxcol) { - rowHeight = CONFIG_TWM4NX_ICONMGR_IMAGE.width + 4; + // Yes.. remember the new size + + m_nrows = row; + m_ncolumns = maxcol; + + // The height of one row is determined (mostly) by the font height + + windowSize.h = getRowHeight() * m_nWindows; + if (!m_window->getWindowSize(&windowSize)) + { + gerr("ERROR: getWindowSize() failed\n"); + return; + } + + if (windowSize.h == 0) + { + windowSize.h = rowIncr; + } + + struct nxgl_size_s newsize; + newsize.w = maxcol * colIncr; + + if (newsize.w == 0) + { + newsize.w = colIncr; + } + + newsize.h = windowSize.h; + + if (!m_window->setWindowSize(&newsize)) + { + gerr("ERROR: setWindowSize() failed\n"); + return; + } + + // Resize the button array + + nxgl_coord_t buttonWidth = newsize.w / m_maxColumns; + nxgl_coord_t buttonHeight = newsize.w / m_nrows; + + if (!m_buttons->resizeArray(m_maxColumns, m_nrows, + buttonWidth, buttonHeight)) + { + gerr("ERROR: CButtonArray::resizeArray failed\n"); + return; + } + + // Re-apply all of the button labels + + int rowndx = 0; + int colndx = 0; + + for (FAR struct SWindowEntry *swin = m_head; + swin != (FAR struct SWindowEntry *)0; + swin = swin->flink) + { + // Get the window name as an NWidgets::CNxString + + NXWidgets::CNxString string = swin->cwin->getWindowName(); + + // Apply the window name to the button + + m_buttons->setText(colndx, rowndx, string); + + // Increment the column, rolling over to the next row if necessary + + if (++colndx >= m_maxColumns) + { + colndx = 0; + rowndx++; + } + } } - - windowSize.h = rowHeight * m_count; - m_window->setWindowSize(&windowSize); - - if (windowSize.h == 0) - { - windowSize.h = rowIncr; - } - - struct nxgl_size_s newsize; - newsize.w = maxcol * colIncr; - - if (newsize.w == 0) - { - newsize.w = colIncr; - } - - newsize.h = windowSize.h; - - if (!m_window->setWindowSize(&newsize)) - { - return; - } - - // Get the net size of the containing frame - - struct nxgl_size_s frameSize; - m_window->windowToFrameSize(&windowSize, &frameSize); - - struct nxgl_point_s framePos; - m_window->getFramePosition(&framePos); - - // Resize the frame - - FAR CResize *resize = m_twm4nx->getResize(); - resize->setupWindow(m_window, &framePos, &frameSize); } /** @@ -546,35 +445,6 @@ bool CIconMgr::event(FAR struct SEventMsg *msg) switch (msg->eventID) { - case EVENT_ICONMGR_UP: - case EVENT_ICONMGR_DOWN: - case EVENT_ICONMGR_LEFT: - case EVENT_ICONMGR_RIGHT: - case EVENT_ICONMGR_FORWARD: - case EVENT_ICONMGR_BACK: - { - move(msg->eventID); - } - break; - - case EVENT_ICONMGR_SHOWPARENT: // Raise Icon manager parent window - { - m_window->deIconify(); - } - break; - - case EVENT_ICONMGR_HIDE: // Hide the Icon Manager - { - hide(); - } - break; - - case EVENT_ICONMGR_SORT: // Sort the Icon Manager - { - sort(); - } - break; - default: ret = false; break; @@ -583,6 +453,26 @@ bool CIconMgr::event(FAR struct SEventMsg *msg) return ret; } +/** + * Return the height of one row + * + * @return The height of one row + */ + +nxgl_coord_t CIconMgr::getRowHeight(void) +{ + FAR CFonts *fonts = m_twm4nx->getFonts(); + FAR NXWidgets::CNxFont *iconManagerFont = fonts->getIconManagerFont(); + + nxgl_coord_t rowHeight = iconManagerFont->getHeight() + 10; + if (rowHeight < (CONFIG_TWM4NX_ICONMGR_IMAGE.width + 4)) + { + rowHeight = CONFIG_TWM4NX_ICONMGR_IMAGE.width + 4; + } + + return rowHeight; +} + /** * Create and initialize the icon manager window * @@ -634,8 +524,66 @@ bool CIconMgr::createWindow(FAR const char *prefix) bool CIconMgr::createButtonArray(void) { -#warning Missing logic - return false; + // Create a Widget control instance for the window using the default style + // for now. CWindowEvent derives from CWidgetControl. + // REVISIT: Create the style, using the selected colors. + + FAR CWindowEvent *control = new CWindowEvent(m_twm4nx); + if (control == (FAR CWindowEvent *)0) + { + return false; + } + + // Get the width of the window + + struct nxgl_size_s windowSize; + if (!m_window->getWindowSize(&windowSize)) + { + gerr("ERROR: Failed to get window size\n"); + delete control; + return false; + } + + // The button must be positioned at the upper left of the window + + struct nxgl_point_s arrayPos; + m_window->getWindowPosition(&arrayPos); + + // Create the button array + // REVISIT: Hmm.. Button array cannot be dynamically resized! + + uint8_t nrows = m_nrows > 0 ? m_nrows : 1; + + nxgl_coord_t buttonWidth = windowSize.w / m_maxColumns; + nxgl_coord_t buttonHeight = windowSize.w / nrows; + + // Now we have enough information to create the button array + + m_buttons = new NXWidgets::CButtonArray(control, + arrayPos.x, arrayPos.y, + m_maxColumns, nrows, + buttonWidth, buttonHeight); + if (m_buttons == (FAR NXWidgets::CButtonArray *)0) + { + gerr("ERROR: Failed to get window size\n"); + delete control; + return false; + } + + // Configure the button array widget + + FAR CFonts *fonts = m_twm4nx->getFonts(); + FAR NXWidgets::CNxFont *iconManagerFont = fonts->getIconManagerFont(); + + m_buttons->setFont(iconManagerFont); + m_buttons->setBorderless(true); + m_buttons->disableDrawing(); + m_buttons->setRaisesEvents(false); + + // Register to get events from the mouse clicks on the image + + m_buttons->addWidgetEventHandler(this); + return true; } /** @@ -755,3 +703,54 @@ void CIconMgr::freeWEntry(FAR struct SWindowEntry *wentry) free(wentry); } + +/** + * Handle a widget action event. This will be a button pre-release event. + * + * @param e The event data. + */ + +void CIconMgr::handleActionEvent(const NXWidgets::CWidgetEventArgs &e) +{ + // A button should now be clicked + + int column; + int row; + + if (m_buttons->isButtonClicked(column, row)) + { + // Get the text associated with this button + + const NXWidgets::CNxString string = m_buttons->getText(column, row); + + // Now find the window with this name + + for (FAR struct SWindowEntry *swin = m_head; + swin != (FAR struct SWindowEntry *)0; + swin = swin->flink) + { + // Check if the button string is the same as the window name + + if (string.compareTo(swin->cwin->getWindowName()) == 0) + { + // Got it. Is the window Iconified? + + if (swin->cwin->isIconified()) + { + // Yes, de-Iconify it + + swin->cwin->deIconify(); + } + else + { + // Otherwise, raise the window to the top of the heirarchy + + swin->cwin->raiseWindow(); + } + + break; + } + } + } +} + diff --git a/graphics/twm4nx/src/cmenus.cxx b/graphics/twm4nx/src/cmenus.cxx index 660149090..d88023887 100644 --- a/graphics/twm4nx/src/cmenus.cxx +++ b/graphics/twm4nx/src/cmenus.cxx @@ -323,10 +323,9 @@ bool CMenus::event(FAR struct SEventMsg *eventmsg) newmsg.eventID = item->func; newmsg.pos.x = eventmsg->pos.x; newmsg.pos.y = eventmsg->pos.y; + newmsg.delta.x = 0; + newmsg.delta.y = 0; newmsg.context = eventmsg->context; - newmsg.pulldown = eventmsg->pulldown; - newmsg.action = item->action; - newmsg.nxwin = eventmsg->nxwin; newmsg.obj = eventmsg->obj; // NOTE that we cannot block because we are on the same thread diff --git a/graphics/twm4nx/src/cresize.cxx b/graphics/twm4nx/src/cresize.cxx index 74132b333..6745bfbf7 100644 --- a/graphics/twm4nx/src/cresize.cxx +++ b/graphics/twm4nx/src/cresize.cxx @@ -661,7 +661,7 @@ void CResize::endResize(FAR CWindow *cwin) CIconMgr *iconMgr = cwin->getIconMgr(); DEBUGASSERT(iconMgr != (CIconMgr *)0); - unsigned int currcol = iconMgr->getCurrColumn(); + unsigned int currcol = iconMgr->getNumberOfColumns(); if (currcol == 0) { currcol = 1; @@ -671,7 +671,7 @@ void CResize::endResize(FAR CWindow *cwin) iconMgr->getSize(&iconMgrSize); iconMgrSize.w = (unsigned int) - ((m_dragsize.w * (unsigned long)iconMgr->getColumns()) / currcol); + ((m_dragsize.w * (unsigned long)iconMgr->getDisplayColumns()) / currcol); cwin->resizeFrame(&iconMgrSize, &pos); iconMgr->pack(); @@ -950,7 +950,7 @@ bool CResize::event(FAR struct SEventMsg *eventmsg) if (eventmsg->context == EVENT_CONTEXT_FRAME || eventmsg->context == EVENT_CONTEXT_WINDOW || - eventmsg->context == EVENT_CONTEXT_TITLE) + eventmsg->context == EVENT_CONTEXT_TOOLBAR) { resizeFromCenter(cwin); } diff --git a/graphics/twm4nx/src/cwindow.cxx b/graphics/twm4nx/src/cwindow.cxx index 78dd3a270..5418c1a89 100644 --- a/graphics/twm4nx/src/cwindow.cxx +++ b/graphics/twm4nx/src/cwindow.cxx @@ -80,24 +80,42 @@ #include "graphics/twm4nx/twm4nx_cursor.hxx" ///////////////////////////////////////////////////////////////////////////// -// Private Data +// Private Types ///////////////////////////////////////////////////////////////////////////// using namespace Twm4Nx; -// Association of configured bitmaps with buttons - -static FAR const NXWidgets::SRlePaletteBitmap *GTbBitmaps[NTOOLBAR_BUTTONS] = +struct SToolbarInfo { - &CONFIG_TWM4NX_MENU_IMAGE, // MENU_BUTTON (first on left) - &CONFIG_TWM4NX_TERMINATE_IMAGE, // DELETE_BUTTON (first on right) - &CONFIG_TWM4NX_RESIZE_IMAGE, // RESIZE_BUTTON - &CONFIG_TWM4NX_MINIMIZE_IMAGE // MINIMIZE_BUTTON + FAR const NXWidgets::SRlePaletteBitmap *bitmap; /**< Bitmap configured for button */ + bool rightSide; /**< True: Button packed on the right */ + uint16_t event; /**< Event when button released */ }; -static bool GButtonRightSide[NTOOLBAR_BUTTONS] = +///////////////////////////////////////////////////////////////////////////// +// Private Data +///////////////////////////////////////////////////////////////////////////// + +// This array provides a static description of the toolbar buttons + +struct SToolbarInfo GToolBarInfo[NTOOLBAR_BUTTONS] = { - false, true, true, true, + [MENU_BUTTON] = + { + &CONFIG_TWM4NX_MENU_IMAGE, false, EVENT_TOOLBAR_MENU + }, + [DELETE_BUTTON] = + { + &CONFIG_TWM4NX_TERMINATE_IMAGE, true, EVENT_TOOLBAR_TERMINATE + }, + [RESIZE_BUTTON] = + { + &CONFIG_TWM4NX_RESIZE_IMAGE, true, EVENT_TOOLBAR_RESIZE + }, + [MINIMIZE_BUTTON] = + { + &CONFIG_TWM4NX_MINIMIZE_IMAGE, true, EVENT_TOOLBAR_MINIMIZE + } }; ///////////////////////////////////////////////////////////////////////////// @@ -184,7 +202,7 @@ bool CWindow::initialize(FAR const char *name, FAR const char *mqname = m_twm4nx->getEventQueueName(); - m_eventq = mq_open(mqname, O_WRONLY); + m_eventq = mq_open(mqname, O_WRONLY | O_NONBLOCK); if (m_eventq == (mqd_t)-1) { gerr("ERROR: Failed open message queue '%s': %d\n", @@ -474,17 +492,16 @@ void CWindow::deIconify(void) bool CWindow::event(FAR struct SEventMsg *eventmsg) { - FAR NXWidgets::CNxTkWindow *nxwin = eventmsg->nxwin; bool success = true; switch (eventmsg->eventID) { case EVENT_WINDOW_RAISE: // Raise window to the top of the heirarchy - nxwin->raise(); // Could be the main or the icon window + m_nxWin->raise(); // Could be the main or the icon window break; case EVENT_WINDOW_LOWER: // Lower window to the bottom of the heirarchy - nxwin->lower(); // Could be the main or the icon window + m_nxWin->lower(); // Could be the main or the icon window break; case EVENT_WINDOW_POPUP: // De-iconify and raise the main window @@ -519,7 +536,7 @@ bool CWindow::event(FAR struct SEventMsg *eventmsg) // drains all of the message events. We will get the // EVENT_WINDOW_DELETE event at that point - NXWidgets::CWidgetControl *control = nxwin->getWidgetControl(); + NXWidgets::CWidgetControl *control = m_nxWin->getWidgetControl(); nxtk_block(control->getWindowHandle(), (FAR void *)m_nxWin); } @@ -640,7 +657,7 @@ bool CWindow::getToolbarHeight(FAR const char *name) for (int btindex = 0; btindex < NTOOLBAR_BUTTONS; btindex++) { - nxgl_coord_t btnHeight = GTbBitmaps[btindex]->height; + nxgl_coord_t btnHeight = GToolBarInfo[btindex].bitmap->height; if (btnHeight > m_tbHeight) { m_tbHeight = btnHeight; @@ -698,7 +715,7 @@ bool CWindow::updateToolbarLayout(void) m_tbRightX = 0; for (int btindex = 0; btindex < NTOOLBAR_BUTTONS; btindex++) { - if (GButtonRightSide[btindex]) + if (GToolBarInfo[btindex].rightSide) { FAR NXWidgets::CImage *cimage = m_tbButtons[btindex]; @@ -799,7 +816,8 @@ bool CWindow::createToolbarButtons(void) for (int btindex = 0; btindex < NTOOLBAR_BUTTONS; btindex++) { - FAR const NXWidgets::SRlePaletteBitmap *sbitmap = GTbBitmaps[btindex]; + FAR const NXWidgets::SRlePaletteBitmap *sbitmap = + GToolBarInfo[btindex].bitmap; #ifdef CONFIG_TWM4NX_TOOLBAR_ICONSCALE // Create a CScaledBitmap to scale the bitmap icon @@ -817,6 +835,7 @@ bool CWindow::createToolbarButtons(void) return false; } #endif + // Create the image. The image will serve as button since it // can detect clicks and release just like a button. @@ -885,7 +904,7 @@ bool CWindow::createToolbarButtons(void) // Pack on the left or right horizontally - if (GButtonRightSide[btindex]) + if (GToolBarInfo[btindex].rightSide) { m_tbRightX -= (cimage->getWidth() + CONFIG_TWM4NX_TOOLBAR_HSPACING); pos.x = m_tbRightX; @@ -943,12 +962,9 @@ bool CWindow::createToolbarTitle(FAR const char *name) titlePos.x = m_tbLeftX + CONFIG_TWM4NX_FRAME_VSPACING; titlePos.y = 0; - // Create the widget control (with the window messenger) using the default style - - // REVISIT: Create the style, using the selected colors. - // Create a Widget control instance for the window using the default style // for now. CWindowEvent derives from CWidgetControl. + // REVISIT: Create the style, using the selected colors. FAR CWindowEvent *control = new CWindowEvent(m_twm4nx); if (control == (FAR CWindowEvent *)0) @@ -984,6 +1000,49 @@ bool CWindow::createToolbarTitle(FAR const char *name) return true; } +/** + * After the toolbar was grabbed, it may be dragged then dropped, or it + * may be simply "un-grabbed". Both cases are handled here. + * + * NOTE: Unlike the other event handlers, this does NOT override any + * virtual event handling methods. It just combines some common event- + * handling logic. + * + * @param e The event data. + */ + +void CWindow::handleUngrabEvent(const NXWidgets::CWidgetEventArgs &e) +{ + // Exit the dragging state + + m_drag = false; + + // Generate the un-grab event + + struct SEventMsg msg; + msg.eventID = EVENT_TOOLBAR_UNGRAB; + msg.pos.x = e.getX(); + msg.pos.y = e.getY(); + msg.delta.x = 0; + msg.delta.y = 0; + msg.context = EVENT_CONTEXT_TOOLBAR; + msg.obj = (FAR void *)this; + + // NOTE that we cannot block because we are on the same thread + // as the message reader. If the event queue becomes full then + // we have no other option but to lose events. + // + // I suppose we could recurse and call Twm4Nx::dispatchEvent at + // the risk of runawy stack usage. + + int ret = mq_send(m_eventq, (FAR const char *)&msg, + sizeof(struct SEventMsg), 100); + if (ret < 0) + { + gerr("ERROR: mq_send failed: %d\n", ret); + } +} + /** * Override the mouse button drag event. * @@ -995,9 +1054,32 @@ void CWindow::handleDragEvent(const NXWidgets::CWidgetEventArgs &e) // We are interested only the the drag event on the title box while we are // in the dragging state. - if (m_drag) + if (m_drag && m_tbTitle->isBeingDragged()) { -#warning Missing logic + // Generate the event + + struct SEventMsg msg; + msg.eventID = EVENT_WINDOW_DRAG; + msg.pos.x = e.getX(); + msg.pos.y = e.getY(); + msg.delta.x = e.getVX(); + msg.delta.y = e.getVY(); + msg.context = EVENT_CONTEXT_TOOLBAR; + msg.obj = (FAR void *)this; + + // NOTE that we cannot block because we are on the same thread + // as the message reader. If the event queue becomes full then + // we have no other option but to lose events. + // + // I suppose we could recurse and call Twm4Nx::dispatchEvent at + // the risk of runawy stack usage. + + int ret = mq_send(m_eventq, (FAR const char *)&msg, + sizeof(struct SEventMsg), 100); + if (ret < 0) + { + gerr("ERROR: mq_send failed: %d\n", ret); + } } } @@ -1011,10 +1093,16 @@ void CWindow::handleDropEvent(const NXWidgets::CWidgetEventArgs &e) { // We are interested only the the drag drop event on the title box while we // are in the dragging state. + // + // When the Drop Event is received, both isClicked and isBeingDragged() + // will return false. It is sufficient to verify that the isClicked() is + // not true to exit the drag. - if (m_drag) + if (m_drag && !m_tbTitle->isClicked()) { -#warning Missing logic + // Yes.. handle the drop event + + handleUngrabEvent(e); } } @@ -1026,11 +1114,56 @@ void CWindow::handleDropEvent(const NXWidgets::CWidgetEventArgs &e) void CWindow::handleKeyPressEvent(const NXWidgets::CWidgetEventArgs &e) { - // We are interested only the the press event on the title box + // We are interested only the the press event on the title box and + // only if we are not already dragging the window - if (!m_drag) + if (!m_drag && m_tbTitle->isClicked()) { -#warning Missing logic + // Generate the event + + struct SEventMsg msg; + msg.eventID = EVENT_TOOLBAR_GRAB; + msg.pos.x = e.getX(); + msg.pos.y = e.getY(); + msg.delta.x = 0; + msg.delta.y = 0; + msg.context = EVENT_CONTEXT_TOOLBAR; + msg.obj = (FAR void *)this; + + // NOTE that we cannot block because we are on the same thread + // as the message reader. If the event queue becomes full then + // we have no other option but to lose events. + // + // I suppose we could recurse and call Twm4Nx::dispatchEvent at + // the risk of runawy stack usage. + + int ret = mq_send(m_eventq, (FAR const char *)&msg, + sizeof(struct SEventMsg), 100); + if (ret < 0) + { + gerr("ERROR: mq_send failed: %d\n", ret); + } + } +} + +/** + * Override the virtual CWidgetEventHandler::handleReleaseEvent. This + * event will fire when the title widget is released. isClicked() + * will return false for the title widget. + * + * @param e The event data. + */ + +void CWindow::handleReleaseEvent(const NXWidgets::CWidgetEventArgs &e) +{ + // Handle the case where a click event was received, but the + // window was not dragged. + + if (m_drag && !m_tbTitle->isClicked()) + { + // Handle the non-drag drop event + + handleUngrabEvent(e); } } @@ -1039,13 +1172,47 @@ void CWindow::handleKeyPressEvent(const NXWidgets::CWidgetEventArgs &e) * event will fire when the image is released but before it has been * has been drawn. isClicked() will return true for the appropriate * images. + * + * @param e The event data. */ void CWindow::handleActionEvent(const NXWidgets::CWidgetEventArgs &e) { // We are are interested in the pre-release event for any of the // toolbar buttons. -#warning Missing logic + + for (int btindex = 0; btindex < NTOOLBAR_BUTTONS; btindex++) + { + // Check if the widget is clicked + + if (m_tbButtons[btindex]->isClicked()) + { + // Yes.. generate the event + + struct SEventMsg msg; + msg.eventID = GToolBarInfo[btindex].event; + msg.pos.x = e.getX(); + msg.pos.y = e.getY(); + msg.delta.x = 0; + msg.delta.y = 0; + msg.context = EVENT_CONTEXT_TOOLBAR; + msg.obj = (FAR void *)this; + + // NOTE that we cannot block because we are on the same thread + // as the message reader. If the event queue becomes full then + // we have no other option but to lose events. + // + // I suppose we could recurse and call Twm4Nx::dispatchEvent at + // the risk of runawy stack usage. + + int ret = mq_send(m_eventq, (FAR const char *)&msg, + sizeof(struct SEventMsg), 100); + if (ret < 0) + { + gerr("ERROR: mq_send failed: %d\n", ret); + } + } + } } /** diff --git a/include/graphics/nxwidgets/cbuttonarray.hxx b/include/graphics/nxwidgets/cbuttonarray.hxx index c80a6205e..acfec28f4 100644 --- a/include/graphics/nxwidgets/cbuttonarray.hxx +++ b/include/graphics/nxwidgets/cbuttonarray.hxx @@ -214,6 +214,19 @@ namespace NXWidgets ~CButtonArray(void); + /** + * Resize the array of buttons. Button labels will be removed and will + * have to be reapplied in the new geometry. + * + * @param buttonColumns The number of buttons in one row of the button array + * @param buttonRows The number of buttons in one column of the button array + * @param buttonWidth The width of one button + * @param buttonHeight The height of one button + */ + + bool resizeArray(uint8_t buttonColumns, uint8_t buttonRows, + nxgl_coord_t buttonWidth, nxgl_coord_t buttonHeight); + /** * Returns the string shown in the label. * diff --git a/include/graphics/nxwidgets/cnxstring.hxx b/include/graphics/nxwidgets/cnxstring.hxx index 52f636dd3..b4cf8b261 100644 --- a/include/graphics/nxwidgets/cnxstring.hxx +++ b/include/graphics/nxwidgets/cnxstring.hxx @@ -465,7 +465,7 @@ namespace NXWidgets * @return This string. */ - CNxString &operator=(const char *string); + CNxString &operator=(FAR const char *string); /** * Overloaded assignment operator. Copies the data from the argument @@ -509,6 +509,7 @@ namespace NXWidgets */ int compareTo(const CNxString &string) const; + int compareTo(FAR const char *string) const; /** * snprintf()-style string formatting. Automatically allocates correct diff --git a/include/graphics/twm4nx/ciconmgr.hxx b/include/graphics/twm4nx/ciconmgr.hxx index cb689b578..56f6f88af 100644 --- a/include/graphics/twm4nx/ciconmgr.hxx +++ b/include/graphics/twm4nx/ciconmgr.hxx @@ -57,6 +57,8 @@ namespace NXWidgets { class CNxTkWindow; // Forward reference + class CButtonArray; // Forward reference + class CWidgetEventArgs; // Forward reference struct SRlePaletteBitmap; // Forward reference } @@ -72,12 +74,11 @@ namespace Twm4Nx nxgl_size_s size; int row; int col; - int me; bool active; bool down; }; - class CIconMgr + class CIconMgr : protected NXWidgets::CWidgetEventHandler { private: @@ -86,10 +87,19 @@ namespace Twm4Nx FAR struct SWindowEntry *m_tail; /**< Tail of the window list */ FAR struct SWindowEntry *m_active; /**< The active entry */ FAR struct CWindow *m_window; /**< Parent window */ - unsigned int m_columns; /**< Number of columns icon manager */ - unsigned int m_currows; - unsigned int m_curcolumns; - unsigned int m_count; + FAR NXWidgets::CButtonArray *m_buttons; /**< The cotained button array */ + uint8_t m_maxColumns; /**< Max columns per row */ + uint8_t m_nrows; /**< Number of rows in the button array */ + uint8_t m_ncolumns; /**< Number of columns in the button array */ + unsigned int m_nWindows; /**< The number of windows in the icon mgr. */ + + /** + * Return the height of one row + * + * @return The height of one row + */ + + nxgl_coord_t getRowHeight(void); /** * Create and initialize the icon manager window @@ -144,6 +154,14 @@ namespace Twm4Nx void freeWEntry(FAR struct SWindowEntry *wentry); + /** + * Handle a widget action event. This will be a button pre-release event. + * + * @param e The event data. + */ + + void handleActionEvent(const NXWidgets::CWidgetEventArgs &e); + public: /** @@ -153,7 +171,7 @@ namespace Twm4Nx * @param ncolumns The number of columns this icon manager has */ - CIconMgr(CTwm4Nx *twm4nx, int ncolumns); + CIconMgr(CTwm4Nx *twm4nx, uint8_t ncolumns); /** * CIconMgr Destructor @@ -177,6 +195,14 @@ namespace Twm4Nx bool add(FAR CWindow *win); + /** + * Remove a window from the icon manager + * + * @param win the TWM window structure + */ + + void remove(FAR struct SWindow *win); + /** * Hide the icon manager */ @@ -189,30 +215,22 @@ namespace Twm4Nx } } - /** - * Remove a window from the icon manager - * - * @param win the TWM window structure - */ - - void remove(FAR struct SWindow *win); - /** * Get the number of columns */ - inline unsigned int getColumns(void) + inline unsigned int getDisplayColumns(void) { - return m_columns; + return m_maxColumns; } /** * Get the current column */ - inline unsigned int getCurrColumn(void) + inline unsigned int getNumberOfColumns(void) { - return m_curcolumns; + return m_ncolumns; } /** @@ -224,20 +242,6 @@ namespace Twm4Nx return m_window->getFrameSize(size); } - /** - * Move the pointer around in an icon manager - * - * @param dir one of the following: - * - EVENT_ICONMGR_FORWARD: Forward in the window list - * - EVENT_ICONMGR_BACK: Backward in the window list - * - EVENT_ICONMGR_UP: Up one row - * - EVENT_ICONMGR_DOWN: Down one row - * - EVENT_ICONMGR_LEFT: Left one column - * - EVENT_ICONMGR_RIGHT: Right one column - */ - - void move(int dir); - /** * Pack the icon manager windows following an addition or deletion */ diff --git a/include/graphics/twm4nx/cwindow.hxx b/include/graphics/twm4nx/cwindow.hxx index 0f6f919fb..e009ce4ad 100644 --- a/include/graphics/twm4nx/cwindow.hxx +++ b/include/graphics/twm4nx/cwindow.hxx @@ -98,7 +98,6 @@ namespace Twm4Nx class CWindow; // Forward reference struct SMenuRoot; // Forward reference struct SMenuItem; // Forward reference - struct SToolbarButton; // Forward reference // The CWindow class implements a standard, framed window with a toolbar // containing the standard buttons and the window title. @@ -198,6 +197,19 @@ namespace Twm4Nx bool enableWidgets(void); + /** + * After the toolbar was grabbed, it may be dragged then dropped, or it + * may be simply "un-grabbed". Both cases are handled here. + * + * NOTE: Unlike the other event handlers, this does NOT override any + * virtual event handling methods. It just combines some common event- + * handling logic. + * + * @param e The event data. + */ + + void handleUngrabEvent(const NXWidgets::CWidgetEventArgs &e); + /** * Override the mouse button drag event. * @@ -222,6 +234,16 @@ namespace Twm4Nx void handleKeyPressEvent(const NXWidgets::CWidgetEventArgs &e); + /** + * Override the virtual CWidgetEventHandler::handleReleaseEvent. This + * event will fire when the title widget is released. isClicked() + * will return false for the title widget. + * + * @param e The event data. + */ + + void handleReleaseEvent(const NXWidgets::CWidgetEventArgs &e); + /** * Override the virtual CWidgetEventHandler::handleActionEvent. This * event will fire when the image is released but before it has been @@ -337,7 +359,7 @@ namespace Twm4Nx /** * Get the size of the primary window. This is useful only - * for applications that need to know the drawing area. + * for applications that need to know about the drawing area. * * @param size Location to return the primary window size */ @@ -347,6 +369,18 @@ namespace Twm4Nx return m_nxWin->getSize(size); } + /** + * Get the position of the primary window. This is useful only + * for applications that need to know about the drawing area. + * + * @param pos Location to return the primary window position + */ + + inline bool getWindowPosition(FAR struct nxgl_point_s *pos) + { + return m_nxWin->getPosition(pos); + } + /** * Set the size of the primary window. This is useful only * for oapplications that need to control the drawing area. diff --git a/include/graphics/twm4nx/twm4nx_widgetevents.hxx b/include/graphics/twm4nx/twm4nx_widgetevents.hxx index 58bedc1f5..c21e4002d 100644 --- a/include/graphics/twm4nx/twm4nx_widgetevents.hxx +++ b/include/graphics/twm4nx/twm4nx_widgetevents.hxx @@ -109,22 +109,12 @@ namespace Twm4Nx // Recipient == ICONWIN - EVENT_ICONWIN_GRAB = 0x2000, /**< Click on toolbar (not toolbar buttons) */ + EVENT_ICONWIN_GRAB = 0x2000, /**< Click on toolbar title */ EVENT_ICONWIN_DRAG = 0x2001, /**< Drag window */ EVENT_ICONWIN_UNGRAB = 0x2002, /**< Release click on toolbar */ // Recipient == ICONMGR - EVENT_ICONMGR_FORWARD = 0x3000, /**< Forward in the window list */ - EVENT_ICONMGR_BACK = 0x3001, /**< Backward in the window list */ - EVENT_ICONMGR_UP = 0x3002, /**< Up one row */ - EVENT_ICONMGR_DOWN = 0x3003, /**< Down one row */ - EVENT_ICONMGR_LEFT = 0x3004, /**< Left one column */ - EVENT_ICONMGR_RIGHT = 0x3005, /**< Right one column */ - EVENT_ICONMGR_SHOWPARENT = 0x3006, /**< Raise Icon Manager parent window */ - EVENT_ICONMGR_HIDE = 0x3007, /**< Hide the Icon Manager */ - EVENT_ICONMGR_SORT = 0x3008, /**< Sort the Icon Manager */ - // Recipient == MENU EVENT_MENU_IDENTIFY = 0x4001, /**< Describe the window */ @@ -173,9 +163,8 @@ namespace Twm4Nx enum EButtonContext { EVENT_CONTEXT_WINDOW = 0, - EVENT_CONTEXT_TITLE, + EVENT_CONTEXT_TOOLBAR, EVENT_CONTEXT_ICON, - EVENT_CONTEXT_ROOT, EVENT_CONTEXT_FRAME, EVENT_CONTEXT_ICONMGR, EVENT_CONTEXT_NAME, @@ -192,10 +181,8 @@ namespace Twm4Nx { uint16_t eventID; /**< Encoded event ID */ struct nxgl_point_s pos; /**< X/Y position */ + struct nxgl_point_s delta; /**< X/Y change (for dragging only) */ uint8_t context; /**< Button press context */ - bool pulldown; /**< Pull-down menu */ - FAR const char *action; /**< Menu action */ - FAR NXWidgets::CNxTkWindow *nxwin; /**< Raw NX window reference */ FAR void *obj; /**< Window object (CWindow or CIconWin) */ }; @@ -208,7 +195,7 @@ namespace Twm4Nx { uint16_t eventID; /**< Encoded event ID */ FAR CWindowEvent *instance; /**< X/Y position */ - FAR struct SWindow *win; /**< Twm4NX window reference */ + FAR struct SWindow *win; /**< Twm4NX window reference */ }; }