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