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