]> git.saurik.com Git - wxWidgets.git/blame - src/motif/toolbar.cpp
Font work.
[wxWidgets.git] / src / motif / toolbar.cpp
CommitLineData
4bb6408c 1/////////////////////////////////////////////////////////////////////////////
8a0681f9 2// Name: motif/toolbar.cpp
4bb6408c
JS
3// Purpose: wxToolBar
4// Author: Julian Smart
8a0681f9 5// Modified by: 13.12.99 by VZ during toolbar classes reorganization
4bb6408c
JS
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
8a0681f9 9// Licence: wxWindows licence
4bb6408c
JS
10/////////////////////////////////////////////////////////////////////////////
11
8a0681f9
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
4bb6408c 20#ifdef __GNUG__
8a0681f9 21 #pragma implementation "toolbar.h"
4bb6408c
JS
22#endif
23
4dff3400
JJ
24#ifdef __VMS
25#define XtDisplay XTDISPLAY
26#endif
27
4bb6408c 28#include "wx/wx.h"
1a3ac83f
JS
29#include "wx/app.h"
30#include "wx/timer.h"
1ccbb61a 31#include "wx/toolbar.h"
46675b46 32#include "wx/frame.h"
0d57be45 33
338dd992
JJ
34#ifdef __VMS__
35#pragma message disable nosimpint
36#endif
0d57be45
JS
37#include <Xm/Xm.h>
38#include <Xm/PushBG.h>
39#include <Xm/PushB.h>
1a3ac83f 40#include <Xm/Label.h>
0d57be45
JS
41#include <Xm/ToggleB.h>
42#include <Xm/ToggleBG.h>
43#include <Xm/Form.h>
338dd992
JJ
44#ifdef __VMS__
45#pragma message enable nosimpint
46#endif
0d57be45
JS
47
48#include "wx/motif/private.h"
4bb6408c 49
8a0681f9
VZ
50// ----------------------------------------------------------------------------
51// wxWin macros
52// ----------------------------------------------------------------------------
53
54#if !USE_SHARED_LIBRARY
12ed316d 55IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
8a0681f9 56#endif
4bb6408c 57
8a0681f9
VZ
58// ----------------------------------------------------------------------------
59// private functions
60// ----------------------------------------------------------------------------
4bb6408c 61
1a3ac83f 62static void wxToolButtonCallback (Widget w, XtPointer clientData,
bf6c2b35 63 XtPointer ptr);
1a3ac83f
JS
64static void wxToolButtonPopupCallback (Widget w, XtPointer client_data,
65 XEvent *event, Boolean *continue_to_dispatch);
66
8a0681f9
VZ
67// ----------------------------------------------------------------------------
68// private classes
69// ----------------------------------------------------------------------------
70
71class wxToolBarTimer : public wxTimer
1a3ac83f
JS
72{
73public:
8a0681f9 74 virtual void Notify();
1a3ac83f 75
8a0681f9
VZ
76 static Widget help_popup;
77 static Widget buttonWidget;
78 static wxString helpString;
1a3ac83f
JS
79};
80
8a0681f9
VZ
81class wxToolBarTool : public wxToolBarToolBase
82{
83public:
84 wxToolBarTool(wxToolBar *tbar,
85 int id,
fcb35b5f
VZ
86 const wxString& label,
87 const wxBitmap& bmpNormal,
88 const wxBitmap& bmpToggled,
89 wxItemKind kind,
8a0681f9 90 wxObject *clientData,
fcb35b5f
VZ
91 const wxString& shortHelp,
92 const wxString& longHelp)
93 : wxToolBarToolBase(tbar, id, label, bmpNormal, bmpToggled, kind,
94 clientData, shortHelp, longHelp)
8a0681f9
VZ
95 {
96 Init();
97 }
98
99 wxToolBarTool(wxToolBar *tbar, wxControl *control)
100 : wxToolBarToolBase(tbar, control)
101 {
102 Init();
103 }
104
105 virtual ~wxToolBarTool();
106
107 // accessors
108 void SetWidget(Widget widget) { m_widget = widget; }
109 Widget GetButtonWidget() const { return m_widget; }
110
111 void SetPixmap(Pixmap pixmap) { m_pixmap = pixmap; }
112 Pixmap GetPixmap() const { return m_pixmap; }
113
114protected:
115 void Init();
116
117 Widget m_widget;
118 Pixmap m_pixmap;
119};
120
121// ----------------------------------------------------------------------------
122// globals
123// ----------------------------------------------------------------------------
124
1a3ac83f
JS
125static wxToolBarTimer* wxTheToolBarTimer = (wxToolBarTimer*) NULL;
126
127Widget wxToolBarTimer::help_popup = (Widget) 0;
128Widget wxToolBarTimer::buttonWidget = (Widget) 0;
8a0681f9
VZ
129wxString wxToolBarTimer::helpString;
130
131// ============================================================================
132// implementation
133// ============================================================================
134
135// ----------------------------------------------------------------------------
136// wxToolBarTool
137// ----------------------------------------------------------------------------
138
982b2cfc 139wxToolBarToolBase *wxToolBar::CreateTool(int id,
fcb35b5f
VZ
140 const wxString& label,
141 const wxBitmap& bmpNormal,
142 const wxBitmap& bmpToggled,
143 wxItemKind kind,
982b2cfc 144 wxObject *clientData,
fcb35b5f
VZ
145 const wxString& shortHelp,
146 const wxString& longHelp)
8a0681f9 147{
fcb35b5f
VZ
148 return new wxToolBarTool(this, id, label, bmpNormal, bmpToggled, kind,
149 clientData, shortHelp, longHelp);
8a0681f9 150}
1a3ac83f 151
fcb35b5f 152
982b2cfc 153wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
4bb6408c 154{
982b2cfc 155 return new wxToolBarTool(this, control);
4bb6408c
JS
156}
157
8a0681f9
VZ
158void wxToolBarTool::Init()
159{
160 m_widget = (Widget)0;
161 m_pixmap = (Pixmap)0;
162}
163
164wxToolBarTool::~wxToolBarTool()
165{
982b2cfc
VZ
166 if ( m_widget )
167 XtDestroyWidget(m_widget);
2b5f62a0
VZ
168 // note: do not delete m_pixmap here because it will be deleted
169 // by the base class when the bitmap is destroyed.
8a0681f9
VZ
170}
171
172// ----------------------------------------------------------------------------
173// wxToolBar construction
174// ----------------------------------------------------------------------------
175
176void wxToolBar::Init()
4bb6408c
JS
177{
178 m_maxWidth = -1;
179 m_maxHeight = -1;
4bb6408c
JS
180 m_defaultWidth = 24;
181 m_defaultHeight = 22;
7b28757f
JS
182 m_toolPacking = 2;
183 m_toolSeparation = 8;
184 m_xMargin = 2;
185 m_yMargin = 2;
186 m_maxRows = 100;
187 m_maxCols = 100;
8a0681f9
VZ
188}
189
190bool wxToolBar::Create(wxWindow *parent,
191 wxWindowID id,
192 const wxPoint& pos,
193 const wxSize& size,
194 long style,
195 const wxString& name)
196{
46675b46
MB
197 if( !wxControl::CreateControl( parent, id, pos, size, style,
198 wxDefaultValidator, name ) )
199 return FALSE;
8a0681f9 200
a756f210 201 m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
4bb6408c 202
0d57be45
JS
203 Widget parentWidget = (Widget) parent->GetClientWidget();
204
205 Widget toolbar = XtVaCreateManagedWidget("toolbar",
7fe7d506
JS
206 xmBulletinBoardWidgetClass, (Widget) parentWidget,
207 XmNmarginWidth, 0,
208 XmNmarginHeight, 0,
209 XmNresizePolicy, XmRESIZE_NONE,
210 NULL);
211/*
212 Widget toolbar = XtVaCreateManagedWidget("toolbar",
213 xmFormWidgetClass, (Widget) m_clientWidget,
0d57be45
JS
214 XmNtraversalOn, False,
215 XmNhorizontalSpacing, 0,
216 XmNverticalSpacing, 0,
1a3ac83f
JS
217 XmNleftOffset, 0,
218 XmNrightOffset, 0,
219 XmNmarginWidth, 0,
220 XmNmarginHeight, 0,
0d57be45 221 NULL);
7fe7d506 222*/
0d57be45
JS
223
224 m_mainWidget = (WXWidget) toolbar;
225
4b5f3fe6
JS
226 ChangeFont(FALSE);
227
46675b46
MB
228 wxPoint rPos = pos;
229 wxSize rSize = size;
230
231 if( rPos.x == -1 ) rPos.x = 0;
232 if( rPos.y == -1 ) rPos.y = 0;
233 if( rSize.x == -1 && GetParent() )
234 rSize.x = GetParent()->GetSize().x;
235
0d57be45 236 SetCanAddEventHandler(TRUE);
46675b46
MB
237 AttachWidget (parent, m_mainWidget, (WXWidget) NULL,
238 rPos.x, rPos.y, rSize.x, rSize.y);
0d57be45 239
0d57be45 240 ChangeBackgroundColour();
bf6c2b35 241
0d57be45 242 return TRUE;
4bb6408c
JS
243}
244
245wxToolBar::~wxToolBar()
246{
1a3ac83f
JS
247 delete wxTheToolBarTimer;
248 wxTheToolBarTimer = NULL;
4bb6408c
JS
249}
250
8a0681f9 251bool wxToolBar::Realize()
7fe7d506 252{
8a0681f9
VZ
253 if ( m_tools.GetCount() == 0 )
254 {
255 // nothing to do
256 return TRUE;
257 }
7fe7d506 258
46675b46
MB
259 bool isVertical = GetWindowStyle() & wxTB_VERTICAL;
260
7fe7d506
JS
261 // Separator spacing
262 const int separatorSize = GetToolSeparation(); // 8;
263 wxSize margins = GetToolMargins();
f3979fcc 264 int packing = GetToolPacking();
7fe7d506
JS
265 int marginX = margins.x;
266 int marginY = margins.y;
267
268 int currentX = marginX;
269 int currentY = marginY;
270
46675b46 271 int buttonHeight = 0, buttonWidth = 0;
7fe7d506
JS
272
273 int currentSpacing = 0;
274
8a0681f9
VZ
275 Widget button;
276 Pixmap pixmap, insensPixmap;
277 wxBitmap bmp;
278
279 wxToolBarToolsList::Node *node = m_tools.GetFirst();
280 while ( node )
7fe7d506 281 {
8a0681f9 282 wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
7fe7d506 283
8a0681f9 284 switch ( tool->GetStyle() )
7fe7d506 285 {
8a0681f9 286 case wxTOOL_STYLE_CONTROL:
f3979fcc 287 {
66f55ec6
JS
288 wxControl* control = tool->GetControl();
289 wxSize sz = control->GetSize();
f3979fcc 290 wxPoint pos = control->GetPosition();
46675b46
MB
291 // Allow a control to specify a y[x]-offset by setting
292 // its initial position, but still don't allow it to
293 // position itself above the top[left] margin.
96c3039d 294 int controlY = (pos.y > 0) ? currentY + pos.y : currentY;
46675b46
MB
295 int controlX = (pos.x > 0) ? currentX + pos.x : currentX;
296 control->Move( isVertical ? controlX : currentX,
297 isVertical ? currentY : controlY );
298 if ( isVertical )
299 currentY += sz.y + packing;
300 else
301 currentX += sz.x + packing;
66f55ec6 302
8a0681f9 303 break;
f3979fcc 304 }
8a0681f9 305 case wxTOOL_STYLE_SEPARATOR:
46675b46
MB
306 // skip separators for vertical toolbars
307 if( isVertical ) break;
8a0681f9
VZ
308 currentX += separatorSize;
309 break;
7fe7d506 310
8a0681f9
VZ
311 case wxTOOL_STYLE_BUTTON:
312 button = (Widget) 0;
bf6c2b35 313
8a0681f9 314 if ( tool->CanBeToggled() )
7fe7d506 315 {
8a0681f9
VZ
316 button = XtVaCreateWidget("toggleButton",
317 xmToggleButtonWidgetClass, (Widget) m_mainWidget,
318 XmNx, currentX, XmNy, currentY,
e838cc14
VZ
319 XmNindicatorOn, False,
320 XmNshadowThickness, 2,
321 XmNborderWidth, 0,
322 XmNspacing, 0,
323 XmNmarginWidth, 0,
324 XmNmarginHeight, 0,
8a0681f9
VZ
325 XmNmultiClick, XmMULTICLICK_KEEP,
326 XmNlabelType, XmPIXMAP,
327 NULL);
328 XtAddCallback ((Widget) button, XmNvalueChangedCallback, (XtCallbackProc) wxToolButtonCallback,
329 (XtPointer) this);
330
331 XtVaSetValues ((Widget) button,
332 XmNselectColor, m_backgroundColour.AllocColour(XtDisplay((Widget) button)),
333 NULL);
bf6c2b35 334 }
7fe7d506 335 else
8a0681f9
VZ
336 {
337 button = XtVaCreateWidget("button",
338 xmPushButtonWidgetClass, (Widget) m_mainWidget,
339 XmNx, currentX, XmNy, currentY,
340 XmNpushButtonEnabled, True,
341 XmNmultiClick, XmMULTICLICK_KEEP,
342 XmNlabelType, XmPIXMAP,
343 NULL);
344 XtAddCallback (button,
345 XmNactivateCallback, (XtCallbackProc) wxToolButtonCallback,
346 (XtPointer) this);
347 }
7fe7d506 348
8a0681f9 349 DoChangeBackgroundColour((WXWidget) button, m_backgroundColour, TRUE);
7fe7d506 350
8a0681f9 351 tool->SetWidget(button);
7fe7d506 352
8a0681f9
VZ
353 // For each button, if there is a mask, we must create
354 // a new wxBitmap that has the correct background colour
355 // for the button. Otherwise the background will just be
356 // e.g. black if a transparent XPM has been loaded.
fcb35b5f 357 bmp = tool->GetNormalBitmap();
8a0681f9 358 if ( bmp.GetMask() )
7fe7d506 359 {
8a0681f9
VZ
360 int backgroundPixel;
361 XtVaGetValues(button, XmNbackground, &backgroundPixel,
362 NULL);
363
364 wxColour col;
365 col.SetPixel(backgroundPixel);
e838cc14 366 bmp = wxCreateMaskedBitmap(bmp, col);
8a0681f9 367
fcb35b5f 368 tool->SetNormalBitmap(bmp);
7fe7d506 369 }
8a0681f9
VZ
370
371 // Create a selected/toggled bitmap. If there isn't a 2nd
372 // bitmap, we need to create it (with a darker, selected
373 // background)
374 int backgroundPixel;
375 if ( tool->CanBeToggled() )
376 XtVaGetValues(button, XmNselectColor, &backgroundPixel,
377 NULL);
7fe7d506 378 else
8a0681f9
VZ
379 XtVaGetValues(button, XmNarmColor, &backgroundPixel,
380 NULL);
8a0681f9
VZ
381 wxColour col;
382 col.SetPixel(backgroundPixel);
383
fcb35b5f
VZ
384 // FIXME: we use disabled bitmap as the bitmap for the toggled
385 // state, we probably need a GetToggledBitmap() instead
386 wxBitmap bmpToggled = tool->GetDisabledBitmap();
387 if ( bmpToggled.Ok() && bmpToggled.GetMask())
7fe7d506 388 {
8a0681f9 389 // Use what's there
fcb35b5f
VZ
390 wxBitmap newBitmap = wxCreateMaskedBitmap(bmpToggled, col);
391 tool->SetDisabledBitmap(newBitmap);
7fe7d506 392 }
8a0681f9 393 else
7fe7d506 394 {
8a0681f9
VZ
395 // Use unselected bitmap
396 if ( bmp.GetMask() )
397 {
398 wxBitmap newBitmap = wxCreateMaskedBitmap(bmp, col);
fcb35b5f 399 tool->SetDisabledBitmap(newBitmap);
8a0681f9
VZ
400 }
401 else
fcb35b5f 402 tool->SetDisabledBitmap(bmp);
8a0681f9
VZ
403 }
404
fcb35b5f 405 // FIXME: and here we should use GetDisabledBitmap()...
8a0681f9
VZ
406 pixmap = (Pixmap) bmp.GetPixmap();
407 insensPixmap = (Pixmap) bmp.GetInsensPixmap();
408
409 if (tool->CanBeToggled())
410 {
411 // Toggle button
412 Pixmap pixmap2 = (Pixmap) 0;
413 Pixmap insensPixmap2 = (Pixmap) 0;
414
415 // If there's a bitmap for the toggled state, use it,
416 // otherwise generate one.
fcb35b5f
VZ
417 //
418 // FIXME: see above
419 if ( bmpToggled.Ok() )
8a0681f9 420 {
fcb35b5f
VZ
421 pixmap2 = (Pixmap) bmpToggled.GetPixmap();
422 insensPixmap2 = (Pixmap) bmpToggled.GetInsensPixmap();
8a0681f9
VZ
423 }
424 else
425 {
426 pixmap2 = (Pixmap) bmp.GetArmPixmap(button);
427 insensPixmap2 = XCreateInsensitivePixmap((Display*) wxGetDisplay(), pixmap2);
428 }
429
982b2cfc
VZ
430 tool->SetPixmap(pixmap2);
431
8a0681f9 432 XtVaSetValues (button,
8a0681f9
VZ
433 XmNfillOnSelect, True,
434 XmNlabelPixmap, pixmap,
435 XmNselectPixmap, pixmap2,
436 XmNlabelInsensitivePixmap, insensPixmap,
437 XmNselectInsensitivePixmap, insensPixmap2,
438 XmNlabelType, XmPIXMAP,
439 NULL);
7fe7d506
JS
440 }
441 else
442 {
8a0681f9
VZ
443 Pixmap pixmap2 = (Pixmap) 0;
444
445 // If there's a bitmap for the armed state, use it,
446 // otherwise generate one.
fcb35b5f 447 if ( bmpToggled.Ok() )
8a0681f9 448 {
fcb35b5f 449 pixmap2 = (Pixmap) bmpToggled.GetPixmap();
8a0681f9
VZ
450 }
451 else
452 {
453 pixmap2 = (Pixmap) bmp.GetArmPixmap(button);
454
455 }
982b2cfc
VZ
456
457 tool->SetPixmap(pixmap2);
458
8a0681f9
VZ
459 // Normal button
460 XtVaSetValues(button,
461 XmNlabelPixmap, pixmap,
462 XmNlabelInsensitivePixmap, insensPixmap,
463 XmNarmPixmap, pixmap2,
464 NULL);
465 }
982b2cfc 466
8a0681f9 467 XtManageChild(button);
7fe7d506 468
8a0681f9
VZ
469 {
470 Dimension width, height;
471 XtVaGetValues(button,
472 XmNwidth, &width,
473 XmNheight, & height,
474 NULL);
46675b46
MB
475 if ( isVertical )
476 currentY += height + packing;
477 else
478 currentX += width + packing;
8a0681f9 479 buttonHeight = wxMax(buttonHeight, height);
46675b46 480 buttonWidth = wxMax(buttonWidth, width);
7fe7d506 481 }
8a0681f9
VZ
482
483 XtAddEventHandler (button, EnterWindowMask | LeaveWindowMask,
484 False, wxToolButtonPopupCallback, (XtPointer) this);
485
486 currentSpacing = 0;
487 break;
7fe7d506 488 }
8a0681f9
VZ
489
490 node = node->GetNext();
7fe7d506
JS
491 }
492
46675b46
MB
493 SetSize( -1, -1,
494 isVertical ? buttonWidth + 2 * marginX : currentX,
495 isVertical ? currentY : buttonHeight + 2*marginY );
7fe7d506
JS
496
497 return TRUE;
498}
499
982b2cfc
VZ
500wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord WXUNUSED(x),
501 wxCoord WXUNUSED(y)) const
4bb6408c 502{
8a0681f9 503 wxFAIL_MSG( _T("TODO") );
4b5f3fe6 504
982b2cfc 505 return (wxToolBarToolBase *)NULL;
4bb6408c
JS
506}
507
982b2cfc 508bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool)
4bb6408c 509{
8a0681f9 510 tool->Attach(this);
4bb6408c 511
8a0681f9 512 return TRUE;
4bb6408c
JS
513}
514
982b2cfc 515bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool)
4bb6408c 516{
8a0681f9 517 tool->Detach();
0d57be45 518
8a0681f9 519 return TRUE;
4bb6408c
JS
520}
521
982b2cfc 522void wxToolBar::DoEnableTool(wxToolBarToolBase *toolBase, bool enable)
1a3ac83f 523{
982b2cfc
VZ
524 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
525
8a0681f9 526 XtSetSensitive(tool->GetButtonWidget(), (Boolean) enable);
1a3ac83f
JS
527}
528
982b2cfc 529void wxToolBar::DoToggleTool(wxToolBarToolBase *toolBase, bool toggle)
4bb6408c 530{
982b2cfc
VZ
531 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
532
8a0681f9 533 XmToggleButtonSetState(tool->GetButtonWidget(), (Boolean) toggle, False);
4bb6408c
JS
534}
535
982b2cfc
VZ
536void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool),
537 bool WXUNUSED(toggle))
1a3ac83f 538{
982b2cfc 539 // nothing to do
1a3ac83f
JS
540}
541
46675b46
MB
542void wxToolBar::DoSetSize(int x, int y, int width, int height, int sizeFlags)
543{
544 int old_width, old_height;
545 GetSize(&old_width, &old_height);
546
547 wxToolBarBase::DoSetSize(x, y, width, height, sizeFlags);
548
549 // Correct width and height if needed.
550 if ( width == -1 || height == -1 )
551 {
552 int tmp_width, tmp_height;
553 GetSize(&tmp_width, &tmp_height);
554
555 if ( width == -1 )
556 width = tmp_width;
557 if ( height == -1 )
558 height = tmp_height;
559 }
560
561 // We must refresh the frame size when the toolbar changes size
562 // otherwise the toolbar can be shown incorrectly
563 if ( old_width != width || old_height != height )
564 {
565 // But before we send the size event check it
566 // we have a frame that is not being deleted.
567 wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
568 if ( frame && !frame->IsBeingDeleted() )
569 {
570 frame->SendSizeEvent();
571 }
572 }
573}
574
8a0681f9
VZ
575// ----------------------------------------------------------------------------
576// Motif callbacks
577// ----------------------------------------------------------------------------
1a3ac83f 578
982b2cfc 579wxToolBarToolBase *wxToolBar::FindToolByWidget(WXWidget w) const
7fe7d506 580{
8a0681f9
VZ
581 wxToolBarToolsList::Node* node = m_tools.GetFirst();
582 while ( node )
583 {
584 wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
585 if ( tool->GetButtonWidget() == w)
586 {
587 return tool;
588 }
7fe7d506 589
8a0681f9
VZ
590 node = node->GetNext();
591 }
7fe7d506 592
982b2cfc 593 return (wxToolBarToolBase *)NULL;
7fe7d506
JS
594}
595
8a0681f9
VZ
596static void wxToolButtonCallback(Widget w,
597 XtPointer clientData,
598 XtPointer WXUNUSED(ptr))
1a3ac83f
JS
599{
600 wxToolBar *toolBar = (wxToolBar *) clientData;
982b2cfc 601 wxToolBarToolBase *tool = toolBar->FindToolByWidget((WXWidget) w);
8a0681f9
VZ
602 if ( !tool )
603 return;
1a3ac83f 604
8a0681f9
VZ
605 if ( tool->CanBeToggled() )
606 tool->Toggle();
607
608 if ( !toolBar->OnLeftClick(tool->GetId(), tool->IsToggled()) )
1a3ac83f 609 {
8a0681f9
VZ
610 // revert
611 tool->Toggle();
1a3ac83f 612 }
1a3ac83f
JS
613}
614
1a3ac83f 615
8a0681f9
VZ
616static void wxToolButtonPopupCallback(Widget w,
617 XtPointer client_data,
618 XEvent *event,
619 Boolean *WXUNUSED(continue_to_dispatch))
1a3ac83f
JS
620{
621 // TODO: retrieve delay before popping up tooltip from wxSystemSettings.
8a0681f9 622 static const int delayMilli = 800;
1a3ac83f 623
8a0681f9 624 wxToolBar* toolBar = (wxToolBar*) client_data;
982b2cfc 625 wxToolBarToolBase *tool = toolBar->FindToolByWidget((WXWidget) w);
1a3ac83f 626
8a0681f9
VZ
627 if ( !tool )
628 return;
1a3ac83f 629
8a0681f9
VZ
630 wxString tooltip = tool->GetShortHelp();
631 if ( !tooltip )
632 return;
1a3ac83f 633
8a0681f9
VZ
634 if (!wxTheToolBarTimer)
635 wxTheToolBarTimer = new wxToolBarTimer;
1a3ac83f 636
8a0681f9
VZ
637 wxToolBarTimer::buttonWidget = w;
638 wxToolBarTimer::helpString = tooltip;
1a3ac83f
JS
639
640 /************************************************************/
641 /* Popup help label */
642 /************************************************************/
643 if (event->type == EnterNotify)
644 {
645 if (wxToolBarTimer::help_popup != (Widget) 0)
646 {
647 XtDestroyWidget (wxToolBarTimer::help_popup);
648 XtPopdown (wxToolBarTimer::help_popup);
bf6c2b35 649 }
1a3ac83f
JS
650 wxToolBarTimer::help_popup = (Widget) 0;
651
652 // One shot
653 wxTheToolBarTimer->Start(delayMilli, TRUE);
654
655 }
656 /************************************************************/
657 /* Popdown help label */
658 /************************************************************/
659 else if (event->type == LeaveNotify)
660 {
661 if (wxTheToolBarTimer)
662 wxTheToolBarTimer->Stop();
663 if (wxToolBarTimer::help_popup != (Widget) 0)
664 {
665 XtDestroyWidget (wxToolBarTimer::help_popup);
666 XtPopdown (wxToolBarTimer::help_popup);
bf6c2b35 667 }
1a3ac83f
JS
668 wxToolBarTimer::help_popup = (Widget) 0;
669 }
1a3ac83f
JS
670}
671
672void wxToolBarTimer::Notify()
673{
674 Position x, y;
675
676 /************************************************************/
677 /* Create shell without window decorations */
678 /************************************************************/
bf6c2b35
VZ
679 help_popup = XtVaCreatePopupShell ("shell",
680 overrideShellWidgetClass, (Widget) wxTheApp->GetTopLevelWidget(),
1a3ac83f
JS
681 NULL);
682
683 /************************************************************/
684 /* Get absolute position on display of toolbar button */
685 /************************************************************/
686 XtTranslateCoords (buttonWidget,
bf6c2b35
VZ
687 (Position) 0,
688 (Position) 0,
1a3ac83f
JS
689 &x, &y);
690
691 // Move the tooltip more or less above the button
692 int yOffset = 20; // TODO: What should be really?
693 y -= yOffset;
694 if (y < yOffset) y = 0;
695
696 /************************************************************/
697 /* Set the position of the help popup */
698 /************************************************************/
bf6c2b35
VZ
699 XtVaSetValues (help_popup,
700 XmNx, (Position) x,
701 XmNy, (Position) y,
1a3ac83f 702 NULL);
bf6c2b35 703
1a3ac83f
JS
704 /************************************************************/
705 /* Create help label */
706 /************************************************************/
707 XmString text = XmStringCreateSimple ((char*) (const char*) helpString);
bf6c2b35
VZ
708 XtVaCreateManagedWidget ("help_label",
709 xmLabelWidgetClass, help_popup,
1a3ac83f 710 XmNlabelString, text,
bf6c2b35
VZ
711 XtVaTypedArg,
712 XmNforeground, XtRString, "black",
713 strlen("black")+1,
714 XtVaTypedArg,
715 XmNbackground, XtRString, "LightGoldenrod",
716 strlen("LightGoldenrod")+1,
1a3ac83f
JS
717 NULL);
718 XmStringFree (text);
719
720 /************************************************************/
721 /* Popup help label */
722 /************************************************************/
723 XtPopup (help_popup, XtGrabNone);
724}
725