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