Squashed commit of the following:

apps/graphics/twm4nx:  Add new logic to place an icon at a reasonable spot on the background.

    apps/graphics/twm4nx:  Remove some unused logic.
This commit is contained in:
Gregory Nutt 2019-05-11 09:47:27 -06:00
parent 80de28c865
commit 2b2e17d126
13 changed files with 339 additions and 786 deletions

View File

@ -54,10 +54,10 @@ STACKSIZE = $(CONFIG_TWM4NX_STACKSIZE)
ASRCS =
CSRCS =
CXXSRCS = cbackground.cxx cfonts.cxx cicon.cxx ciconmgr.cxx
CXXSRCS += ciconwidget.cxx cinput.cxx cmenus.cxx cmainmenu.cxx cresize.cxx
CXXSRCS += cwindow.cxx cwindowevent.cxx cwindowfactory.cxx
CXXSRCS += twm4nx_cursor.cxx
CXXSRCS = cbackground.cxx cfonts.cxx ciconmgr.cxx ciconwidget.cxx
CXXSRCS += cmenus.cxx cmainmenu.cxx
CXXSRCS += cwindow.cxx cwindowevent.cxx cresize.cxx cwindowfactory.cxx
CXXSRCS += cinput.cxx twm4nx_cursor.cxx
MAINSRC = ctwm4nx.cxx
VPATH = src

View File

@ -54,7 +54,7 @@
#include "graphics/twm4nx/twm4nx_config.hxx"
#include "graphics/twm4nx/cwindowevent.hxx"
#include "graphics/twm4nx/cicon.hxx"
#include "graphics/twm4nx/cwindowfactory.hxx"
#include "graphics/twm4nx/cmainmenu.hxx"
#include "graphics/twm4nx/cbackground.hxx"
@ -163,6 +163,42 @@ void CBackground::getDisplaySize(FAR struct nxgl_size_s &size)
rect.getSize(size);
}
/**
* Check if the region within 'bounds' collides with any other reserved
* region on the desktop. This is used for icon placement.
*
* @param iconBounds The candidate bounding box
* @param collision The bounding box of the reserved region that the
* candidate collides with
* @return Returns true if there is a collision
*/
bool CBackground::checkCollision(FAR const struct nxgl_rect_s &bounds,
FAR struct nxgl_rect_s &collision)
{
// Is there a background image
if (m_backImage != (NXWidgets::CImage *)0)
{
// Create a bounding box for the background image
struct nxgl_size_s imageSize;
m_backImage->getSize(imageSize);
struct nxgl_point_s imagePos;
m_backImage->getPos(imagePos);
collision.pt1.x = imagePos.x;
collision.pt1.y = imagePos.y;
collision.pt1.x = imagePos.x + imageSize.w - 1;
collision.pt1.y = imagePos.y + imageSize.h - 1;
return nxgl_intersecting(&bounds, &collision);
}
return false;
}
/**
* Handle the background window redraw.
*
@ -219,8 +255,8 @@ bool CBackground::redrawBackgroundWindow(FAR const struct nxgl_rect_s *rect,
// Now redraw any background icons that need to be redrawn
FAR CIcon *cicon = m_twm4nx->getIcon();
cicon->redrawIcons(rect, more);
FAR CWindowFactory *factory = m_twm4nx->getWindowFactory();
factory->redrawIcons(rect);
return true;
}

View File

@ -1,516 +0,0 @@
/////////////////////////////////////////////////////////////////////////////
// apps/graphics/twm4nx/src/cicon.cxx
// Icon releated routines
//
// Copyright (C) 2019 Gregory Nutt. All rights reserved.
// Author: Gregory Nutt <gnutt@nuttx.org>
//
// Largely an original work but derives from TWM 1.0.10 in many ways:
//
// Copyright 1989,1998 The Open Group
//
// Please refer to apps/twm4nx/COPYING for detailed copyright information.
//
// 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 <cstdlib>
#include "nuttx/nx/nxglib.h"
#include "graphics/twm4nx/twm4nx_config.hxx"
#include "graphics/twm4nx/ctwm4nx.hxx"
#include "graphics/twm4nx/cwindow.hxx"
#include "graphics/twm4nx/cwindowevent.hxx"
#include "graphics/twm4nx/cicon.hxx"
/////////////////////////////////////////////////////////////////////////////
// CTwm4Nx Implementation
/////////////////////////////////////////////////////////////////////////////
using namespace Twm4Nx;
/**
* CIcon Constructor
*/
CIcon::CIcon(CTwm4Nx *twm4nx)
{
m_twm4nx = twm4nx; // Cached the Twm4Nx session
m_icons = (FAR struct SNameList *)0; // List of icon images
m_regionHead = (FAR struct SIconRegion *)0; // Pointer to icon regions
m_regionTail = (FAR struct SIconRegion *)0; // Pointer to the last icon region
}
/**
* CIcon Destructor
*/
CIcon::~CIcon(void)
{
freeIconRegions();
}
/**
* Create a new icon region and add it to the list of icon regions.
*
* @param pos The position of the region on the background
* @param size The size of the region
* @param step
*/
void CIcon::addIconRegion(FAR nxgl_point_s *pos, FAR nxgl_size_s *size,
FAR struct nxgl_point_s *step)
{
FAR struct SIconRegion *ir;
// Allocate the new region
ir = (FAR struct SIconRegion *)std::malloc(sizeof(struct SIconRegion));
// Add the new region to the list of regions
ir->flink = (FAR struct SIconRegion *)0;
if (m_regionTail != (FAR struct SIconRegion *)0)
{
m_regionTail->flink = ir;
}
m_regionTail = ir;
if (m_regionHead != (FAR struct SIconRegion *)0)
{
m_regionHead = ir;
}
// Initiliaze the region
ir->entries = NULL;
if (step->x <= 0)
{
step->x = 1;
}
if (step->y <= 0)
{
step->y = 1;
}
ir->step.x = step->x;
ir->step.y = step->y;
ir->pos.x = pos->x;
ir->pos.y = pos->y;
ir->size.w = size->w;
ir->size.h = size->h;
struct nxgl_size_s displaySize;
m_twm4nx->getDisplaySize(&displaySize);
if (ir->pos.x < 0)
{
ir->pos.x += displaySize.w - ir->size.w;
}
if (ir->pos.y < 0)
{
ir->pos.y += displaySize.h - ir->size.h;
}
// Allocate one region entry
ir->entries = (FAR struct SIconEntry *)malloc(sizeof(struct SIconRegion));
if (ir->entries != (FAR struct SIconEntry *)0)
{
ir->entries->flink = (FAR struct SIconEntry *)0;
ir->entries->pos.x = ir->pos.x;
ir->entries->pos.y = ir->pos.y;
ir->entries->size.w = ir->size.w;
ir->entries->size.h = ir->size.h;
ir->entries->cwin = (FAR CWindow *)0;
ir->entries->used = false;
}
}
/**
* Position an icon on the background
*
* @param cwin The Window whose icon will be placed
* @param pos An backup position to use is there are no available regions
* @param final A location in which to return the selection icon position
*/
void CIcon::place(FAR CWindow *cwin, FAR const struct nxgl_point_s *pos,
FAR struct nxgl_point_s *final)
{
// Try each region
FAR struct SIconEntry *ie = (FAR struct SIconEntry *)0;
for (FAR struct SIconRegion *ir = m_regionHead; ir; ir = ir->flink)
{
struct nxgl_size_s iconWindowSize;
cwin->getIconWidgetSize(iconWindowSize);
struct nxgl_size_s tmpsize;
tmpsize.w = roundUp(iconWindowSize.w, ir->step.x);
tmpsize.h = roundUp(iconWindowSize.h, ir->step.y);
// Try each entry in the regions
for (ie = ir->entries; ie; ie = ie->flink)
{
// Look for an unused entry
if (ie->used)
{
continue;
}
// Does the entry describe a region that is of sufficient size?
if (ie->size.w >= tmpsize.w && ie->size.h >= tmpsize.h)
{
// Yes.. We have it. Break out with ie non-NULL
break;
}
}
// Break out of the outer loop if the the region entry was found by
// the inner loop
if (ie != (FAR struct SIconEntry *)0)
{
break;
}
}
// Did we find an entry?
if (ie != (FAR struct SIconEntry *)0)
{
// Yes.. place the icon in this region
ie->used = true;
ie->cwin = cwin;
struct nxgl_size_s iconWindowSize;
cwin->getIconWidgetSize(iconWindowSize);
final->x = ie->pos.x + (ie->size.w - iconWindowSize.w) / 2;
final->y = ie->pos.y + (ie->size.h - iconWindowSize.h) / 2;
}
else
{
// No.. place it.. wherever
final->x = pos->x;
final->y = pos->y;
}
}
/**
* Bring the window up.
*
* @param cwin The window to be brought up.
*/
void CIcon::up(FAR CWindow *cwin)
{
struct nxgl_point_s newpos;
struct nxgl_point_s oldpos;
// Did the user move the icon?
if (cwin->hasIconMoved())
{
struct nxgl_size_s oldsize;
cwin->getIconWidgetSize(oldsize);
cwin->getIconWidgetPosition(oldpos);
newpos.x = oldpos.x + ((int)oldsize.w) / 2;
newpos.y = oldpos.y + ((int)oldsize.h) / 2;
FAR struct SIconRegion *ir;
for (ir = m_regionHead; ir; ir = ir->flink)
{
if (newpos.x >= ir->pos.x &&
newpos.x < (ir->pos.x + ir->size.w) &&
newpos.y >= ir->pos.y &&
newpos.y < (ir->pos.y + ir->size.h))
{
break;
}
}
if (ir == NULL)
{
return; // outside icon regions, leave alone
}
}
oldpos.x = -100;
oldpos.y = -100;
place(cwin, &oldpos, &newpos);
if (newpos.x != oldpos.x || newpos.y != oldpos.y)
{
cwin->getIconWidgetPosition(newpos);
cwin->setIconMoved(false); // since we've restored it
}
}
/**
* Take the window down.
*
* @param cwin The window to be taken down.
*/
void CIcon::down(FAR CWindow *cwin)
{
FAR struct SIconRegion *ir;
FAR struct SIconEntry *ie;
ie = findEntry(cwin, &ir);
if (ie != (FAR struct SIconEntry *)0)
{
ie->cwin = 0;
ie->used = false;
FAR struct SIconEntry *ip = prevEntry(ie, ir);
FAR struct SIconEntry *in = ie->flink;
for (; ; )
{
if (ip && ip->used == false &&
((ip->pos.x == ie->pos.x && ip->size.w == ie->size.w) ||
(ip->pos.y == ie->pos.y && ip->size.h == ie->size.h)))
{
ip->flink = ie->flink;
mergeEntries(ie, ip);
free(ie);
ie = ip;
ip = prevEntry(ip, ir);
}
else if (in && in->used == false &&
((in->pos.x == ie->pos.x && in->size.w == ie->size.w) ||
(in->pos.y == ie->pos.y && in->size.h == ie->size.h)))
{
ie->flink = in->flink;
mergeEntries(in, ie);
free(in);
in = ie->flink;
}
else
{
break;
}
}
}
}
/**
* Redraw icons. The icons are drawn on the background window. When
* the background window receives a redraw request, it will call this
* method in order to redraw any effected icons drawn in the
* background.
*
* @param nxRect The region in the window to be redrawn
* @param more More redraw requests will follow
*/
void CIcon::redrawIcons(FAR const nxgl_rect_s *nxRect, bool more)
{
twminfo("Redrawing...\n");
// Try each region
FAR struct SIconEntry *ie = (FAR struct SIconEntry *)0;
for (FAR struct SIconRegion *ir = m_regionHead; ir; ir = ir->flink)
{
// Try each entry in the region
for (ie = ir->entries; ie; ie = ie->flink)
{
// Create a bounding box for the icon
FAR CWindow *cwin = ie->cwin;
struct nxgl_size_s iconWindowSize;
cwin->getIconWidgetSize(iconWindowSize);
struct nxgl_point_s iconPosition;
cwin->getIconWidgetPosition(iconPosition);
struct nxgl_rect_s iconBounds;
iconBounds.pt1.x = iconPosition.x;
iconBounds.pt1.y = iconPosition.y;
iconBounds.pt2.x = iconPosition.x + iconWindowSize.w - 1;
iconBounds.pt2.y = iconPosition.y + iconWindowSize.h - 1;
struct nxgl_rect_s intersection;
nxgl_rectintersect(&intersection, nxRect, &iconBounds);
if (!nxgl_nullrect(&intersection))
{
// Redraw the icon (or a portion of the icon)
twminfo("Redraw icon\n");
cwin->redrawIcon();
}
}
}
}
/**
* Find the icon region holding the window 'cwin'
*
* @param cwin The window whose icon region is sought
* @param irp A location in which to provide the region
*/
FAR struct SIconEntry *CIcon::findEntry(FAR CWindow *cwin,
FAR struct SIconRegion **irp)
{
FAR struct SIconRegion *ir;
FAR struct SIconEntry *ie;
for (ir = m_regionHead; ir; ir = ir->flink)
{
for (ie = ir->entries; ie; ie = ie->flink)
if (ie->cwin == cwin)
{
if (irp)
{
*irp = ir;
}
return ie;
}
}
return (FAR struct SIconEntry *)0;
}
/**
* Given entry 'ie' in the list 'ir', return the entry just prior to 'ie'
*
* @param ie The entry whose predecessor is sought
* @param ir The region containing the entry
* @return The entry just before 'ie' in the list
*/
FAR struct SIconEntry *CIcon::prevEntry(FAR struct SIconEntry *ie,
FAR struct SIconRegion *ir)
{
FAR struct SIconEntry *ip;
if (ie == ir->entries)
{
return (FAR struct SIconEntry *)0;
}
for (ip = ir->entries; ip->flink != ie; ip = ip->flink)
{
}
return ip;
}
/**
* 'old' is being freed; and is adjacent to ie. Merge
* regions together
*/
void CIcon::mergeEntries(FAR struct SIconEntry *old,
FAR struct SIconEntry *ie)
{
if (old->pos.y == ie->pos.y)
{
ie->size.w = old->size.w + ie->size.w;
if (old->pos.x < ie->pos.x)
{
ie->pos.x = old->pos.x;
}
}
else
{
ie->size.h = old->size.h + ie->size.h;
if (old->pos.y < ie->pos.y)
{
ie->pos.y = old->pos.y;
}
}
}
/**
* Free all of the icon entries linked to a region
*
* @param ir The region whose entries will be freed
*/
void CIcon::freeIconEntries(FAR struct SIconRegion *ir)
{
FAR struct SIconEntry *ie;
FAR struct SIconEntry *tmp;
for (ie = ir->entries; ie; ie = tmp)
{
tmp = ie->flink;
std::free(ie);
}
}
/**
* Free all icon regions and all of the region entries linked into the
* region
*/
void CIcon::freeIconRegions(void)
{
struct SIconRegion *ir;
struct SIconRegion *tmp;
for (ir = m_regionHead; ir != NULL;)
{
tmp = ir;
freeIconEntries(ir);
ir = ir->flink;
free(tmp);
}
m_regionHead = NULL;
m_regionTail = NULL;
}

View File

@ -66,7 +66,6 @@
#include "graphics/twm4nx/cmenus.hxx"
#include "graphics/twm4nx/cresize.hxx"
#include "graphics/twm4nx/cfonts.hxx"
#include "graphics/twm4nx/cicon.hxx"
#include "graphics/twm4nx/ciconmgr.hxx"
#include "graphics/twm4nx/cwindow.hxx"
#include "graphics/twm4nx/cwindowfactory.hxx"

View File

@ -72,7 +72,6 @@
#include "graphics/twm4nx/cwindowfactory.hxx"
#include "graphics/twm4nx/cwindowevent.hxx"
#include "graphics/twm4nx/cinput.hxx"
#include "graphics/twm4nx/cicon.hxx"
#include "graphics/twm4nx/ciconwidget.hxx"
#include "graphics/twm4nx/ciconmgr.hxx"
#include "graphics/twm4nx/cmenus.hxx"
@ -124,7 +123,6 @@ CTwm4Nx::CTwm4Nx(int display)
m_display = display;
m_eventq = (mqd_t)-1;
m_background = (FAR CBackground *)0;
m_icon = (FAR CIcon *)0;
m_iconmgr = (FAR CIconMgr *)0;
m_factory = (FAR CWindowFactory *)0;
m_fonts = (FAR CFonts *)0;
@ -285,15 +283,6 @@ bool CTwm4Nx::run(void)
return false;
}
// Cache a CIcon instance for use across the session
m_icon = new CIcon(this);
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);

View File

@ -161,7 +161,6 @@ CWindow::CWindow(CTwm4Nx *twm4nx)
m_iconBitMap = (FAR NXWidgets::CRlePaletteBitmap *)0;
m_iconWidget = (FAR CIconWidget *)0;
m_iconMgr = (FAR CIconMgr *)0;
m_iconOn = false;
m_iconified = false;
// Dragging
@ -260,8 +259,6 @@ bool CWindow::initialize(FAR const NXWidgets::CNxString &name,
winsize.h = maxWindow.h;
}
m_iconOn = false;
// Create the window
m_nxWin = (FAR NXWidgets::CNxTkWindow *)0;
@ -542,21 +539,34 @@ bool CWindow::iconify(void)
// Hide the main window
m_iconified = true;
m_nxWin->hide();
// Menu windows don't have an icon
if (m_iconWidget != (FAR CIconWidget *)0)
if (hasIcon())
{
// Enable and redraw the icon widget and lower the main window
// Enable the widget
m_iconOn = true;
m_iconWidget->enable();
// Pick a position for icon
struct nxgl_point_s iconPos;
m_iconWidget->getPos(iconPos);
FAR CWindowFactory *factory = m_twm4nx->getWindowFactory();
if (factory->placeIcon(this, iconPos, iconPos))
{
m_iconWidget->moveTo(iconPos.x, iconPos.y);
}
// Redraw the icon widget
m_iconWidget->enableDrawing();
m_iconWidget->redraw();
}
m_iconified = true;
m_nxWin->synchronize();
}
@ -580,11 +590,10 @@ bool CWindow::deIconify(void)
m_iconified = false;
m_nxWin->show();
if (m_iconWidget != (FAR CIconWidget *)0)
if (hasIcon())
{
// Disable the icon widget
m_iconOn = false;
m_iconWidget->disableDrawing();
m_iconWidget->disable();

View File

@ -59,6 +59,7 @@
#include "graphics/twm4nx/twm4nx_config.hxx"
#include "graphics/twm4nx/ctwm4nx.hxx"
#include "graphics/twm4nx/cbackground.hxx"
#include "graphics/twm4nx/cwindow.hxx"
#include "graphics/twm4nx/cwindowfactory.hxx"
#include "graphics/twm4nx/ciconmgr.hxx"
@ -278,6 +279,157 @@ void CWindowFactory::destroyWindow(FAR CWindow *cwin)
free(win);
}
/**
* Pick a position for a new Icon on the desktop. Tries to avoid
* collisions with other Icons and reserved areas on the background
*
* @param cwin The window being iconified.
* @param defPos The default position to use if there is no free
* region on the desktop.
* @param iconPos The selected Icon position. Might be the same as
* the default position.
* @return True is returned on success
*/
bool CWindowFactory::placeIcon(FAR CWindow *cwin,
FAR const struct nxgl_point_s &defPos,
FAR struct nxgl_point_s &iconPos)
{
// Does this window have an Icon?
bool success = false;
if (cwin->hasIcon())
{
// Get the size of the Display (i.e., the size of the background)
struct nxgl_size_s displaySize;
m_twm4nx->getDisplaySize(&displaySize);
// Get the size of the Icon
struct nxgl_size_s iconSize;
(void)cwin->getIconWidgetSize(iconSize);
// Get the background instance
FAR CBackground *backgd = m_twm4nx->getBackground();
// Search for a free region. Start at the at the left size
struct nxgl_point_s tmppos;
tmppos.x = CONFIG_TWM4NX_ICON_HSPACING;
// Try each possible horizonal position until we find a free location or
// until we run out of positions to test
nxgl_coord_t iconWidth = 0;
for (; tmppos.x < (displaySize.w - iconSize.w); tmppos.x += iconWidth)
{
// Start at the top of the next column
tmppos.y = CONFIG_TWM4NX_ICON_VSPACING;
// Try each possible vertical position until we find a free
// location or until we run out of positions to test
nxgl_coord_t iconHeight;
for (; tmppos.y < (displaySize.h - iconSize.h); tmppos.y += iconHeight)
{
// Create a bounding box at this position
struct nxgl_rect_s iconBounds;
iconBounds.pt1.x = tmppos.x;
iconBounds.pt1.y = tmppos.y;
iconBounds.pt2.x = tmppos.x + iconSize.w - 1;
iconBounds.pt2.y = tmppos.y + iconSize.h - 1;
// Check if this box intersects any reserved region on the background.
// If nt, check if so other icon is already occupying this position
struct nxgl_rect_s collision;
if (!backgd->checkCollision(iconBounds, collision) &&
!checkCollision(cwin, iconBounds, collision))
{
// No collision.. place the icon at this position
iconPos.x = tmppos.x;
iconPos.y = tmppos.y;
return true;
}
// Yes.. reset the search position to move past the collision.
// This is only in the vertical direction. This may terminate
// the inner loop.
iconHeight = collision.pt2.y - tmppos.y +
CONFIG_TWM4NX_ICON_VSPACING + 1;
}
}
// No free region found, use the user provided default
iconPos.x = defPos.x;
iconPos.y = defPos.y;
success = true;
}
return success;
}
/**
* Redraw icons. The icons are drawn on the background window. When
* the background window receives a redraw request, it will call this
* method in order to redraw any effected icons drawn in the
* background.
*
* @param nxRect The region in the background to be redrawn
*/
void CWindowFactory::redrawIcons(FAR const nxgl_rect_s *nxRect)
{
twminfo("Redrawing...\n");
// Try each window
for (FAR struct SWindow *win = m_windowHead;
win != (FAR struct SWindow *)0;
win = win->flink)
{
// Check if the window has an icon and it is in the iconified state
FAR CWindow *cwin = win->cwin;
if (cwin->hasIcon() && cwin->isIconified())
{
// Yes.. Create a bounding box for the icon
struct nxgl_size_s iconSize;
(void)cwin->getIconWidgetSize(iconSize);
struct nxgl_point_s iconPos;
(void)cwin->getIconWidgetPosition(iconPos);
struct nxgl_rect_s iconBounds;
iconBounds.pt1.x = iconPos.x;
iconBounds.pt1.y = iconPos.y;
iconBounds.pt2.x = iconPos.x + iconSize.w - 1;
iconBounds.pt2.y = iconPos.y + iconSize.h - 1;
// Does anything within bounding box need to be redrawn?
struct nxgl_rect_s intersection;
nxgl_rectintersect(&intersection, nxRect, &iconBounds);
if (!nxgl_nullrect(&intersection))
{
// Yes.. Redraw the icon (or a portion of the icon)
twminfo("Redraw icon\n");
cwin->redrawIcon();
}
}
}
}
/**
* Handle WINDOW events.
*
@ -395,6 +547,60 @@ FAR struct SWindow *CWindowFactory::findWindow(FAR CWindow *cwin)
return (FAR struct SWindow *)0;
}
/**
* Check if the icon within iconBounds collides with any other icon on the
* desktop.
*
* @param cwin The window containing the Icon of interest
* @param iconBounds The candidate Icon bounding box
* @param collision The bounding box of the icon that the candidate collides
* with
* @return Returns true if there is a collision
*/
bool CWindowFactory::checkCollision(FAR CWindow *cwin,
FAR const struct nxgl_rect_s &iconBounds,
FAR struct nxgl_rect_s &collision)
{
// Try every window
for (FAR struct SWindow *win = m_windowHead;
win != (FAR struct SWindow *)0;
win = win->flink)
{
// Ignore 'this' window, any windows that are not iconified, and any
// windows that have no icons.
if (win->cwin != cwin && win->cwin->hasIcon() &&
win->cwin->isIconified())
{
// Create a bounding box for the icon
struct nxgl_size_s iconSize;
(void)win->cwin->getIconWidgetSize(iconSize);
struct nxgl_point_s iconPos;
(void)win->cwin->getIconWidgetPosition(iconPos);
collision.pt1.x = iconPos.x;
collision.pt1.y = iconPos.y;
collision.pt2.x = iconPos.x + iconSize.w - 1;
collision.pt2.y = iconPos.y + iconSize.h - 1;
// Return true if there is an intersection
if (nxgl_intersecting(&iconBounds, &collision))
{
return true;
}
}
}
// No collision
return false;
}
/**
* This is the function that responds to the EVENT_WINDOW_DESKTOP. It
* iconifies all windows so that the desktop is visible.

View File

@ -164,7 +164,20 @@ namespace Twm4Nx
* @return true on success
*/
bool redrawBackgroundWindow(FAR const struct nxgl_rect_s *rect, bool more);
bool redrawBackgroundWindow(FAR const struct nxgl_rect_s *rect, bool more);
/**
* Check if the region within 'bounds' collides with any other reserved
* region on the desktop. This is used for icon placement.
*
* @param iconBounds The candidate bounding box
* @param collision The bounding box of the reserved region that the
* candidate collides with
* @return Returns true if there is a collision
*/
bool checkCollision(FAR const struct nxgl_rect_s &bounds,
FAR struct nxgl_rect_s &collision);
/**
* Handle EVENT_BACKGROUND events.

View File

@ -1,201 +0,0 @@
/////////////////////////////////////////////////////////////////////////////
// apps/graphics/twm4nx/include/cicon.hxx
// Icon related definitions
//
// Copyright (C) 2019 Gregory Nutt. All rights reserved.
// Author: Gregory Nutt <gnutt@nuttx.org>
//
// Largely an original work but derives from TWM 1.0.10 in many ways:
//
// Copyright 1989,1998 The Open Group
//
// Please refer to apps/twm4nx/COPYING for detailed copyright information.
//
// 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_CICON_HXX
#define __APPS_INCLUDE_GRAPHICS_TWM4NX_CICON_HXX
/////////////////////////////////////////////////////////////////////////////
// Implementation Classes
/////////////////////////////////////////////////////////////////////////////
namespace Twm4Nx
{
class CTwm4Nx; /* Forward reference */
struct SIconEntry; /* Forward reference */
struct SIconRegion
{
FAR struct SIconRegion *flink;
struct nxgl_point_s pos;
struct nxgl_size_s size;
struct nxgl_point_s step; // Allocation granularity
FAR struct SIconEntry *entries;
};
struct SIconEntry
{
FAR struct SIconEntry *flink;
struct nxgl_point_s pos;
struct nxgl_size_s size;
FAR CWindow *cwin;
bool used;
};
/**
* The CIcon class supports a database of icons.
*/
class CIcon
{
private:
FAR CTwm4Nx *m_twm4nx; /**< The Twm4Nx session */
FAR struct SNameList *m_icons; /**< List of icon images */
FAR struct SIconRegion *m_regionHead; /**< Head of the icon region list */
FAR struct SIconRegion *m_regionTail; /**< Tail of the icon region list */
inline int roundUp(int v, int multiple)
{
return ((v + multiple - 1) / multiple) * multiple;
}
/**
* Find the icon region holding the window 'cwin'
*
* @param cwin The window whose icon region is sought
* @param irp A location in which to provide the region
*/
FAR struct SIconEntry *findEntry(FAR CWindow *cwin,
FAR struct SIconRegion **irp);
/**
* Given entry 'ie' in the list 'ir', return the entry just prior to 'ie'
*
* @param ie The entry whose predecessor is sought
* @param ir The region containing the entry
* @return The entry just before 'ie' in the list
*/
FAR struct SIconEntry *prevEntry(FAR struct SIconEntry *ie,
FAR struct SIconRegion *ir);
/**
* 'old' is being freed; and is adjacent to ie. Merge
* regions together
*/
void mergeEntries(FAR struct SIconEntry *old,
FAR struct SIconEntry *ie);
/**
* Free all of the icon entries linked to a region
*
* @param ir The region whose entries will be freed
*/
void freeIconEntries(FAR struct SIconRegion *ir);
/**
* Free all icon regions and all of the region entries linked into the
* region
*/
void freeIconRegions(void);
public:
/**
* CIcon Constructor
*/
CIcon(FAR CTwm4Nx *twm4nx);
/**
* CIcon Destructor
*/
~CIcon(void);
/**
* Create a new icon region and add it to the list of icon regions.
*
* @param pos The position of the region on the background
* @param size The size of the region
* @param step
*/
void addIconRegion(FAR nxgl_point_s *pos, FAR nxgl_size_s *size,
FAR struct nxgl_point_s *step);
/**
* Position an icon on the background
*
* @param cwin The Window whose icon will be placed
* @param pos An backup position to use is there are no available regions
* @param final A location in which to return the selection icon position
*/
void place(FAR CWindow *cwin, FAR const struct nxgl_point_s *pos,
FAR struct nxgl_point_s *final);
/**
* Bring the window up.
*
* @param cwin. The window to be brought up.
*/
void up(FAR CWindow *cwin);
/**
* Take the window down.
*
* @param cwin. The window to be taken down.
*/
void down(FAR CWindow *cwin);
/**
* Redraw icons. The icons are drawn on the background window. When
* the background window receives a redraw request, it will call this
* method in order to redraw any effected icons drawn in the
* background.
*
* @param nxRect The region in the window to be redrawn
* @param more More redraw requests will follow
*/
void redrawIcons(FAR const nxgl_rect_s *nxRect, bool more);
};
}
#endif // __APPS_INCLUDE_GRAPHICS_TWM4NX_CICON_HXX

View File

@ -83,7 +83,6 @@ namespace Twm4Nx
class CInput; // Forward reference
class CBackground; // Forward reference
class CWidgetEvent; // Forward reference
class CIcon; // Forward reference
class CIconMgr; // Forward reference
class CFonts; // Forward reference
class CWindow; // Forward reference
@ -112,7 +111,6 @@ namespace Twm4Nx
FAR char *m_queueName; /**< NxWidget event queue name */
mqd_t m_eventq; /**< NxWidget event message queue */
FAR CBackground *m_background; /**< Background window management */
FAR CIcon *m_icon; /**< The cached Cicon instance */
FAR CIconMgr *m_iconmgr; /**< The Default icon manager */
FAR CWindowFactory *m_factory; /**< The cached CWindowFactory instance */
FAR CFonts *m_fonts; /**< The cached Cfonts instance */
@ -252,17 +250,6 @@ namespace Twm4Nx
return m_background;
}
/**
* Return the session's CIcon instance.
*
* @return The contained instance of the Icon class for this session.
*/
inline FAR CIcon *getIcon(void)
{
return m_icon;
}
/**
* Return the session's Icon Manager instance.
*

View File

@ -159,8 +159,6 @@ namespace Twm4Nx
FAR CIconWidget *m_iconWidget; /**< The icon widget */
FAR CIconMgr *m_iconMgr; /**< Pointer to it if this is an icon manager */
bool m_iconMoved; /**< User explicitly moved the icon. */
bool m_iconOn; /**< Icon is visible. */
bool m_iconified; /**< Is the window an icon now ? */
// Toolbar
@ -717,31 +715,23 @@ namespace Twm4Nx
}
/**
* Has the Icon moved?
*
* @return True if the operation was successful
* Check if this window has an Icon. Menu windows, for examples, have
* no icons.
*/
inline bool hasIconMoved(void)
inline bool hasIcon(void)
{
return m_iconMoved;
}
/**
* Set Icon moved
*/
inline void setIconMoved(bool moved)
{
m_iconMoved = moved;
return (m_iconWidget != (FAR CIconWidget *)0);
}
/**
* Get the size of the icon window associated with this application
* window. This is needed for placement of the icon on the background
* window.
* window and for determining if the icon widget needs to be redraw
* when the background is redrawn.
*
* @param size Location to return the icon window size
* @return True if the icon size was returned
*/
inline void getIconWidgetSize(FAR struct nxgl_size_s &size)
@ -754,10 +744,11 @@ namespace Twm4Nx
/**
* Get the current position of the icon window associated with the
* application window. This is needed for placement of the icon on
* the background window.
* application window. This is needed for determining if an icon
* widgets needs to be redrawn when the background is redrawn.
*
* @param pos Location to return the icon window position
* @return True if the icon position was returned
*/
inline void getIconWidgetPosition(FAR struct nxgl_point_s &pos)
@ -770,13 +761,14 @@ namespace Twm4Nx
/**
* Set the new position of the icon window associated with the
* application window. This is needed for placement of the icon on the
* application window. This is needed for movement of the icon on the
* background window.
*
* @param pos The new location of the icon window
* @return True if the icon position was correctly set
*/
inline bool setIconWindowPosition(FAR const struct nxgl_point_s &pos)
inline bool setIconWidgetPosition(FAR const struct nxgl_point_s &pos)
{
bool success = false;
if (m_iconWidget != (FAR CIconWidget *)0)

View File

@ -188,6 +188,21 @@ namespace Twm4Nx
FAR struct SWindow *findWindow(FAR CWindow *cwin);
/**
* Check if the icon within iconBounds collides with any other icon on
* the desktop.
*
* @param cwin The window containing the Icon of interest
* @param iconBounds The candidate Icon bounding box
* @param collision The bounding box of the icon that the candidate
* collides with
* @return Returns true if there is a collision
*/
bool checkCollision(FAR CWindow *cwin,
FAR const struct nxgl_rect_s &iconBounds,
FAR struct nxgl_rect_s &collision);
/**
* This is the function that responds to the EVENT_WINDOW_DESKTOP. It
* iconifies all windows so that the desktop is visible.
@ -260,15 +275,31 @@ namespace Twm4Nx
void destroyWindow(FAR CWindow *cwin);
/**
* Return the head of the window list.
* Pick a position for a new Icon on the desktop. Tries to avoid
* collisions with other Icons and reserved areas on the background
*
* @return The head of the window list.
* @param cwin The window being iconified.
* @param defPos The default position to use if there is no free
* region on the desktop.
* @param iconPos The selected Icon position. Might be the same as
* the default position.
* @return True is returned on success
*/
inline FAR struct SWindow *windowHead(void)
{
return m_windowHead;
}
bool placeIcon(FAR CWindow *cwin,
FAR const struct nxgl_point_s &defPos,
FAR struct nxgl_point_s &iconPos);
/**
* Redraw icons. The icons are drawn on the background window. When
* the background window receives a redraw request, it will call this
* method in order to redraw any effected icons drawn in the
* background.
*
* @param nxRect The region in the background to be redrawn
*/
void redrawIcons(FAR const nxgl_rect_s *nxRect);
/**
* Handle WINDOW events.

View File

@ -165,6 +165,14 @@
# define CONFIG_TWM4NX_MENU_VSPACING 0
#endif
#ifndef CONFIG_TWM4NX_ICON_VSPACING
# define CONFIG_TWM4NX_ICON_VSPACING 2
#endif
#ifndef CONFIG_TWM4NX_ICON_HSPACING
# define CONFIG_TWM4NX_ICON_HSPACING 2
#endif
#ifndef CONFIG_TWM4NX_ICONMGR_VSPACING
# define CONFIG_TWM4NX_ICONMGR_VSPACING 2
#endif