]> git.saurik.com Git - wxWidgets.git/blob - src/motif/toolbar.cpp
Corrections to Forty Thieves; wxMemoryDC problem temporarily sorted
[wxWidgets.git] / src / motif / toolbar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: toolbar.cpp
3 // Purpose: wxToolBar
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "toolbar.h"
14 #endif
15
16 #include "wx/wx.h"
17 #include "wx/app.h"
18 #include "wx/timer.h"
19 #include "wx/motif/toolbar.h"
20
21 #include <Xm/Xm.h>
22 #include <Xm/PushBG.h>
23 #include <Xm/PushB.h>
24 #include <Xm/Label.h>
25 #include <Xm/ToggleB.h>
26 #include <Xm/ToggleBG.h>
27 #include <Xm/Form.h>
28
29 #include "wx/motif/private.h"
30
31 #if !USE_SHARED_LIBRARY
32 IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
33
34 BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
35 END_EVENT_TABLE()
36 #endif
37
38 static void wxToolButtonCallback (Widget w, XtPointer clientData,
39 XtPointer ptr);
40 static void wxToolButtonPopupCallback (Widget w, XtPointer client_data,
41 XEvent *event, Boolean *continue_to_dispatch);
42
43 class wxToolBarTimer: public wxTimer
44 {
45 public:
46 wxToolBarTimer() { }
47 virtual void Notify();
48
49 static Widget help_popup;
50 static Widget buttonWidget;
51 static wxString helpString;
52 };
53
54 static wxToolBarTimer* wxTheToolBarTimer = (wxToolBarTimer*) NULL;
55
56 Widget wxToolBarTimer::help_popup = (Widget) 0;
57 Widget wxToolBarTimer::buttonWidget = (Widget) 0;
58 wxString wxToolBarTimer::helpString = "";
59
60 wxToolBar::wxToolBar():
61 m_widgets(wxKEY_INTEGER)
62 {
63 m_maxWidth = -1;
64 m_maxHeight = -1;
65 m_defaultWidth = 24;
66 m_defaultHeight = 22;
67 }
68
69 bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
70 long style, const wxString& name)
71 {
72 m_maxWidth = -1;
73 m_maxHeight = -1;
74
75 m_defaultWidth = 24;
76 m_defaultHeight = 22;
77 SetName(name);
78 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE);
79 m_foregroundColour = parent->GetForegroundColour();
80 m_windowStyle = style;
81
82 SetParent(parent);
83
84 if (parent) parent->AddChild(this);
85
86 Widget parentWidget = (Widget) parent->GetClientWidget();
87
88 Widget toolbar = XtVaCreateManagedWidget("toolbar",
89 xmBulletinBoardWidgetClass, (Widget) parentWidget,
90 XmNmarginWidth, 0,
91 XmNmarginHeight, 0,
92 XmNresizePolicy, XmRESIZE_NONE,
93 NULL);
94 /*
95 Widget toolbar = XtVaCreateManagedWidget("toolbar",
96 xmFormWidgetClass, (Widget) m_clientWidget,
97 XmNtraversalOn, False,
98 XmNhorizontalSpacing, 0,
99 XmNverticalSpacing, 0,
100 XmNleftOffset, 0,
101 XmNrightOffset, 0,
102 XmNmarginWidth, 0,
103 XmNmarginHeight, 0,
104 NULL);
105 */
106
107 m_mainWidget = (WXWidget) toolbar;
108
109 m_windowFont = parent->GetFont();
110 ChangeFont(FALSE);
111
112 SetCanAddEventHandler(TRUE);
113 AttachWidget (parent, m_mainWidget, (WXWidget) NULL, pos.x, pos.y, size.x, size.y);
114
115 ChangeBackgroundColour();
116
117 return TRUE;
118 }
119
120 wxToolBar::~wxToolBar()
121 {
122 delete wxTheToolBarTimer;
123 wxTheToolBarTimer = NULL;
124 ClearTools();
125 DestroyPixmaps();
126 }
127
128 bool wxToolBar::CreateTools()
129 {
130 if (m_tools.Number() == 0)
131 return FALSE;
132
133 // Separator spacing
134 const int separatorSize = GetToolSeparation(); // 8;
135 wxSize margins = GetToolMargins();
136 int marginX = margins.x;
137 int marginY = margins.y;
138
139 int currentX = marginX;
140 int currentY = marginY;
141
142 int buttonHeight = 0;
143
144 int currentSpacing = 0;
145
146 m_widgets.Clear();
147 Widget prevButton = (Widget) 0;
148 wxNode* node = m_tools.First();
149 while (node)
150 {
151 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
152
153 if (tool->m_toolStyle == wxTOOL_STYLE_SEPARATOR)
154 currentX += separatorSize;
155 else if (tool->m_bitmap1.Ok())
156 {
157 Widget button = (Widget) 0;
158
159 if (tool->m_isToggle)
160 {
161 button = XtVaCreateWidget("toggleButton",
162 xmToggleButtonWidgetClass, (Widget) m_mainWidget,
163 XmNx, currentX, XmNy, currentY,
164 // XmNpushButtonEnabled, True,
165 XmNmultiClick, XmMULTICLICK_KEEP,
166 XmNlabelType, XmPIXMAP,
167 NULL);
168 XtAddCallback ((Widget) button, XmNvalueChangedCallback, (XtCallbackProc) wxToolButtonCallback,
169 (XtPointer) this);
170 }
171 else
172 {
173 button = XtVaCreateWidget("button",
174 xmPushButtonWidgetClass, (Widget) m_mainWidget,
175 XmNx, currentX, XmNy, currentY,
176 XmNpushButtonEnabled, True,
177 XmNmultiClick, XmMULTICLICK_KEEP,
178 XmNlabelType, XmPIXMAP,
179 NULL);
180 XtAddCallback (button,
181 XmNactivateCallback, (XtCallbackProc) wxToolButtonCallback,
182 (XtPointer) this);
183 }
184
185 // For each button, if there is a mask, we must create
186 // a new wxBitmap that has the correct background colour
187 // for the button. Otherwise the background will just be
188 // e.g. black if a transparent XPM has been loaded.
189 wxBitmap originalBitmap = tool->m_bitmap1;
190
191 if (tool->m_bitmap1.GetMask())
192 {
193 int backgroundPixel;
194 XtVaGetValues(button, XmNbackground, &backgroundPixel,
195 NULL);
196
197
198 wxColour col;
199 col.SetPixel(backgroundPixel);
200
201 wxBitmap newBitmap = wxCreateMaskedBitmap(tool->m_bitmap1, col);
202
203 tool->m_bitmap1 = newBitmap;
204 }
205
206 // Create a selected/toggled bitmap. If there isn't a m_bitmap2,
207 // we need to create it (with a darker, selected background)
208 int backgroundPixel;
209 if (tool->m_isToggle)
210 XtVaGetValues(button, XmNselectColor, &backgroundPixel,
211 NULL);
212 else
213 XtVaGetValues(button, XmNarmColor, &backgroundPixel,
214 NULL);
215
216 wxColour col;
217 col.SetPixel(backgroundPixel);
218
219 if (tool->m_bitmap2.Ok() && tool->m_bitmap2.GetMask())
220 {
221 // Use what's there
222 wxBitmap newBitmap = wxCreateMaskedBitmap(tool->m_bitmap2, col);
223 tool->m_bitmap2 = newBitmap;
224 }
225 else
226 {
227 // Use unselected bitmap
228 if (originalBitmap.GetMask())
229 {
230 wxBitmap newBitmap = wxCreateMaskedBitmap(originalBitmap, col);
231 tool->m_bitmap2 = newBitmap;
232 }
233 else
234 tool->m_bitmap2 = tool->m_bitmap1;
235 }
236
237 Pixmap pixmap = (Pixmap) tool->m_bitmap1.GetPixmap();
238 Pixmap insensPixmap = (Pixmap) tool->m_bitmap1.GetInsensPixmap();
239
240 if (tool->m_isToggle)
241 {
242 // Toggle button
243 Pixmap pixmap2 = (Pixmap) 0;
244 Pixmap insensPixmap2 = (Pixmap) 0;
245
246 // If there's a bitmap for the toggled state, use it,
247 // otherwise generate one.
248 if (tool->m_bitmap2.Ok())
249 {
250 pixmap2 = (Pixmap) tool->m_bitmap2.GetPixmap();
251 insensPixmap2 = (Pixmap) tool->m_bitmap2.GetInsensPixmap();
252 }
253 else
254 {
255 pixmap2 = (Pixmap) tool->m_bitmap1.GetArmPixmap(button);
256 insensPixmap2 = XCreateInsensitivePixmap((Display*) wxGetDisplay(), pixmap2);
257 m_pixmaps.Append((wxObject*) insensPixmap2); // Store for later deletion
258 }
259 XtVaSetValues (button,
260 XmNindicatorOn, False,
261 XmNshadowThickness, 2,
262 // XmNborderWidth, 0,
263 // XmNspacing, 0,
264 XmNmarginWidth, 0,
265 XmNmarginHeight, 0,
266 XmNfillOnSelect, True,
267 XmNlabelPixmap, pixmap,
268 XmNselectPixmap, pixmap2,
269 XmNlabelInsensitivePixmap, insensPixmap,
270 XmNselectInsensitivePixmap, insensPixmap2,
271 XmNlabelType, XmPIXMAP,
272 NULL);
273 }
274 else
275 {
276 Pixmap pixmap2 = (Pixmap) 0;
277
278 // If there's a bitmap for the armed state, use it,
279 // otherwise generate one.
280 if (tool->m_bitmap2.Ok())
281 {
282 pixmap2 = (Pixmap) tool->m_bitmap2.GetPixmap();
283 }
284 else
285 {
286 pixmap2 = (Pixmap) tool->m_bitmap1.GetArmPixmap(button);
287
288 }
289 // Normal button
290 XtVaSetValues(button,
291 XmNlabelPixmap, pixmap,
292 XmNlabelInsensitivePixmap, insensPixmap,
293 XmNarmPixmap, pixmap2,
294 NULL);
295 }
296 XtManageChild(button);
297
298 Dimension width, height;
299 XtVaGetValues(button, XmNwidth, & width, XmNheight, & height,
300 NULL);
301 currentX += width + marginX;
302 buttonHeight = wxMax(buttonHeight, height);
303
304 XtAddEventHandler (button, EnterWindowMask | LeaveWindowMask,
305 False, wxToolButtonPopupCallback, (XtPointer) this);
306 m_widgets.Append(tool->m_index, (wxObject*) button);
307
308 prevButton = button;
309 currentSpacing = 0;
310 }
311 node = node->Next();
312 }
313
314 SetSize(-1, -1, currentX, buttonHeight + 2*marginY);
315
316 return TRUE;
317 }
318
319 // Old version, assuming we use a form. Now we use
320 // a bulletin board, so we can create controls on the toolbar.
321 #if 0
322 bool wxToolBar::CreateTools()
323 {
324 if (m_tools.Number() == 0)
325 return FALSE;
326
327 // Separator spacing
328 const int separatorSize = GetToolSeparation(); // 8;
329
330 int currentSpacing = 0;
331
332 m_widgets.Clear();
333 Widget prevButton = (Widget) 0;
334 wxNode* node = m_tools.First();
335 while (node)
336 {
337 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
338
339 if (tool->m_toolStyle == wxTOOL_STYLE_SEPARATOR)
340 currentSpacing = separatorSize;
341 else if (tool->m_bitmap1.Ok())
342 {
343 Widget button = (Widget) 0;
344
345 if (tool->m_isToggle)
346 {
347 button = XtVaCreateManagedWidget("toggleButton",
348 xmToggleButtonWidgetClass, (Widget) m_mainWidget,
349 XmNleftAttachment, (prevButton == (Widget) 0) ? XmATTACH_FORM : XmATTACH_WIDGET,
350 XmNleftWidget, (prevButton == (Widget) 0) ? NULL : prevButton,
351 XmNleftOffset, currentSpacing,
352 XmNtopAttachment, XmATTACH_FORM,
353 // XmNpushButtonEnabled, True,
354 XmNmultiClick, XmMULTICLICK_KEEP,
355 XmNlabelType, XmPIXMAP,
356 NULL);
357 XtAddCallback ((Widget) button, XmNvalueChangedCallback, (XtCallbackProc) wxToolButtonCallback,
358 (XtPointer) this);
359 }
360 else
361 {
362 button = XtVaCreateManagedWidget("button",
363 xmPushButtonWidgetClass, (Widget) m_mainWidget,
364 XmNleftAttachment, (prevButton == (Widget) 0) ? XmATTACH_FORM : XmATTACH_WIDGET,
365 XmNleftWidget, (prevButton == (Widget) 0) ? NULL : prevButton,
366 XmNleftOffset, currentSpacing,
367 XmNtopAttachment, XmATTACH_FORM,
368 XmNpushButtonEnabled, True,
369 XmNmultiClick, XmMULTICLICK_KEEP,
370 XmNlabelType, XmPIXMAP,
371 NULL);
372 XtAddCallback (button,
373 XmNactivateCallback, (XtCallbackProc) wxToolButtonCallback,
374 (XtPointer) this);
375 }
376
377 // For each button, if there is a mask, we must create
378 // a new wxBitmap that has the correct background colour
379 // for the button. Otherwise the background will just be
380 // e.g. black if a transparent XPM has been loaded.
381 wxBitmap originalBitmap = tool->m_bitmap1;
382
383 if (tool->m_bitmap1.GetMask())
384 {
385 int backgroundPixel;
386 XtVaGetValues(button, XmNbackground, &backgroundPixel,
387 NULL);
388
389
390 wxColour col;
391 col.SetPixel(backgroundPixel);
392
393 wxBitmap newBitmap = wxCreateMaskedBitmap(tool->m_bitmap1, col);
394
395 tool->m_bitmap1 = newBitmap;
396 }
397
398 // Create a selected/toggled bitmap. If there isn't a m_bitmap2,
399 // we need to create it (with a darker, selected background)
400 int backgroundPixel;
401 if (tool->m_isToggle)
402 XtVaGetValues(button, XmNselectColor, &backgroundPixel,
403 NULL);
404 else
405 XtVaGetValues(button, XmNarmColor, &backgroundPixel,
406 NULL);
407
408 wxColour col;
409 col.SetPixel(backgroundPixel);
410
411 if (tool->m_bitmap2.Ok() && tool->m_bitmap2.GetMask())
412 {
413 // Use what's there
414 wxBitmap newBitmap = wxCreateMaskedBitmap(tool->m_bitmap2, col);
415 tool->m_bitmap2 = newBitmap;
416 }
417 else
418 {
419 // Use unselected bitmap
420 if (originalBitmap.GetMask())
421 {
422 wxBitmap newBitmap = wxCreateMaskedBitmap(originalBitmap, col);
423 tool->m_bitmap2 = newBitmap;
424 }
425 else
426 tool->m_bitmap2 = tool->m_bitmap1;
427 }
428
429 Pixmap pixmap = (Pixmap) tool->m_bitmap1.GetPixmap();
430 Pixmap insensPixmap = (Pixmap) tool->m_bitmap1.GetInsensPixmap();
431
432 if (tool->m_isToggle)
433 {
434 // Toggle button
435 Pixmap pixmap2 = (Pixmap) 0;
436 Pixmap insensPixmap2 = (Pixmap) 0;
437
438 // If there's a bitmap for the toggled state, use it,
439 // otherwise generate one.
440 if (tool->m_bitmap2.Ok())
441 {
442 pixmap2 = (Pixmap) tool->m_bitmap2.GetPixmap();
443 insensPixmap2 = (Pixmap) tool->m_bitmap2.GetInsensPixmap();
444 }
445 else
446 {
447 pixmap2 = (Pixmap) tool->m_bitmap1.GetArmPixmap(button);
448 insensPixmap2 = XCreateInsensitivePixmap((Display*) wxGetDisplay(), pixmap2);
449 m_pixmaps.Append((wxObject*) insensPixmap2); // Store for later deletion
450 }
451 XtVaSetValues (button,
452 XmNindicatorOn, False,
453 XmNshadowThickness, 2,
454 // XmNborderWidth, 0,
455 // XmNspacing, 0,
456 XmNmarginWidth, 0,
457 XmNmarginHeight, 0,
458 XmNfillOnSelect, True,
459 XmNlabelPixmap, pixmap,
460 XmNselectPixmap, pixmap2,
461 XmNlabelInsensitivePixmap, insensPixmap,
462 XmNselectInsensitivePixmap, insensPixmap2,
463 XmNlabelType, XmPIXMAP,
464 NULL);
465 }
466 else
467 {
468 Pixmap pixmap2 = (Pixmap) 0;
469
470 // If there's a bitmap for the armed state, use it,
471 // otherwise generate one.
472 if (tool->m_bitmap2.Ok())
473 {
474 pixmap2 = (Pixmap) tool->m_bitmap2.GetPixmap();
475 }
476 else
477 {
478 pixmap2 = (Pixmap) tool->m_bitmap1.GetArmPixmap(button);
479
480 }
481 // Normal button
482 XtVaSetValues(button,
483 XmNlabelPixmap, pixmap,
484 XmNlabelInsensitivePixmap, insensPixmap,
485 XmNarmPixmap, pixmap2,
486 NULL);
487 }
488
489 XtAddEventHandler (button, EnterWindowMask | LeaveWindowMask,
490 False, wxToolButtonPopupCallback, (XtPointer) this);
491 m_widgets.Append(tool->m_index, (wxObject*) button);
492
493 prevButton = button;
494 currentSpacing = 0;
495 }
496 node = node->Next();
497 }
498
499 return TRUE;
500 }
501 #endif
502
503 void wxToolBar::SetToolBitmapSize(const wxSize& size)
504 {
505 // TODO not necessary?
506 m_defaultWidth = size.x; m_defaultHeight = size.y;
507 }
508
509 wxSize wxToolBar::GetMaxSize() const
510 {
511 int w, h;
512 GetSize(& w, & h);
513
514 return wxSize(w, h);
515 }
516
517 // The button size is bigger than the bitmap size
518 wxSize wxToolBar::GetToolSize() const
519 {
520 // TODO not necessary?
521 return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
522 }
523
524 void wxToolBar::EnableTool(int toolIndex, bool enable)
525 {
526 wxNode *node = m_tools.Find((long)toolIndex);
527 if (node)
528 {
529 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
530 tool->m_enabled = enable;
531
532 WXWidget widget = FindWidgetForIndex(tool->m_index);
533 if (widget == (WXWidget) 0)
534 return;
535
536 XtSetSensitive((Widget) widget, (Boolean) enable);
537 }
538 }
539
540 void wxToolBar::ToggleTool(int toolIndex, bool toggle)
541 {
542 wxNode *node = m_tools.Find((long)toolIndex);
543 if (node)
544 {
545 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
546 if (tool->m_isToggle)
547 {
548 tool->m_toggleState = toggle;
549
550 WXWidget widget = FindWidgetForIndex(tool->m_index);
551 if (widget == (WXWidget) 0)
552 return;
553
554 XmToggleButtonSetState((Widget) widget, (Boolean) toggle, False);
555 }
556 }
557 }
558
559 void wxToolBar::ClearTools()
560 {
561 wxNode* node = m_widgets.First();
562 while (node)
563 {
564 Widget button = (Widget) node->Data();
565 XtDestroyWidget(button);
566 node = node->Next();
567 }
568 m_widgets.Clear();
569 DestroyPixmaps();
570
571 wxToolBarBase::ClearTools();
572 }
573
574 void wxToolBar::DestroyPixmaps()
575 {
576 wxNode* node = m_pixmaps.First();
577 while (node)
578 {
579 Pixmap pixmap = (Pixmap) node->Data();
580 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) GetXDisplay()), pixmap);
581 node = node->Next();
582 }
583 m_pixmaps.Clear();
584 }
585
586 // If pushedBitmap is NULL, a reversed version of bitmap is
587 // created and used as the pushed/toggled image.
588 // If toggle is TRUE, the button toggles between the two states.
589
590 wxToolBarTool *wxToolBar::AddTool(int index, const wxBitmap& bitmap, const wxBitmap& pushedBitmap,
591 bool toggle, long xPos, long yPos, wxObject *clientData, const wxString& helpString1, const wxString& helpString2)
592 {
593 wxToolBarTool *tool = new wxToolBarTool(index, bitmap, wxNullBitmap, toggle, xPos, yPos, helpString1, helpString2);
594 tool->m_clientData = clientData;
595
596 if (xPos > -1)
597 tool->m_x = xPos;
598 else
599 tool->m_x = m_xMargin;
600
601 if (yPos > -1)
602 tool->m_y = yPos;
603 else
604 tool->m_y = m_yMargin;
605
606 tool->SetSize(GetDefaultButtonWidth(), GetDefaultButtonHeight());
607
608 m_tools.Append((long)index, tool);
609 return tool;
610 }
611
612 int wxToolBar::FindIndexForWidget(WXWidget w)
613 {
614 wxNode* node = m_widgets.First();
615 while (node)
616 {
617 WXWidget widget = (WXWidget) node->Data();
618 if (widget == w)
619 return (int) node->GetKeyInteger();
620 node = node->Next();
621 }
622 return -1;
623 }
624
625 WXWidget wxToolBar::FindWidgetForIndex(int index)
626 {
627 wxNode* node = m_widgets.Find((long) index);
628 if (!node)
629 return (WXWidget) 0;
630 else
631 return (WXWidget) node->Data();
632 }
633
634 WXWidget wxToolBar::GetTopWidget() const
635 {
636 return m_mainWidget;
637 }
638
639 WXWidget wxToolBar::GetClientWidget() const
640 {
641 return m_mainWidget;
642 }
643
644 WXWidget wxToolBar::GetMainWidget() const
645 {
646 return m_mainWidget;
647 }
648
649
650 void wxToolButtonCallback (Widget w, XtPointer clientData,
651 XtPointer ptr)
652 {
653 wxToolBar *toolBar = (wxToolBar *) clientData;
654 int index = toolBar->FindIndexForWidget((WXWidget) w);
655
656 if (index != -1)
657 {
658 wxNode *node = toolBar->GetTools().Find((long)index);
659 if (!node)
660 return;
661 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
662 if (tool->m_isToggle)
663 tool->m_toggleState = toolBar->GetToolState(index);
664
665 (void) toolBar->OnLeftClick(index, tool->m_toggleState);
666 }
667
668 }
669
670
671 static void wxToolButtonPopupCallback (Widget w, XtPointer client_data,
672 XEvent *event, Boolean *continue_to_dispatch)
673 {
674 // TODO: retrieve delay before popping up tooltip from wxSystemSettings.
675 int delayMilli = 800;
676 wxToolBar* toolBar = (wxToolBar*) client_data;
677
678 int index = toolBar->FindIndexForWidget((WXWidget) w);
679
680 if (index != -1)
681 {
682 wxNode *node = toolBar->GetTools().Find((long)index);
683 if (!node)
684 return;
685 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
686 wxString str(toolBar->GetToolShortHelp(index));
687 if (str.IsNull() || str == "")
688 return;
689
690 if (!wxTheToolBarTimer)
691 wxTheToolBarTimer = new wxToolBarTimer;
692
693 wxToolBarTimer::buttonWidget = w;
694 wxToolBarTimer::helpString = str;
695
696
697 /************************************************************/
698 /* Popup help label */
699 /************************************************************/
700 if (event->type == EnterNotify)
701 {
702 if (wxToolBarTimer::help_popup != (Widget) 0)
703 {
704 XtDestroyWidget (wxToolBarTimer::help_popup);
705 XtPopdown (wxToolBarTimer::help_popup);
706 }
707 wxToolBarTimer::help_popup = (Widget) 0;
708
709 // One shot
710 wxTheToolBarTimer->Start(delayMilli, TRUE);
711
712 }
713 /************************************************************/
714 /* Popdown help label */
715 /************************************************************/
716 else if (event->type == LeaveNotify)
717 {
718 if (wxTheToolBarTimer)
719 wxTheToolBarTimer->Stop();
720 if (wxToolBarTimer::help_popup != (Widget) 0)
721 {
722 XtDestroyWidget (wxToolBarTimer::help_popup);
723 XtPopdown (wxToolBarTimer::help_popup);
724 }
725 wxToolBarTimer::help_popup = (Widget) 0;
726 }
727 }
728 }
729
730 void wxToolBarTimer::Notify()
731 {
732 Position x, y;
733
734 /************************************************************/
735 /* Create shell without window decorations */
736 /************************************************************/
737 help_popup = XtVaCreatePopupShell ("shell",
738 overrideShellWidgetClass, (Widget) wxTheApp->GetTopLevelWidget(),
739 NULL);
740
741 /************************************************************/
742 /* Get absolute position on display of toolbar button */
743 /************************************************************/
744 XtTranslateCoords (buttonWidget,
745 (Position) 0,
746 (Position) 0,
747 &x, &y);
748
749 // Move the tooltip more or less above the button
750 int yOffset = 20; // TODO: What should be really?
751 y -= yOffset;
752 if (y < yOffset) y = 0;
753
754 /************************************************************/
755 /* Set the position of the help popup */
756 /************************************************************/
757 XtVaSetValues (help_popup,
758 XmNx, (Position) x,
759 XmNy, (Position) y,
760 NULL);
761
762 /************************************************************/
763 /* Create help label */
764 /************************************************************/
765 XmString text = XmStringCreateSimple ((char*) (const char*) helpString);
766 XtVaCreateManagedWidget ("help_label",
767 xmLabelWidgetClass, help_popup,
768 XmNlabelString, text,
769 XtVaTypedArg,
770 XmNforeground, XtRString, "black",
771 strlen("black")+1,
772 XtVaTypedArg,
773 XmNbackground, XtRString, "LightGoldenrod",
774 strlen("LightGoldenrod")+1,
775 NULL);
776 XmStringFree (text);
777
778 /************************************************************/
779 /* Popup help label */
780 /************************************************************/
781 XtPopup (help_popup, XtGrabNone);
782 }
783