]> git.saurik.com Git - wxWidgets.git/blame - src/motif/toolbar.cpp
1. more keyboard navigation fixes - seems to work now
[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"
1ccbb61a 19#include "wx/toolbar.h"
0d57be45
JS
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
94b49b93
JS
185 DoChangeBackgroundColour((WXWidget) button, m_backgroundColour, TRUE);
186
7fe7d506
JS
187 // For each button, if there is a mask, we must create
188 // a new wxBitmap that has the correct background colour
189 // for the button. Otherwise the background will just be
190 // e.g. black if a transparent XPM has been loaded.
191 wxBitmap originalBitmap = tool->m_bitmap1;
192
193 if (tool->m_bitmap1.GetMask())
194 {
195 int backgroundPixel;
196 XtVaGetValues(button, XmNbackground, &backgroundPixel,
197 NULL);
198
199
200 wxColour col;
201 col.SetPixel(backgroundPixel);
202
203 wxBitmap newBitmap = wxCreateMaskedBitmap(tool->m_bitmap1, col);
204
205 tool->m_bitmap1 = newBitmap;
206 }
207
208 // Create a selected/toggled bitmap. If there isn't a m_bitmap2,
209 // we need to create it (with a darker, selected background)
210 int backgroundPixel;
211 if (tool->m_isToggle)
212 XtVaGetValues(button, XmNselectColor, &backgroundPixel,
213 NULL);
214 else
215 XtVaGetValues(button, XmNarmColor, &backgroundPixel,
216 NULL);
217
218 wxColour col;
219 col.SetPixel(backgroundPixel);
220
221 if (tool->m_bitmap2.Ok() && tool->m_bitmap2.GetMask())
222 {
223 // Use what's there
224 wxBitmap newBitmap = wxCreateMaskedBitmap(tool->m_bitmap2, col);
225 tool->m_bitmap2 = newBitmap;
226 }
227 else
228 {
229 // Use unselected bitmap
230 if (originalBitmap.GetMask())
231 {
232 wxBitmap newBitmap = wxCreateMaskedBitmap(originalBitmap, col);
233 tool->m_bitmap2 = newBitmap;
234 }
235 else
236 tool->m_bitmap2 = tool->m_bitmap1;
237 }
238
239 Pixmap pixmap = (Pixmap) tool->m_bitmap1.GetPixmap();
240 Pixmap insensPixmap = (Pixmap) tool->m_bitmap1.GetInsensPixmap();
241
242 if (tool->m_isToggle)
243 {
244 // Toggle button
245 Pixmap pixmap2 = (Pixmap) 0;
246 Pixmap insensPixmap2 = (Pixmap) 0;
247
248 // If there's a bitmap for the toggled state, use it,
249 // otherwise generate one.
250 if (tool->m_bitmap2.Ok())
251 {
252 pixmap2 = (Pixmap) tool->m_bitmap2.GetPixmap();
253 insensPixmap2 = (Pixmap) tool->m_bitmap2.GetInsensPixmap();
254 }
255 else
256 {
257 pixmap2 = (Pixmap) tool->m_bitmap1.GetArmPixmap(button);
258 insensPixmap2 = XCreateInsensitivePixmap((Display*) wxGetDisplay(), pixmap2);
259 m_pixmaps.Append((wxObject*) insensPixmap2); // Store for later deletion
260 }
261 XtVaSetValues (button,
262 XmNindicatorOn, False,
263 XmNshadowThickness, 2,
264 // XmNborderWidth, 0,
265 // XmNspacing, 0,
266 XmNmarginWidth, 0,
267 XmNmarginHeight, 0,
268 XmNfillOnSelect, True,
269 XmNlabelPixmap, pixmap,
270 XmNselectPixmap, pixmap2,
271 XmNlabelInsensitivePixmap, insensPixmap,
272 XmNselectInsensitivePixmap, insensPixmap2,
273 XmNlabelType, XmPIXMAP,
274 NULL);
275 }
276 else
277 {
278 Pixmap pixmap2 = (Pixmap) 0;
279
280 // If there's a bitmap for the armed state, use it,
281 // otherwise generate one.
282 if (tool->m_bitmap2.Ok())
283 {
284 pixmap2 = (Pixmap) tool->m_bitmap2.GetPixmap();
285 }
286 else
287 {
288 pixmap2 = (Pixmap) tool->m_bitmap1.GetArmPixmap(button);
289
290 }
291 // Normal button
292 XtVaSetValues(button,
293 XmNlabelPixmap, pixmap,
294 XmNlabelInsensitivePixmap, insensPixmap,
295 XmNarmPixmap, pixmap2,
296 NULL);
297 }
298 XtManageChild(button);
299
300 Dimension width, height;
301 XtVaGetValues(button, XmNwidth, & width, XmNheight, & height,
302 NULL);
303 currentX += width + marginX;
304 buttonHeight = wxMax(buttonHeight, height);
305
306 XtAddEventHandler (button, EnterWindowMask | LeaveWindowMask,
307 False, wxToolButtonPopupCallback, (XtPointer) this);
308 m_widgets.Append(tool->m_index, (wxObject*) button);
309
310 prevButton = button;
311 currentSpacing = 0;
312 }
313 node = node->Next();
314 }
315
316 SetSize(-1, -1, currentX, buttonHeight + 2*marginY);
317
318 return TRUE;
319}
320
321// Old version, assuming we use a form. Now we use
322// a bulletin board, so we can create controls on the toolbar.
323#if 0
4bb6408c
JS
324bool wxToolBar::CreateTools()
325{
326 if (m_tools.Number() == 0)
327 return FALSE;
328
1a3ac83f
JS
329 // Separator spacing
330 const int separatorSize = GetToolSeparation(); // 8;
331
332 int currentSpacing = 0;
333
0d57be45
JS
334 m_widgets.Clear();
335 Widget prevButton = (Widget) 0;
336 wxNode* node = m_tools.First();
337 while (node)
338 {
339 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
1a3ac83f
JS
340
341 if (tool->m_toolStyle == wxTOOL_STYLE_SEPARATOR)
342 currentSpacing = separatorSize;
343 else if (tool->m_bitmap1.Ok())
0d57be45
JS
344 {
345 Widget button = (Widget) 0;
346
347 if (tool->m_isToggle)
348 {
349 button = XtVaCreateManagedWidget("toggleButton",
350 xmToggleButtonWidgetClass, (Widget) m_mainWidget,
351 XmNleftAttachment, (prevButton == (Widget) 0) ? XmATTACH_FORM : XmATTACH_WIDGET,
352 XmNleftWidget, (prevButton == (Widget) 0) ? NULL : prevButton,
1a3ac83f 353 XmNleftOffset, currentSpacing,
0d57be45
JS
354 XmNtopAttachment, XmATTACH_FORM,
355 // XmNpushButtonEnabled, True,
356 XmNmultiClick, XmMULTICLICK_KEEP,
357 XmNlabelType, XmPIXMAP,
358 NULL);
1a3ac83f
JS
359 XtAddCallback ((Widget) button, XmNvalueChangedCallback, (XtCallbackProc) wxToolButtonCallback,
360 (XtPointer) this);
0d57be45
JS
361 }
362 else
363 {
364 button = XtVaCreateManagedWidget("button",
365 xmPushButtonWidgetClass, (Widget) m_mainWidget,
366 XmNleftAttachment, (prevButton == (Widget) 0) ? XmATTACH_FORM : XmATTACH_WIDGET,
367 XmNleftWidget, (prevButton == (Widget) 0) ? NULL : prevButton,
1a3ac83f 368 XmNleftOffset, currentSpacing,
0d57be45
JS
369 XmNtopAttachment, XmATTACH_FORM,
370 XmNpushButtonEnabled, True,
371 XmNmultiClick, XmMULTICLICK_KEEP,
372 XmNlabelType, XmPIXMAP,
373 NULL);
1a3ac83f
JS
374 XtAddCallback (button,
375 XmNactivateCallback, (XtCallbackProc) wxToolButtonCallback,
376 (XtPointer) this);
377 }
0d57be45
JS
378
379 // For each button, if there is a mask, we must create
380 // a new wxBitmap that has the correct background colour
381 // for the button. Otherwise the background will just be
382 // e.g. black if a transparent XPM has been loaded.
1a3ac83f
JS
383 wxBitmap originalBitmap = tool->m_bitmap1;
384
0d57be45
JS
385 if (tool->m_bitmap1.GetMask())
386 {
0d57be45
JS
387 int backgroundPixel;
388 XtVaGetValues(button, XmNbackground, &backgroundPixel,
389 NULL);
390
391
392 wxColour col;
393 col.SetPixel(backgroundPixel);
394
1a3ac83f 395 wxBitmap newBitmap = wxCreateMaskedBitmap(tool->m_bitmap1, col);
0d57be45
JS
396
397 tool->m_bitmap1 = newBitmap;
398 }
0d57be45 399
1a3ac83f
JS
400 // Create a selected/toggled bitmap. If there isn't a m_bitmap2,
401 // we need to create it (with a darker, selected background)
402 int backgroundPixel;
403 if (tool->m_isToggle)
404 XtVaGetValues(button, XmNselectColor, &backgroundPixel,
405 NULL);
406 else
407 XtVaGetValues(button, XmNarmColor, &backgroundPixel,
408 NULL);
0d57be45 409
1a3ac83f
JS
410 wxColour col;
411 col.SetPixel(backgroundPixel);
0d57be45 412
1a3ac83f
JS
413 if (tool->m_bitmap2.Ok() && tool->m_bitmap2.GetMask())
414 {
415 // Use what's there
416 wxBitmap newBitmap = wxCreateMaskedBitmap(tool->m_bitmap2, col);
0d57be45
JS
417 tool->m_bitmap2 = newBitmap;
418 }
1a3ac83f
JS
419 else
420 {
421 // Use unselected bitmap
422 if (originalBitmap.GetMask())
423 {
424 wxBitmap newBitmap = wxCreateMaskedBitmap(originalBitmap, col);
425 tool->m_bitmap2 = newBitmap;
426 }
427 else
428 tool->m_bitmap2 = tool->m_bitmap1;
429 }
430
0d57be45
JS
431 Pixmap pixmap = (Pixmap) tool->m_bitmap1.GetPixmap();
432 Pixmap insensPixmap = (Pixmap) tool->m_bitmap1.GetInsensPixmap();
433
434 if (tool->m_isToggle)
435 {
1a3ac83f 436 // Toggle button
0d57be45
JS
437 Pixmap pixmap2 = (Pixmap) 0;
438 Pixmap insensPixmap2 = (Pixmap) 0;
439
440 // If there's a bitmap for the toggled state, use it,
441 // otherwise generate one.
442 if (tool->m_bitmap2.Ok())
443 {
444 pixmap2 = (Pixmap) tool->m_bitmap2.GetPixmap();
445 insensPixmap2 = (Pixmap) tool->m_bitmap2.GetInsensPixmap();
446 }
447 else
448 {
449 pixmap2 = (Pixmap) tool->m_bitmap1.GetArmPixmap(button);
1a3ac83f
JS
450 insensPixmap2 = XCreateInsensitivePixmap((Display*) wxGetDisplay(), pixmap2);
451 m_pixmaps.Append((wxObject*) insensPixmap2); // Store for later deletion
0d57be45
JS
452 }
453 XtVaSetValues (button,
1a3ac83f
JS
454 XmNindicatorOn, False,
455 XmNshadowThickness, 2,
456 // XmNborderWidth, 0,
457 // XmNspacing, 0,
458 XmNmarginWidth, 0,
459 XmNmarginHeight, 0,
460 XmNfillOnSelect, True,
461 XmNlabelPixmap, pixmap,
462 XmNselectPixmap, pixmap2,
463 XmNlabelInsensitivePixmap, insensPixmap,
464 XmNselectInsensitivePixmap, insensPixmap2,
465 XmNlabelType, XmPIXMAP,
466 NULL);
467 }
0d57be45
JS
468 else
469 {
1a3ac83f
JS
470 Pixmap pixmap2 = (Pixmap) 0;
471
472 // If there's a bitmap for the armed state, use it,
473 // otherwise generate one.
474 if (tool->m_bitmap2.Ok())
475 {
476 pixmap2 = (Pixmap) tool->m_bitmap2.GetPixmap();
477 }
478 else
479 {
480 pixmap2 = (Pixmap) tool->m_bitmap1.GetArmPixmap(button);
481
482 }
483 // Normal button
0d57be45
JS
484 XtVaSetValues(button,
485 XmNlabelPixmap, pixmap,
1a3ac83f
JS
486 XmNlabelInsensitivePixmap, insensPixmap,
487 XmNarmPixmap, pixmap2,
488 NULL);
0d57be45
JS
489 }
490
1a3ac83f
JS
491 XtAddEventHandler (button, EnterWindowMask | LeaveWindowMask,
492 False, wxToolButtonPopupCallback, (XtPointer) this);
0d57be45
JS
493 m_widgets.Append(tool->m_index, (wxObject*) button);
494
495 prevButton = button;
1a3ac83f 496 currentSpacing = 0;
0d57be45
JS
497 }
498 node = node->Next();
499 }
500
501 return TRUE;
4bb6408c 502}
7fe7d506 503#endif
4bb6408c
JS
504
505void wxToolBar::SetToolBitmapSize(const wxSize& size)
506{
4b5f3fe6 507 // TODO not necessary?
4bb6408c 508 m_defaultWidth = size.x; m_defaultHeight = size.y;
4bb6408c
JS
509}
510
511wxSize wxToolBar::GetMaxSize() const
512{
4b5f3fe6
JS
513 int w, h;
514 GetSize(& w, & h);
515
516 return wxSize(w, h);
4bb6408c
JS
517}
518
519// The button size is bigger than the bitmap size
520wxSize wxToolBar::GetToolSize() const
521{
4b5f3fe6 522 // TODO not necessary?
4bb6408c
JS
523 return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
524}
525
526void wxToolBar::EnableTool(int toolIndex, bool enable)
527{
528 wxNode *node = m_tools.Find((long)toolIndex);
529 if (node)
530 {
531 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
532 tool->m_enabled = enable;
1a3ac83f
JS
533
534 WXWidget widget = FindWidgetForIndex(tool->m_index);
535 if (widget == (WXWidget) 0)
536 return;
537
538 XtSetSensitive((Widget) widget, (Boolean) enable);
4bb6408c
JS
539 }
540}
541
542void wxToolBar::ToggleTool(int toolIndex, bool toggle)
543{
544 wxNode *node = m_tools.Find((long)toolIndex);
545 if (node)
546 {
547 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
548 if (tool->m_isToggle)
549 {
550 tool->m_toggleState = toggle;
1a3ac83f
JS
551
552 WXWidget widget = FindWidgetForIndex(tool->m_index);
553 if (widget == (WXWidget) 0)
554 return;
555
556 XmToggleButtonSetState((Widget) widget, (Boolean) toggle, False);
4bb6408c
JS
557 }
558 }
559}
560
561void wxToolBar::ClearTools()
562{
0d57be45
JS
563 wxNode* node = m_widgets.First();
564 while (node)
565 {
566 Widget button = (Widget) node->Data();
567 XtDestroyWidget(button);
568 node = node->Next();
569 }
570 m_widgets.Clear();
1a3ac83f 571 DestroyPixmaps();
0d57be45 572
4bb6408c
JS
573 wxToolBarBase::ClearTools();
574}
575
1a3ac83f
JS
576void wxToolBar::DestroyPixmaps()
577{
578 wxNode* node = m_pixmaps.First();
579 while (node)
580 {
581 Pixmap pixmap = (Pixmap) node->Data();
582 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) GetXDisplay()), pixmap);
583 node = node->Next();
584 }
585 m_pixmaps.Clear();
586}
587
4bb6408c
JS
588// If pushedBitmap is NULL, a reversed version of bitmap is
589// created and used as the pushed/toggled image.
590// If toggle is TRUE, the button toggles between the two states.
591
592wxToolBarTool *wxToolBar::AddTool(int index, const wxBitmap& bitmap, const wxBitmap& pushedBitmap,
593 bool toggle, long xPos, long yPos, wxObject *clientData, const wxString& helpString1, const wxString& helpString2)
594{
c0ed460c 595 wxToolBarTool *tool = new wxToolBarTool(index, bitmap, wxNullBitmap, toggle, xPos, yPos, helpString1, helpString2);
4bb6408c
JS
596 tool->m_clientData = clientData;
597
598 if (xPos > -1)
599 tool->m_x = xPos;
600 else
601 tool->m_x = m_xMargin;
602
603 if (yPos > -1)
604 tool->m_y = yPos;
605 else
606 tool->m_y = m_yMargin;
607
1ccbb61a
VZ
608 wxSize& size = GetToolSize();
609 tool->SetSize(size.x, size.y);
4bb6408c
JS
610
611 m_tools.Append((long)index, tool);
612 return tool;
613}
614
1a3ac83f
JS
615int wxToolBar::FindIndexForWidget(WXWidget w)
616{
617 wxNode* node = m_widgets.First();
618 while (node)
619 {
620 WXWidget widget = (WXWidget) node->Data();
621 if (widget == w)
4fabb575 622 return (int) node->GetKeyInteger();
1a3ac83f
JS
623 node = node->Next();
624 }
625 return -1;
626}
627
628WXWidget wxToolBar::FindWidgetForIndex(int index)
629{
630 wxNode* node = m_widgets.Find((long) index);
631 if (!node)
632 return (WXWidget) 0;
633 else
634 return (WXWidget) node->Data();
635}
636
7fe7d506
JS
637WXWidget wxToolBar::GetTopWidget() const
638{
639 return m_mainWidget;
640}
641
642WXWidget wxToolBar::GetClientWidget() const
643{
644 return m_mainWidget;
645}
646
647WXWidget wxToolBar::GetMainWidget() const
648{
649 return m_mainWidget;
650}
651
652
1a3ac83f
JS
653void wxToolButtonCallback (Widget w, XtPointer clientData,
654 XtPointer ptr)
655{
656 wxToolBar *toolBar = (wxToolBar *) clientData;
657 int index = toolBar->FindIndexForWidget((WXWidget) w);
658
659 if (index != -1)
660 {
661 wxNode *node = toolBar->GetTools().Find((long)index);
662 if (!node)
663 return;
664 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
665 if (tool->m_isToggle)
666 tool->m_toggleState = toolBar->GetToolState(index);
667
668 (void) toolBar->OnLeftClick(index, tool->m_toggleState);
669 }
670
671}
672
1a3ac83f
JS
673
674static void wxToolButtonPopupCallback (Widget w, XtPointer client_data,
675 XEvent *event, Boolean *continue_to_dispatch)
676{
677 // TODO: retrieve delay before popping up tooltip from wxSystemSettings.
678 int delayMilli = 800;
679 wxToolBar* toolBar = (wxToolBar*) client_data;
680
681 int index = toolBar->FindIndexForWidget((WXWidget) w);
682
683 if (index != -1)
684 {
685 wxNode *node = toolBar->GetTools().Find((long)index);
686 if (!node)
687 return;
688 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
689 wxString str(toolBar->GetToolShortHelp(index));
690 if (str.IsNull() || str == "")
691 return;
692
693 if (!wxTheToolBarTimer)
694 wxTheToolBarTimer = new wxToolBarTimer;
695
696 wxToolBarTimer::buttonWidget = w;
697 wxToolBarTimer::helpString = str;
698
699
700 /************************************************************/
701 /* Popup help label */
702 /************************************************************/
703 if (event->type == EnterNotify)
704 {
705 if (wxToolBarTimer::help_popup != (Widget) 0)
706 {
707 XtDestroyWidget (wxToolBarTimer::help_popup);
708 XtPopdown (wxToolBarTimer::help_popup);
709 }
710 wxToolBarTimer::help_popup = (Widget) 0;
711
712 // One shot
713 wxTheToolBarTimer->Start(delayMilli, TRUE);
714
715 }
716 /************************************************************/
717 /* Popdown help label */
718 /************************************************************/
719 else if (event->type == LeaveNotify)
720 {
721 if (wxTheToolBarTimer)
722 wxTheToolBarTimer->Stop();
723 if (wxToolBarTimer::help_popup != (Widget) 0)
724 {
725 XtDestroyWidget (wxToolBarTimer::help_popup);
726 XtPopdown (wxToolBarTimer::help_popup);
727 }
728 wxToolBarTimer::help_popup = (Widget) 0;
729 }
730 }
731}
732
733void wxToolBarTimer::Notify()
734{
735 Position x, y;
736
737 /************************************************************/
738 /* Create shell without window decorations */
739 /************************************************************/
740 help_popup = XtVaCreatePopupShell ("shell",
741 overrideShellWidgetClass, (Widget) wxTheApp->GetTopLevelWidget(),
742 NULL);
743
744 /************************************************************/
745 /* Get absolute position on display of toolbar button */
746 /************************************************************/
747 XtTranslateCoords (buttonWidget,
748 (Position) 0,
749 (Position) 0,
750 &x, &y);
751
752 // Move the tooltip more or less above the button
753 int yOffset = 20; // TODO: What should be really?
754 y -= yOffset;
755 if (y < yOffset) y = 0;
756
757 /************************************************************/
758 /* Set the position of the help popup */
759 /************************************************************/
760 XtVaSetValues (help_popup,
761 XmNx, (Position) x,
762 XmNy, (Position) y,
763 NULL);
764
765 /************************************************************/
766 /* Create help label */
767 /************************************************************/
768 XmString text = XmStringCreateSimple ((char*) (const char*) helpString);
769 XtVaCreateManagedWidget ("help_label",
770 xmLabelWidgetClass, help_popup,
771 XmNlabelString, text,
772 XtVaTypedArg,
773 XmNforeground, XtRString, "black",
774 strlen("black")+1,
775 XtVaTypedArg,
776 XmNbackground, XtRString, "LightGoldenrod",
777 strlen("LightGoldenrod")+1,
778 NULL);
779 XmStringFree (text);
780
781 /************************************************************/
782 /* Popup help label */
783 /************************************************************/
784 XtPopup (help_popup, XtGrabNone);
785}
786