]> git.saurik.com Git - wxWidgets.git/blame - src/motif/toolbar.cpp
ADDED wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
[wxWidgets.git] / src / motif / toolbar.cpp
CommitLineData
4bb6408c
JS
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"
1a3ac83f
JS
17#include "wx/app.h"
18#include "wx/timer.h"
0d57be45
JS
19#include "wx/motif/toolbar.h"
20
21#include <Xm/Xm.h>
22#include <Xm/PushBG.h>
23#include <Xm/PushB.h>
1a3ac83f 24#include <Xm/Label.h>
0d57be45
JS
25#include <Xm/ToggleB.h>
26#include <Xm/ToggleBG.h>
27#include <Xm/Form.h>
28
29#include "wx/motif/private.h"
4bb6408c
JS
30
31#if !USE_SHARED_LIBRARY
32IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
33
34BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
35END_EVENT_TABLE()
36#endif
37
1a3ac83f
JS
38static void wxToolButtonCallback (Widget w, XtPointer clientData,
39 XtPointer ptr);
40static void wxToolButtonPopupCallback (Widget w, XtPointer client_data,
41 XEvent *event, Boolean *continue_to_dispatch);
42
1a3ac83f
JS
43class wxToolBarTimer: public wxTimer
44{
45public:
46 wxToolBarTimer() { }
47 virtual void Notify();
48
49 static Widget help_popup;
50 static Widget buttonWidget;
51 static wxString helpString;
52};
53
54static wxToolBarTimer* wxTheToolBarTimer = (wxToolBarTimer*) NULL;
55
56Widget wxToolBarTimer::help_popup = (Widget) 0;
57Widget wxToolBarTimer::buttonWidget = (Widget) 0;
58wxString wxToolBarTimer::helpString = "";
59
0d57be45
JS
60wxToolBar::wxToolBar():
61 m_widgets(wxKEY_INTEGER)
4bb6408c
JS
62{
63 m_maxWidth = -1;
64 m_maxHeight = -1;
65 m_defaultWidth = 24;
66 m_defaultHeight = 22;
4bb6408c
JS
67}
68
69bool 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);
0d57be45
JS
78 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE);
79 m_foregroundColour = parent->GetForegroundColour();
4bb6408c
JS
80 m_windowStyle = style;
81
82 SetParent(parent);
83
84 if (parent) parent->AddChild(this);
85
0d57be45
JS
86 Widget parentWidget = (Widget) parent->GetClientWidget();
87
88 Widget toolbar = XtVaCreateManagedWidget("toolbar",
7fe7d506
JS
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,
0d57be45
JS
97 XmNtraversalOn, False,
98 XmNhorizontalSpacing, 0,
99 XmNverticalSpacing, 0,
1a3ac83f
JS
100 XmNleftOffset, 0,
101 XmNrightOffset, 0,
102 XmNmarginWidth, 0,
103 XmNmarginHeight, 0,
0d57be45 104 NULL);
7fe7d506 105*/
0d57be45
JS
106
107 m_mainWidget = (WXWidget) toolbar;
108
4b5f3fe6
JS
109 m_windowFont = parent->GetFont();
110 ChangeFont(FALSE);
111
0d57be45
JS
112 SetCanAddEventHandler(TRUE);
113 AttachWidget (parent, m_mainWidget, (WXWidget) NULL, pos.x, pos.y, size.x, size.y);
114
0d57be45 115 ChangeBackgroundColour();
4bb6408c 116
0d57be45 117 return TRUE;
4bb6408c
JS
118}
119
120wxToolBar::~wxToolBar()
121{
1a3ac83f
JS
122 delete wxTheToolBarTimer;
123 wxTheToolBarTimer = NULL;
124 ClearTools();
125 DestroyPixmaps();
4bb6408c
JS
126}
127
7fe7d506
JS
128bool 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
4bb6408c
JS
322bool wxToolBar::CreateTools()
323{
324 if (m_tools.Number() == 0)
325 return FALSE;
326
1a3ac83f
JS
327 // Separator spacing
328 const int separatorSize = GetToolSeparation(); // 8;
329
330 int currentSpacing = 0;
331
0d57be45
JS
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();
1a3ac83f
JS
338
339 if (tool->m_toolStyle == wxTOOL_STYLE_SEPARATOR)
340 currentSpacing = separatorSize;
341 else if (tool->m_bitmap1.Ok())
0d57be45
JS
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,
1a3ac83f 351 XmNleftOffset, currentSpacing,
0d57be45
JS
352 XmNtopAttachment, XmATTACH_FORM,
353 // XmNpushButtonEnabled, True,
354 XmNmultiClick, XmMULTICLICK_KEEP,
355 XmNlabelType, XmPIXMAP,
356 NULL);
1a3ac83f
JS
357 XtAddCallback ((Widget) button, XmNvalueChangedCallback, (XtCallbackProc) wxToolButtonCallback,
358 (XtPointer) this);
0d57be45
JS
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,
1a3ac83f 366 XmNleftOffset, currentSpacing,
0d57be45
JS
367 XmNtopAttachment, XmATTACH_FORM,
368 XmNpushButtonEnabled, True,
369 XmNmultiClick, XmMULTICLICK_KEEP,
370 XmNlabelType, XmPIXMAP,
371 NULL);
1a3ac83f
JS
372 XtAddCallback (button,
373 XmNactivateCallback, (XtCallbackProc) wxToolButtonCallback,
374 (XtPointer) this);
375 }
0d57be45
JS
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.
1a3ac83f
JS
381 wxBitmap originalBitmap = tool->m_bitmap1;
382
0d57be45
JS
383 if (tool->m_bitmap1.GetMask())
384 {
0d57be45
JS
385 int backgroundPixel;
386 XtVaGetValues(button, XmNbackground, &backgroundPixel,
387 NULL);
388
389
390 wxColour col;
391 col.SetPixel(backgroundPixel);
392
1a3ac83f 393 wxBitmap newBitmap = wxCreateMaskedBitmap(tool->m_bitmap1, col);
0d57be45
JS
394
395 tool->m_bitmap1 = newBitmap;
396 }
0d57be45 397
1a3ac83f
JS
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);
0d57be45 407
1a3ac83f
JS
408 wxColour col;
409 col.SetPixel(backgroundPixel);
0d57be45 410
1a3ac83f
JS
411 if (tool->m_bitmap2.Ok() && tool->m_bitmap2.GetMask())
412 {
413 // Use what's there
414 wxBitmap newBitmap = wxCreateMaskedBitmap(tool->m_bitmap2, col);
0d57be45
JS
415 tool->m_bitmap2 = newBitmap;
416 }
1a3ac83f
JS
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
0d57be45
JS
429 Pixmap pixmap = (Pixmap) tool->m_bitmap1.GetPixmap();
430 Pixmap insensPixmap = (Pixmap) tool->m_bitmap1.GetInsensPixmap();
431
432 if (tool->m_isToggle)
433 {
1a3ac83f 434 // Toggle button
0d57be45
JS
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);
1a3ac83f
JS
448 insensPixmap2 = XCreateInsensitivePixmap((Display*) wxGetDisplay(), pixmap2);
449 m_pixmaps.Append((wxObject*) insensPixmap2); // Store for later deletion
0d57be45
JS
450 }
451 XtVaSetValues (button,
1a3ac83f
JS
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 }
0d57be45
JS
466 else
467 {
1a3ac83f
JS
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
0d57be45
JS
482 XtVaSetValues(button,
483 XmNlabelPixmap, pixmap,
1a3ac83f
JS
484 XmNlabelInsensitivePixmap, insensPixmap,
485 XmNarmPixmap, pixmap2,
486 NULL);
0d57be45
JS
487 }
488
1a3ac83f
JS
489 XtAddEventHandler (button, EnterWindowMask | LeaveWindowMask,
490 False, wxToolButtonPopupCallback, (XtPointer) this);
0d57be45
JS
491 m_widgets.Append(tool->m_index, (wxObject*) button);
492
493 prevButton = button;
1a3ac83f 494 currentSpacing = 0;
0d57be45
JS
495 }
496 node = node->Next();
497 }
498
499 return TRUE;
4bb6408c 500}
7fe7d506 501#endif
4bb6408c
JS
502
503void wxToolBar::SetToolBitmapSize(const wxSize& size)
504{
4b5f3fe6 505 // TODO not necessary?
4bb6408c 506 m_defaultWidth = size.x; m_defaultHeight = size.y;
4bb6408c
JS
507}
508
509wxSize wxToolBar::GetMaxSize() const
510{
4b5f3fe6
JS
511 int w, h;
512 GetSize(& w, & h);
513
514 return wxSize(w, h);
4bb6408c
JS
515}
516
517// The button size is bigger than the bitmap size
518wxSize wxToolBar::GetToolSize() const
519{
4b5f3fe6 520 // TODO not necessary?
4bb6408c
JS
521 return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
522}
523
524void 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;
1a3ac83f
JS
531
532 WXWidget widget = FindWidgetForIndex(tool->m_index);
533 if (widget == (WXWidget) 0)
534 return;
535
536 XtSetSensitive((Widget) widget, (Boolean) enable);
4bb6408c
JS
537 }
538}
539
540void 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;
1a3ac83f
JS
549
550 WXWidget widget = FindWidgetForIndex(tool->m_index);
551 if (widget == (WXWidget) 0)
552 return;
553
554 XmToggleButtonSetState((Widget) widget, (Boolean) toggle, False);
4bb6408c
JS
555 }
556 }
557}
558
559void wxToolBar::ClearTools()
560{
0d57be45
JS
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();
1a3ac83f 569 DestroyPixmaps();
0d57be45 570
4bb6408c
JS
571 wxToolBarBase::ClearTools();
572}
573
1a3ac83f
JS
574void 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
4bb6408c
JS
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
590wxToolBarTool *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{
c0ed460c 593 wxToolBarTool *tool = new wxToolBarTool(index, bitmap, wxNullBitmap, toggle, xPos, yPos, helpString1, helpString2);
4bb6408c
JS
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
1a3ac83f
JS
612int 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)
4fabb575 619 return (int) node->GetKeyInteger();
1a3ac83f
JS
620 node = node->Next();
621 }
622 return -1;
623}
624
625WXWidget 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
7fe7d506
JS
634WXWidget wxToolBar::GetTopWidget() const
635{
636 return m_mainWidget;
637}
638
639WXWidget wxToolBar::GetClientWidget() const
640{
641 return m_mainWidget;
642}
643
644WXWidget wxToolBar::GetMainWidget() const
645{
646 return m_mainWidget;
647}
648
649
1a3ac83f
JS
650void 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
1a3ac83f
JS
670
671static 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
730void 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