appkit  1.5.1
RoadNarrows Robotics Application Kit
WinMenu.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: RoadNarrows Robotics Application Tool Kit
4 //
5 // Library: librnr_win
6 //
7 // File: WinMenu.cxx
8 //
9 /*! \file
10  *
11  * $LastChangedDate: 2013-05-03 07:45:13 -0600 (Fri, 03 May 2013) $
12  * $Rev: 2904 $
13  *
14  * \brief RoadNarrows Robotics window base window button menu implementation.
15  *
16  * \author Robin Knight (robin.knight@roadnarrows.com)
17  * \author Daniel Packard (daniel@roadnarrows.com)
18  *
19  * \par Copyright
20  * \h_copy 2011-2017. RoadNarrows LLC.\n
21  * http://www.roadnarrows.com\n
22  * All Rights Reserved
23  */
24 /*
25  * @EulaBegin@
26  *
27  * Permission is hereby granted, without written agreement and without
28  * license or royalty fees, to use, copy, modify, and distribute this
29  * software and its documentation for any purpose, provided that
30  * (1) The above copyright notice and the following two paragraphs
31  * appear in all copies of the source code and (2) redistributions
32  * including binaries reproduces these notices in the supporting
33  * documentation. Substantial modifications to this software may be
34  * copyrighted by their authors and need not follow the licensing terms
35  * described here, provided that the new terms are clearly indicated in
36  * all files where they apply.
37  *
38  * IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY MEMBERS/EMPLOYEES
39  * OF ROADNARROW LLC OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
40  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
41  * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
42  * EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
43  * THE POSSIBILITY OF SUCH DAMAGE.
44  *
45  * THE AUTHOR AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
46  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
47  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
48  * "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
49  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
50  *
51  * @EulaEnd@
52  */
53 ////////////////////////////////////////////////////////////////////////////////
54 
55 #include <sys/types.h>
56 #include <limits.h>
57 #include <stdio.h>
58 #include <libgen.h>
59 #include <unistd.h>
60 #include <stdarg.h>
61 #include <errno.h>
62 
63 #include <string>
64 
65 #include "rnr/rnrconfig.h"
66 #include "rnr/log.h"
67 
68 #include "rnr/appkit/Win.h"
69 #include "rnr/appkit/WinMenu.h"
70 
71 
72 using namespace std;
73 using namespace rnr;
74 
75 
76 //.............................................................................
77 // Class WinButton
78 //.............................................................................
79 
80 void WinButton::copy(const WinButton *pSrc)
81 {
82  m_eType = pSrc->m_eType;
83  m_nEvent = pSrc->m_nEvent;
84  m_eInitState = pSrc->m_eInitState;
85  m_eState = pSrc->m_eInitState;
86  m_eAlign = pSrc->m_eAlign;
87  m_strAltText = pSrc->m_strAltText;
88  m_strTagNormal = pSrc->m_strTagNormal;
89  m_strToolTipNormal = pSrc->m_strToolTipNormal;
90  m_strTagActive = pSrc->m_strTagActive;
91  m_strToolTipActive = pSrc->m_strToolTipActive;
92 }
93 
94 void *WinButton::getCurrentImageWidget()
95 {
96  if( m_eType != WinButtonTypeImage )
97  {
98  return NULL;
99  }
100  else if( (m_eState == WidgetStateActive) && (getActiveImageWidget() != NULL) )
101  {
102  return getActiveImageWidget();
103  }
104  else
105  {
106  return getNormalImageWidget();
107  }
108 }
109 
110 string WinButton::getCurrentLabel()
111 {
112  if( m_eType != WinButtonTypeLabel )
113  {
114  return "";
115  }
116  else if( (m_eState == WidgetStateActive) && !m_strTagActive.empty() )
117  {
118  return m_strTagActive;
119  }
120  else
121  {
122  return m_strTagNormal;
123  }
124 }
125 
126 string WinButton::getCurrentToolTip()
127 {
128  if( m_eState == WidgetStateActive )
129  {
130  switch( m_eType )
131  {
132  case WinButtonTypeImage:
133  if( getActiveImageWidget() != NULL )
134  {
135  return m_strToolTipActive;
136  }
137  break;
138  case WinButtonTypeLabel:
139  if( !m_strTagActive.empty() )
140  {
141  return m_strToolTipActive;
142  }
143  break;
144  default:
145  break;
146  }
147  }
148  return m_strToolTipNormal;
149 }
150 
151 
152 //.............................................................................
153 // Class WinButtonMenu
154 //.............................................................................
155 
156 WinButtonMenu::~WinButtonMenu()
157 {
158  MapBttns_T::iterator iter;
159 
160  for(iter=m_mapButtons.begin(); iter!=m_mapButtons.end(); ++iter)
161  {
162  delete iter->second;
163  }
164  m_mapButtons.clear();
165 }
166 
167 void WinButtonMenu::bind(Win *pWin)
168 {
169  MapBttns_T::iterator iter;
170  WinButton *pButton;
171 
172  if( pWin == NULL )
173  {
174  LOGERROR("Binding window is NULL.");
175  return;
176  }
177 
178  // unbind any previous menu
179  if( m_pWin != NULL )
180  {
181  unbind();
182  }
183 
184  m_pWin = pWin;
185 
186  // add menu items to bound window
187  for(iter=m_mapButtons.begin(); iter!=m_mapButtons.end(); ++iter)
188  {
189  pButton = iter->second;
190 
191  switch( pButton->m_eType )
192  {
193  case WinButtonTypeImage:
194  m_pWin->addImageButton(pButton->m_nEvent,
195  pButton->m_eAlign,
196  pButton->getCurrentImageWidget(),
197  pButton->m_strAltText,
198  pButton->getCurrentToolTip());
199  break;
200  case WinButtonTypeLabel:
201  m_pWin->addLabelButton(pButton->m_nEvent,
202  pButton->m_eAlign,
203  pButton->getCurrentLabel(),
204  pButton->getCurrentToolTip());
205  break;
206  default:
207  break;
208  }
209  }
210 
211  // reset menu item states
212  resetAllButtonStates();
213 
214  // register menu button press callback
215  m_pWin->registerButtonClickCallback(WinButtonMenu::onMenuButtonClick, this);
216 }
217 
218 void WinButtonMenu::unbind()
219 {
220  if( m_pWin != NULL )
221  {
222  m_pWin->unregisterButtonClickCallback();
223  m_pWin->removeAllButtons();
224  m_pWin = NULL;
225  resetAllButtonStates();
226  }
227 }
228 
229 void WinButtonMenu::setButtonStateList(const string &strEvent, ...)
230 {
231  va_list ap;
232  size_t i;
233  int nEvent;
234  WidgetState eNewState;
235  MapBttns_T::iterator pos;
236 
237  LOGDIAG3("'%s' bulk menu state changes.", strEvent.c_str());
238 
239  va_start(ap, strEvent);
240 
241  //
242  // Loop through button map, but limit to number of buttons.
243  //
244  for(i=0; i<m_mapButtons.size(); ++i)
245  {
246  nEvent = va_arg(ap, int);
247 
248  // stop criteria
249  if( nEvent == UIEventNone )
250  {
251  break;
252  }
253 
254  eNewState = (WidgetState)va_arg(ap, int);
255 
256  if( (pos = m_mapButtons.find(nEvent)) != m_mapButtons.end() )
257  {
258  changeButtonState(pos->second, eNewState);
259  }
260  }
261 
262  va_end(ap);
263 }
264 
265 void WinButtonMenu::resetAllButtonStates()
266 {
267  MapBttns_T::iterator iter;
268 
269  for(iter=m_mapButtons.begin(); iter!=m_mapButtons.end(); ++iter)
270  {
271  changeButtonState(iter->second, iter->second->m_eInitState);
272  }
273 }
274 
275 string WinButtonMenu::makeIconPath(const string &strIconFile)
276 {
277  string strPath; // working path of search directories
278  string strIconFqName; // icon fully-qualified file name
279  size_t pos1; // substring starting position 1
280  size_t pos2; // substring ending position 2
281 
282  //
283  // No file name. Note this is not an error.
284  //
285  if( strIconFile.empty() )
286  {
287  return strIconFqName;
288  }
289 
290  //
291  // Icon file name is an absolute path.
292  //
293  if( strIconFile[0] == DIR_SEP_CHAR )
294  {
295  strIconFqName = strIconFile;
296  if( access(strIconFqName.c_str(), F_OK|R_OK) != 0 )
297  {
298  LOGWARN("%s: %s(errno=%d)",
299  strIconFqName.c_str(), strerror(errno), errno);
300  strIconFqName.clear();
301  }
302  return strIconFqName;
303  }
304 
305  //
306  // Search for file.
307  //
308  if( m_strIconPath.empty() )
309  {
310  strPath = ".";
311  }
312  else
313  {
314  strPath = m_strIconPath + PATH_SEP_STR + ".";
315  }
316 
317  for(pos1=0, pos2=strPath.find(PATH_SEP_STR, pos1);
318  pos1 != strPath.npos;
319  pos1=pos2+1, pos2=strPath.find(PATH_SEP_STR, pos1))
320  {
321  strIconFqName = strPath.substr(pos1, pos2) + DIR_SEP_STR + strIconFile;
322  if( access(strIconFqName.c_str(), F_OK|R_OK) == 0 )
323  {
324  return strIconFqName;
325  }
326  }
327 
328  //
329  // Failed to find icon file.
330  //
331  LOGWARN("%s: Icon not found in %s.", strIconFile.c_str(), strPath.c_str());
332 
333  strIconFqName.clear();
334 
335  return strIconFqName;
336 }
337 
338 void WinButtonMenu::changeButtonState(WinButton *pButton, WidgetState eNewState)
339 {
340  WidgetState eCurState;
341 
342  eCurState = pButton->m_eState;
343  pButton->m_eState = eNewState;
344 
345  if( m_pWin != NULL )
346  {
347  switch( pButton->m_eType )
348  {
349  case WinButtonTypeImage:
350  if( pButton->getActiveImageWidget() != NULL )
351  {
352  // normal,disabled --> active
353  if( (eCurState != WidgetStateActive) &&
354  (eNewState == WidgetStateActive) )
355  {
356  m_pWin->replaceButtonImage(pButton->m_nEvent,
357  pButton->getActiveImageWidget(),
358  pButton->m_strToolTipActive);
359  }
360  // active --> normal,disabled
361  else if( (eCurState == WidgetStateActive) &&
362  (eNewState != WidgetStateActive) )
363  {
364  m_pWin->replaceButtonImage(pButton->m_nEvent,
365  pButton->getNormalImageWidget(),
366  pButton->m_strToolTipNormal);
367  }
368  }
369  break;
370  case WinButtonTypeLabel:
371  if( !pButton->m_strTagActive.empty() )
372  {
373  // normal,disabled --> active
374  if( (eCurState != WidgetStateActive) &&
375  (eNewState == WidgetStateActive) )
376  {
377  m_pWin->replaceButtonLabel(pButton->m_nEvent,
378  pButton->m_strTagActive,
379  pButton->m_strToolTipActive);
380  }
381  // active --> normal,disabled
382  else if( (eCurState == WidgetStateActive) &&
383  (eNewState != WidgetStateActive) )
384  {
385  m_pWin->replaceButtonImage(pButton->m_nEvent,
386  pButton->m_strTagNormal,
387  pButton->m_strToolTipNormal);
388  }
389  }
390  break;
391  }
392 
393  // show gui widget state
394  m_pWin->showButtonState(pButton->m_nEvent, eNewState);
395  }
396 }
397 
398 void WinButtonMenu::onMenuButtonClick(int nEvent, void *user_data)
399 {
400  WinButtonMenu *pMenu = (WinButtonMenu *)user_data;
401  MapBttns_T::iterator pos;
402  WidgetState eState;
403 
404  pMenu->setCurrentEvent(nEvent);
405 
406  if( (pos = pMenu->m_mapButtons.find(nEvent)) != pMenu->m_mapButtons.end() )
407  {
408  eState = pos->second->m_eState;
409 
410  // toggle state
411  if( eState == WidgetStateNormal )
412  {
413  pMenu->changeButtonState(pos->second, WidgetStateActive);
414  }
415  else if( eState == WidgetStateActive )
416  {
417  pMenu->changeButtonState(pos->second, WidgetStateNormal);
418  }
419  }
420 }
WidgetState
Definition: Win.h:129
WinButtonType m_eType
button type
Definition: WinMenu.h:201
WidgetState m_eInitState
initial button widget state
Definition: WinMenu.h:203
Window button menu base class.
Definition: WinMenu.h:232
MapBttns_T m_mapButtons
menu button map
Definition: WinMenu.h:486
std::string getCurrentLabel()
Get the text label associated with the current button state.
Definition: WinMenu.cxx:110
virtual void * getActiveImageWidget()
Get the active icon image widget.
Definition: WinMenu.h:169
virtual void * getNormalImageWidget()
Get the normal icon image widget.
Definition: WinMenu.h:158
AlignOp m_eAlign
left or right alignment
Definition: WinMenu.h:205
std::string m_strAltText
alternate text for icon(s)
Definition: WinMenu.h:206
WidgetState m_eState
current button widget state
Definition: WinMenu.h:204
RoadNarrows Robotics Win abstract base class interface.
RoadNarrows Robotics base window button menu interface.
button has text label(s)
Definition: WinMenu.h:84
no action
Definition: Win.h:115
int m_nEvent
button push "mouse click" event
Definition: WinMenu.h:202
std::string m_strTagNormal
button icon for normal state
Definition: WinMenu.h:207
std::string getCurrentToolTip()
Get the tooltip associated with the current button state.
Definition: WinMenu.cxx:126
normal - enabled but not selected
Definition: Win.h:131
button has image(s)
Definition: WinMenu.h:83
std::string m_strToolTipActive
button tooltip for active state
Definition: WinMenu.h:210
int setCurrentEvent(int nNewEvent)
Set the current button menu event.
Definition: WinMenu.h:402
std::string m_strToolTipNormal
button tooltip for normal state
Definition: WinMenu.h:208
RNR Win window abstract base class.
Definition: Win.h:211
Window button base class.
Definition: WinMenu.h:94
void changeButtonState(WinButton *pButton, WidgetState eNewState)
Change the state and gui look of the given button.
Definition: WinMenu.cxx:338
selected
Definition: Win.h:132
void * getCurrentImageWidget()
Get the icon image widget associated with the current button state.
Definition: WinMenu.cxx:94
RoadNarrows Robotics.
Definition: Camera.h:74
std::string m_strTagActive
button icon for active state
Definition: WinMenu.h:209