1 /////////////////////////////////////////////////////////////////////////////
2 // Name: motif/toolbar.cpp
4 // Author: Julian Smart
5 // Modified by: 13.12.99 by VZ during toolbar classes reorganization
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "toolbar.h"
25 #define XtDisplay XTDISPLAY
31 #include "wx/toolbar.h"
34 #pragma message disable nosimpint
37 #include <Xm/PushBG.h>
40 #include <Xm/ToggleB.h>
41 #include <Xm/ToggleBG.h>
44 #pragma message enable nosimpint
47 #include "wx/motif/private.h"
49 // ----------------------------------------------------------------------------
51 // ----------------------------------------------------------------------------
53 #if !USE_SHARED_LIBRARY
54 IMPLEMENT_DYNAMIC_CLASS(wxToolBar
, wxToolBarBase
)
57 // ----------------------------------------------------------------------------
59 // ----------------------------------------------------------------------------
61 static void wxToolButtonCallback (Widget w
, XtPointer clientData
,
63 static void wxToolButtonPopupCallback (Widget w
, XtPointer client_data
,
64 XEvent
*event
, Boolean
*continue_to_dispatch
);
66 // ----------------------------------------------------------------------------
68 // ----------------------------------------------------------------------------
70 class wxToolBarTimer
: public wxTimer
73 virtual void Notify();
75 static Widget help_popup
;
76 static Widget buttonWidget
;
77 static wxString helpString
;
80 class wxToolBarTool
: public wxToolBarToolBase
83 wxToolBarTool(wxToolBar
*tbar
,
85 const wxString
& label
,
86 const wxBitmap
& bmpNormal
,
87 const wxBitmap
& bmpToggled
,
90 const wxString
& shortHelp
,
91 const wxString
& longHelp
)
92 : wxToolBarToolBase(tbar
, id
, label
, bmpNormal
, bmpToggled
, kind
,
93 clientData
, shortHelp
, longHelp
)
98 wxToolBarTool(wxToolBar
*tbar
, wxControl
*control
)
99 : wxToolBarToolBase(tbar
, control
)
104 virtual ~wxToolBarTool();
107 void SetWidget(Widget widget
) { m_widget
= widget
; }
108 Widget
GetButtonWidget() const { return m_widget
; }
110 void SetPixmap(Pixmap pixmap
) { m_pixmap
= pixmap
; }
111 Pixmap
GetPixmap() const { return m_pixmap
; }
120 // ----------------------------------------------------------------------------
122 // ----------------------------------------------------------------------------
124 static wxToolBarTimer
* wxTheToolBarTimer
= (wxToolBarTimer
*) NULL
;
126 Widget
wxToolBarTimer::help_popup
= (Widget
) 0;
127 Widget
wxToolBarTimer::buttonWidget
= (Widget
) 0;
128 wxString
wxToolBarTimer::helpString
;
130 // ============================================================================
132 // ============================================================================
134 // ----------------------------------------------------------------------------
136 // ----------------------------------------------------------------------------
138 wxToolBarToolBase
*wxToolBar::CreateTool(int id
,
139 const wxString
& label
,
140 const wxBitmap
& bmpNormal
,
141 const wxBitmap
& bmpToggled
,
143 wxObject
*clientData
,
144 const wxString
& shortHelp
,
145 const wxString
& longHelp
)
147 return new wxToolBarTool(this, id
, label
, bmpNormal
, bmpToggled
, kind
,
148 clientData
, shortHelp
, longHelp
);
152 wxToolBarToolBase
*wxToolBar::CreateTool(wxControl
*control
)
154 return new wxToolBarTool(this, control
);
157 void wxToolBarTool::Init()
159 m_widget
= (Widget
)0;
160 m_pixmap
= (Pixmap
)0;
163 wxToolBarTool::~wxToolBarTool()
166 XtDestroyWidget(m_widget
);
168 XmDestroyPixmap(DefaultScreenOfDisplay((Display
*)wxGetDisplay()),
172 // ----------------------------------------------------------------------------
173 // wxToolBar construction
174 // ----------------------------------------------------------------------------
176 void wxToolBar::Init()
181 m_defaultHeight
= 22;
183 m_toolSeparation
= 8;
190 bool wxToolBar::Create(wxWindow
*parent
,
195 const wxString
& name
)
202 m_backgroundColour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
203 m_foregroundColour
= parent
->GetForegroundColour();
204 m_windowStyle
= style
;
208 if (parent
) parent
->AddChild(this);
210 Widget parentWidget
= (Widget
) parent
->GetClientWidget();
212 Widget toolbar
= XtVaCreateManagedWidget("toolbar",
213 xmBulletinBoardWidgetClass
, (Widget
) parentWidget
,
216 XmNresizePolicy
, XmRESIZE_NONE
,
219 Widget toolbar = XtVaCreateManagedWidget("toolbar",
220 xmFormWidgetClass, (Widget) m_clientWidget,
221 XmNtraversalOn, False,
222 XmNhorizontalSpacing, 0,
223 XmNverticalSpacing, 0,
231 m_mainWidget
= (WXWidget
) toolbar
;
233 m_font
= parent
->GetFont();
236 SetCanAddEventHandler(TRUE
);
237 AttachWidget (parent
, m_mainWidget
, (WXWidget
) NULL
, pos
.x
, pos
.y
, size
.x
, size
.y
);
239 ChangeBackgroundColour();
244 wxToolBar::~wxToolBar()
246 delete wxTheToolBarTimer
;
247 wxTheToolBarTimer
= NULL
;
250 bool wxToolBar::Realize()
252 if ( m_tools
.GetCount() == 0 )
259 const int separatorSize
= GetToolSeparation(); // 8;
260 wxSize margins
= GetToolMargins();
261 int packing
= GetToolPacking();
262 int marginX
= margins
.x
;
263 int marginY
= margins
.y
;
265 int currentX
= marginX
;
266 int currentY
= marginY
;
268 int buttonHeight
= 0;
270 int currentSpacing
= 0;
273 Pixmap pixmap
, insensPixmap
;
276 wxToolBarToolsList::Node
*node
= m_tools
.GetFirst();
279 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->GetData();
281 switch ( tool
->GetStyle() )
283 case wxTOOL_STYLE_CONTROL
:
285 wxControl
* control
= tool
->GetControl();
286 wxSize sz
= control
->GetSize();
287 wxPoint pos
= control
->GetPosition();
288 control
->Move(currentX
, pos
.y
);
289 currentX
+= sz
.x
+ packing
;
293 case wxTOOL_STYLE_SEPARATOR
:
294 currentX
+= separatorSize
;
297 case wxTOOL_STYLE_BUTTON
:
300 if ( tool
->CanBeToggled() )
302 button
= XtVaCreateWidget("toggleButton",
303 xmToggleButtonWidgetClass
, (Widget
) m_mainWidget
,
304 XmNx
, currentX
, XmNy
, currentY
,
305 XmNindicatorOn
, False
,
306 XmNshadowThickness
, 2,
311 XmNmultiClick
, XmMULTICLICK_KEEP
,
312 XmNlabelType
, XmPIXMAP
,
314 XtAddCallback ((Widget
) button
, XmNvalueChangedCallback
, (XtCallbackProc
) wxToolButtonCallback
,
317 XtVaSetValues ((Widget
) button
,
318 XmNselectColor
, m_backgroundColour
.AllocColour(XtDisplay((Widget
) button
)),
323 button
= XtVaCreateWidget("button",
324 xmPushButtonWidgetClass
, (Widget
) m_mainWidget
,
325 XmNx
, currentX
, XmNy
, currentY
,
326 XmNpushButtonEnabled
, True
,
327 XmNmultiClick
, XmMULTICLICK_KEEP
,
328 XmNlabelType
, XmPIXMAP
,
330 XtAddCallback (button
,
331 XmNactivateCallback
, (XtCallbackProc
) wxToolButtonCallback
,
335 DoChangeBackgroundColour((WXWidget
) button
, m_backgroundColour
, TRUE
);
337 tool
->SetWidget(button
);
339 // For each button, if there is a mask, we must create
340 // a new wxBitmap that has the correct background colour
341 // for the button. Otherwise the background will just be
342 // e.g. black if a transparent XPM has been loaded.
343 bmp
= tool
->GetNormalBitmap();
347 XtVaGetValues(button
, XmNbackground
, &backgroundPixel
,
351 col
.SetPixel(backgroundPixel
);
353 bmp
= wxCreateMaskedBitmap(bmp
, col
);
355 tool
->SetNormalBitmap(bmp
);
358 // Create a selected/toggled bitmap. If there isn't a 2nd
359 // bitmap, we need to create it (with a darker, selected
362 if ( tool
->CanBeToggled() )
363 XtVaGetValues(button
, XmNselectColor
, &backgroundPixel
,
366 XtVaGetValues(button
, XmNarmColor
, &backgroundPixel
,
370 col
.SetPixel(backgroundPixel
);
372 // FIXME: we use disabled bitmap as the bitmap for the toggled
373 // state, we probably need a GetToggledBitmap() instead
374 wxBitmap bmpToggled
= tool
->GetDisabledBitmap();
375 if ( bmpToggled
.Ok() && bmpToggled
.GetMask())
378 wxBitmap newBitmap
= wxCreateMaskedBitmap(bmpToggled
, col
);
379 tool
->SetDisabledBitmap(newBitmap
);
383 // Use unselected bitmap
386 wxBitmap newBitmap
= wxCreateMaskedBitmap(bmp
, col
);
387 tool
->SetDisabledBitmap(newBitmap
);
390 tool
->SetDisabledBitmap(bmp
);
393 // FIXME: and here we should use GetDisabledBitmap()...
394 pixmap
= (Pixmap
) bmp
.GetPixmap();
395 insensPixmap
= (Pixmap
) bmp
.GetInsensPixmap();
397 if (tool
->CanBeToggled())
400 Pixmap pixmap2
= (Pixmap
) 0;
401 Pixmap insensPixmap2
= (Pixmap
) 0;
403 // If there's a bitmap for the toggled state, use it,
404 // otherwise generate one.
407 if ( bmpToggled
.Ok() )
409 pixmap2
= (Pixmap
) bmpToggled
.GetPixmap();
410 insensPixmap2
= (Pixmap
) bmpToggled
.GetInsensPixmap();
414 pixmap2
= (Pixmap
) bmp
.GetArmPixmap(button
);
415 insensPixmap2
= XCreateInsensitivePixmap((Display
*) wxGetDisplay(), pixmap2
);
418 tool
->SetPixmap(pixmap2
);
420 XtVaSetValues (button
,
421 XmNfillOnSelect
, True
,
422 XmNlabelPixmap
, pixmap
,
423 XmNselectPixmap
, pixmap2
,
424 XmNlabelInsensitivePixmap
, insensPixmap
,
425 XmNselectInsensitivePixmap
, insensPixmap2
,
426 XmNlabelType
, XmPIXMAP
,
431 Pixmap pixmap2
= (Pixmap
) 0;
433 // If there's a bitmap for the armed state, use it,
434 // otherwise generate one.
435 if ( bmpToggled
.Ok() )
437 pixmap2
= (Pixmap
) bmpToggled
.GetPixmap();
441 pixmap2
= (Pixmap
) bmp
.GetArmPixmap(button
);
445 tool
->SetPixmap(pixmap2
);
448 XtVaSetValues(button
,
449 XmNlabelPixmap
, pixmap
,
450 XmNlabelInsensitivePixmap
, insensPixmap
,
451 XmNarmPixmap
, pixmap2
,
455 XtManageChild(button
);
458 Dimension width
, height
;
459 XtVaGetValues(button
,
463 currentX
+= width
+ packing
;
464 buttonHeight
= wxMax(buttonHeight
, height
);
467 XtAddEventHandler (button
, EnterWindowMask
| LeaveWindowMask
,
468 False
, wxToolButtonPopupCallback
, (XtPointer
) this);
474 node
= node
->GetNext();
477 SetSize(-1, -1, currentX
, buttonHeight
+ 2*marginY
);
482 wxToolBarToolBase
*wxToolBar::FindToolForPosition(wxCoord
WXUNUSED(x
),
483 wxCoord
WXUNUSED(y
)) const
485 wxFAIL_MSG( _T("TODO") );
487 return (wxToolBarToolBase
*)NULL
;
490 bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos
), wxToolBarToolBase
*tool
)
497 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos
), wxToolBarToolBase
*tool
)
504 void wxToolBar::DoEnableTool(wxToolBarToolBase
*toolBase
, bool enable
)
506 wxToolBarTool
*tool
= (wxToolBarTool
*)toolBase
;
508 XtSetSensitive(tool
->GetButtonWidget(), (Boolean
) enable
);
511 void wxToolBar::DoToggleTool(wxToolBarToolBase
*toolBase
, bool toggle
)
513 wxToolBarTool
*tool
= (wxToolBarTool
*)toolBase
;
515 XmToggleButtonSetState(tool
->GetButtonWidget(), (Boolean
) toggle
, False
);
518 void wxToolBar::DoSetToggle(wxToolBarToolBase
* WXUNUSED(tool
),
519 bool WXUNUSED(toggle
))
524 // ----------------------------------------------------------------------------
526 // ----------------------------------------------------------------------------
528 wxToolBarToolBase
*wxToolBar::FindToolByWidget(WXWidget w
) const
530 wxToolBarToolsList::Node
* node
= m_tools
.GetFirst();
533 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->GetData();
534 if ( tool
->GetButtonWidget() == w
)
539 node
= node
->GetNext();
542 return (wxToolBarToolBase
*)NULL
;
545 static void wxToolButtonCallback(Widget w
,
546 XtPointer clientData
,
547 XtPointer
WXUNUSED(ptr
))
549 wxToolBar
*toolBar
= (wxToolBar
*) clientData
;
550 wxToolBarToolBase
*tool
= toolBar
->FindToolByWidget((WXWidget
) w
);
554 if ( tool
->CanBeToggled() )
557 if ( !toolBar
->OnLeftClick(tool
->GetId(), tool
->IsToggled()) )
565 static void wxToolButtonPopupCallback(Widget w
,
566 XtPointer client_data
,
568 Boolean
*WXUNUSED(continue_to_dispatch
))
570 // TODO: retrieve delay before popping up tooltip from wxSystemSettings.
571 static const int delayMilli
= 800;
573 wxToolBar
* toolBar
= (wxToolBar
*) client_data
;
574 wxToolBarToolBase
*tool
= toolBar
->FindToolByWidget((WXWidget
) w
);
579 wxString tooltip
= tool
->GetShortHelp();
583 if (!wxTheToolBarTimer
)
584 wxTheToolBarTimer
= new wxToolBarTimer
;
586 wxToolBarTimer::buttonWidget
= w
;
587 wxToolBarTimer::helpString
= tooltip
;
589 /************************************************************/
590 /* Popup help label */
591 /************************************************************/
592 if (event
->type
== EnterNotify
)
594 if (wxToolBarTimer::help_popup
!= (Widget
) 0)
596 XtDestroyWidget (wxToolBarTimer::help_popup
);
597 XtPopdown (wxToolBarTimer::help_popup
);
599 wxToolBarTimer::help_popup
= (Widget
) 0;
602 wxTheToolBarTimer
->Start(delayMilli
, TRUE
);
605 /************************************************************/
606 /* Popdown help label */
607 /************************************************************/
608 else if (event
->type
== LeaveNotify
)
610 if (wxTheToolBarTimer
)
611 wxTheToolBarTimer
->Stop();
612 if (wxToolBarTimer::help_popup
!= (Widget
) 0)
614 XtDestroyWidget (wxToolBarTimer::help_popup
);
615 XtPopdown (wxToolBarTimer::help_popup
);
617 wxToolBarTimer::help_popup
= (Widget
) 0;
621 void wxToolBarTimer::Notify()
625 /************************************************************/
626 /* Create shell without window decorations */
627 /************************************************************/
628 help_popup
= XtVaCreatePopupShell ("shell",
629 overrideShellWidgetClass
, (Widget
) wxTheApp
->GetTopLevelWidget(),
632 /************************************************************/
633 /* Get absolute position on display of toolbar button */
634 /************************************************************/
635 XtTranslateCoords (buttonWidget
,
640 // Move the tooltip more or less above the button
641 int yOffset
= 20; // TODO: What should be really?
643 if (y
< yOffset
) y
= 0;
645 /************************************************************/
646 /* Set the position of the help popup */
647 /************************************************************/
648 XtVaSetValues (help_popup
,
653 /************************************************************/
654 /* Create help label */
655 /************************************************************/
656 XmString text
= XmStringCreateSimple ((char*) (const char*) helpString
);
657 XtVaCreateManagedWidget ("help_label",
658 xmLabelWidgetClass
, help_popup
,
659 XmNlabelString
, text
,
661 XmNforeground
, XtRString
, "black",
664 XmNbackground
, XtRString
, "LightGoldenrod",
665 strlen("LightGoldenrod")+1,
669 /************************************************************/
670 /* Popup help label */
671 /************************************************************/
672 XtPopup (help_popup
, XtGrabNone
);