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