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 wxBitmap
& bitmap1
,
86 const wxBitmap
& bitmap2
,
89 const wxString
& shortHelpString
,
90 const wxString
& longHelpString
)
91 : wxToolBarToolBase(tbar
, id
, bitmap1
, bitmap2
, toggle
,
92 clientData
, shortHelpString
, longHelpString
)
97 wxToolBarTool(wxToolBar
*tbar
, wxControl
*control
)
98 : wxToolBarToolBase(tbar
, control
)
103 virtual ~wxToolBarTool();
106 void SetWidget(Widget widget
) { m_widget
= widget
; }
107 Widget
GetButtonWidget() const { return m_widget
; }
109 void SetPixmap(Pixmap pixmap
) { m_pixmap
= pixmap
; }
110 Pixmap
GetPixmap() const { return m_pixmap
; }
119 // ----------------------------------------------------------------------------
121 // ----------------------------------------------------------------------------
123 static wxToolBarTimer
* wxTheToolBarTimer
= (wxToolBarTimer
*) NULL
;
125 Widget
wxToolBarTimer::help_popup
= (Widget
) 0;
126 Widget
wxToolBarTimer::buttonWidget
= (Widget
) 0;
127 wxString
wxToolBarTimer::helpString
;
129 // ============================================================================
131 // ============================================================================
133 // ----------------------------------------------------------------------------
135 // ----------------------------------------------------------------------------
137 wxToolBarToolBase
*wxToolBar::CreateTool(int id
,
138 const wxBitmap
& bitmap1
,
139 const wxBitmap
& bitmap2
,
141 wxObject
*clientData
,
142 const wxString
& shortHelpString
,
143 const wxString
& longHelpString
)
145 return new wxToolBarTool(this, id
, bitmap1
, bitmap2
, toggle
,
146 clientData
, shortHelpString
, longHelpString
);
149 wxToolBarToolBase
*wxToolBar::CreateTool(wxControl
*control
)
151 return new wxToolBarTool(this, control
);
154 void wxToolBarTool::Init()
156 m_widget
= (Widget
)0;
157 m_pixmap
= (Pixmap
)0;
160 wxToolBarTool::~wxToolBarTool()
163 XtDestroyWidget(m_widget
);
165 XmDestroyPixmap(DefaultScreenOfDisplay((Display
*)wxGetDisplay()),
169 // ----------------------------------------------------------------------------
170 // wxToolBar construction
171 // ----------------------------------------------------------------------------
173 void wxToolBar::Init()
178 m_defaultHeight
= 22;
180 m_toolSeparation
= 8;
187 bool wxToolBar::Create(wxWindow
*parent
,
192 const wxString
& name
)
199 m_backgroundColour
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
);
200 m_foregroundColour
= parent
->GetForegroundColour();
201 m_windowStyle
= style
;
205 if (parent
) parent
->AddChild(this);
207 Widget parentWidget
= (Widget
) parent
->GetClientWidget();
209 Widget toolbar
= XtVaCreateManagedWidget("toolbar",
210 xmBulletinBoardWidgetClass
, (Widget
) parentWidget
,
213 XmNresizePolicy
, XmRESIZE_NONE
,
216 Widget toolbar = XtVaCreateManagedWidget("toolbar",
217 xmFormWidgetClass, (Widget) m_clientWidget,
218 XmNtraversalOn, False,
219 XmNhorizontalSpacing, 0,
220 XmNverticalSpacing, 0,
228 m_mainWidget
= (WXWidget
) toolbar
;
230 m_font
= parent
->GetFont();
233 SetCanAddEventHandler(TRUE
);
234 AttachWidget (parent
, m_mainWidget
, (WXWidget
) NULL
, pos
.x
, pos
.y
, size
.x
, size
.y
);
236 ChangeBackgroundColour();
241 wxToolBar::~wxToolBar()
243 delete wxTheToolBarTimer
;
244 wxTheToolBarTimer
= NULL
;
247 bool wxToolBar::Realize()
249 if ( m_tools
.GetCount() == 0 )
256 const int separatorSize
= GetToolSeparation(); // 8;
257 wxSize margins
= GetToolMargins();
258 int packing
= GetToolPacking();
259 int marginX
= margins
.x
;
260 int marginY
= margins
.y
;
262 int currentX
= marginX
;
263 int currentY
= marginY
;
265 int buttonHeight
= 0;
267 int currentSpacing
= 0;
270 Pixmap pixmap
, insensPixmap
;
273 wxToolBarToolsList::Node
*node
= m_tools
.GetFirst();
276 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->GetData();
278 switch ( tool
->GetStyle() )
280 case wxTOOL_STYLE_CONTROL
:
282 wxControl
* control
= tool
->GetControl();
283 wxSize sz
= control
->GetSize();
284 wxPoint pos
= control
->GetPosition();
285 control
->Move(currentX
, pos
.y
);
286 currentX
+= sz
.x
+ packing
;
290 case wxTOOL_STYLE_SEPARATOR
:
291 currentX
+= separatorSize
;
294 case wxTOOL_STYLE_BUTTON
:
297 if ( tool
->CanBeToggled() )
299 button
= XtVaCreateWidget("toggleButton",
300 xmToggleButtonWidgetClass
, (Widget
) m_mainWidget
,
301 XmNx
, currentX
, XmNy
, currentY
,
302 XmNindicatorOn
, False
,
303 XmNshadowThickness
, 2,
308 XmNmultiClick
, XmMULTICLICK_KEEP
,
309 XmNlabelType
, XmPIXMAP
,
311 XtAddCallback ((Widget
) button
, XmNvalueChangedCallback
, (XtCallbackProc
) wxToolButtonCallback
,
314 XtVaSetValues ((Widget
) button
,
315 XmNselectColor
, m_backgroundColour
.AllocColour(XtDisplay((Widget
) button
)),
320 button
= XtVaCreateWidget("button",
321 xmPushButtonWidgetClass
, (Widget
) m_mainWidget
,
322 XmNx
, currentX
, XmNy
, currentY
,
323 XmNpushButtonEnabled
, True
,
324 XmNmultiClick
, XmMULTICLICK_KEEP
,
325 XmNlabelType
, XmPIXMAP
,
327 XtAddCallback (button
,
328 XmNactivateCallback
, (XtCallbackProc
) wxToolButtonCallback
,
332 DoChangeBackgroundColour((WXWidget
) button
, m_backgroundColour
, TRUE
);
334 tool
->SetWidget(button
);
336 // For each button, if there is a mask, we must create
337 // a new wxBitmap that has the correct background colour
338 // for the button. Otherwise the background will just be
339 // e.g. black if a transparent XPM has been loaded.
340 bmp
= tool
->GetBitmap1();
344 XtVaGetValues(button
, XmNbackground
, &backgroundPixel
,
348 col
.SetPixel(backgroundPixel
);
350 bmp
= wxCreateMaskedBitmap(bmp
, col
);
352 tool
->SetBitmap1(bmp
);
355 // Create a selected/toggled bitmap. If there isn't a 2nd
356 // bitmap, we need to create it (with a darker, selected
359 if ( tool
->CanBeToggled() )
360 XtVaGetValues(button
, XmNselectColor
, &backgroundPixel
,
363 XtVaGetValues(button
, XmNarmColor
, &backgroundPixel
,
367 col
.SetPixel(backgroundPixel
);
369 if (tool
->GetBitmap2().Ok() && tool
->GetBitmap2().GetMask())
372 wxBitmap newBitmap
= wxCreateMaskedBitmap(tool
->GetBitmap2(), col
);
373 tool
->SetBitmap2(newBitmap
);
377 // Use unselected bitmap
380 wxBitmap newBitmap
= wxCreateMaskedBitmap(bmp
, col
);
381 tool
->SetBitmap2(newBitmap
);
384 tool
->SetBitmap2(bmp
);
387 pixmap
= (Pixmap
) bmp
.GetPixmap();
388 insensPixmap
= (Pixmap
) bmp
.GetInsensPixmap();
390 if (tool
->CanBeToggled())
393 Pixmap pixmap2
= (Pixmap
) 0;
394 Pixmap insensPixmap2
= (Pixmap
) 0;
396 // If there's a bitmap for the toggled state, use it,
397 // otherwise generate one.
398 if (tool
->GetBitmap2().Ok())
400 wxBitmap bmp2
= tool
->GetBitmap2();
401 pixmap2
= (Pixmap
) bmp2
.GetPixmap();
402 insensPixmap2
= (Pixmap
) bmp2
.GetInsensPixmap();
406 pixmap2
= (Pixmap
) bmp
.GetArmPixmap(button
);
407 insensPixmap2
= XCreateInsensitivePixmap((Display
*) wxGetDisplay(), pixmap2
);
410 tool
->SetPixmap(pixmap2
);
412 XtVaSetValues (button
,
413 XmNfillOnSelect
, True
,
414 XmNlabelPixmap
, pixmap
,
415 XmNselectPixmap
, pixmap2
,
416 XmNlabelInsensitivePixmap
, insensPixmap
,
417 XmNselectInsensitivePixmap
, insensPixmap2
,
418 XmNlabelType
, XmPIXMAP
,
423 Pixmap pixmap2
= (Pixmap
) 0;
425 // If there's a bitmap for the armed state, use it,
426 // otherwise generate one.
427 if (tool
->GetBitmap2().Ok())
429 pixmap2
= (Pixmap
) tool
->GetBitmap2().GetPixmap();
433 pixmap2
= (Pixmap
) bmp
.GetArmPixmap(button
);
437 tool
->SetPixmap(pixmap2
);
440 XtVaSetValues(button
,
441 XmNlabelPixmap
, pixmap
,
442 XmNlabelInsensitivePixmap
, insensPixmap
,
443 XmNarmPixmap
, pixmap2
,
447 XtManageChild(button
);
450 Dimension width
, height
;
451 XtVaGetValues(button
,
455 currentX
+= width
+ packing
;
456 buttonHeight
= wxMax(buttonHeight
, height
);
459 XtAddEventHandler (button
, EnterWindowMask
| LeaveWindowMask
,
460 False
, wxToolButtonPopupCallback
, (XtPointer
) this);
466 node
= node
->GetNext();
469 SetSize(-1, -1, currentX
, buttonHeight
+ 2*marginY
);
474 wxToolBarToolBase
*wxToolBar::FindToolForPosition(wxCoord
WXUNUSED(x
),
475 wxCoord
WXUNUSED(y
)) const
477 wxFAIL_MSG( _T("TODO") );
479 return (wxToolBarToolBase
*)NULL
;
482 bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos
), wxToolBarToolBase
*tool
)
489 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos
), wxToolBarToolBase
*tool
)
496 void wxToolBar::DoEnableTool(wxToolBarToolBase
*toolBase
, bool enable
)
498 wxToolBarTool
*tool
= (wxToolBarTool
*)toolBase
;
500 XtSetSensitive(tool
->GetButtonWidget(), (Boolean
) enable
);
503 void wxToolBar::DoToggleTool(wxToolBarToolBase
*toolBase
, bool toggle
)
505 wxToolBarTool
*tool
= (wxToolBarTool
*)toolBase
;
507 XmToggleButtonSetState(tool
->GetButtonWidget(), (Boolean
) toggle
, False
);
510 void wxToolBar::DoSetToggle(wxToolBarToolBase
* WXUNUSED(tool
),
511 bool WXUNUSED(toggle
))
516 // ----------------------------------------------------------------------------
518 // ----------------------------------------------------------------------------
520 wxToolBarToolBase
*wxToolBar::FindToolByWidget(WXWidget w
) const
522 wxToolBarToolsList::Node
* node
= m_tools
.GetFirst();
525 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->GetData();
526 if ( tool
->GetButtonWidget() == w
)
531 node
= node
->GetNext();
534 return (wxToolBarToolBase
*)NULL
;
537 static void wxToolButtonCallback(Widget w
,
538 XtPointer clientData
,
539 XtPointer
WXUNUSED(ptr
))
541 wxToolBar
*toolBar
= (wxToolBar
*) clientData
;
542 wxToolBarToolBase
*tool
= toolBar
->FindToolByWidget((WXWidget
) w
);
546 if ( tool
->CanBeToggled() )
549 if ( !toolBar
->OnLeftClick(tool
->GetId(), tool
->IsToggled()) )
557 static void wxToolButtonPopupCallback(Widget w
,
558 XtPointer client_data
,
560 Boolean
*WXUNUSED(continue_to_dispatch
))
562 // TODO: retrieve delay before popping up tooltip from wxSystemSettings.
563 static const int delayMilli
= 800;
565 wxToolBar
* toolBar
= (wxToolBar
*) client_data
;
566 wxToolBarToolBase
*tool
= toolBar
->FindToolByWidget((WXWidget
) w
);
571 wxString tooltip
= tool
->GetShortHelp();
575 if (!wxTheToolBarTimer
)
576 wxTheToolBarTimer
= new wxToolBarTimer
;
578 wxToolBarTimer::buttonWidget
= w
;
579 wxToolBarTimer::helpString
= tooltip
;
581 /************************************************************/
582 /* Popup help label */
583 /************************************************************/
584 if (event
->type
== EnterNotify
)
586 if (wxToolBarTimer::help_popup
!= (Widget
) 0)
588 XtDestroyWidget (wxToolBarTimer::help_popup
);
589 XtPopdown (wxToolBarTimer::help_popup
);
591 wxToolBarTimer::help_popup
= (Widget
) 0;
594 wxTheToolBarTimer
->Start(delayMilli
, TRUE
);
597 /************************************************************/
598 /* Popdown help label */
599 /************************************************************/
600 else if (event
->type
== LeaveNotify
)
602 if (wxTheToolBarTimer
)
603 wxTheToolBarTimer
->Stop();
604 if (wxToolBarTimer::help_popup
!= (Widget
) 0)
606 XtDestroyWidget (wxToolBarTimer::help_popup
);
607 XtPopdown (wxToolBarTimer::help_popup
);
609 wxToolBarTimer::help_popup
= (Widget
) 0;
613 void wxToolBarTimer::Notify()
617 /************************************************************/
618 /* Create shell without window decorations */
619 /************************************************************/
620 help_popup
= XtVaCreatePopupShell ("shell",
621 overrideShellWidgetClass
, (Widget
) wxTheApp
->GetTopLevelWidget(),
624 /************************************************************/
625 /* Get absolute position on display of toolbar button */
626 /************************************************************/
627 XtTranslateCoords (buttonWidget
,
632 // Move the tooltip more or less above the button
633 int yOffset
= 20; // TODO: What should be really?
635 if (y
< yOffset
) y
= 0;
637 /************************************************************/
638 /* Set the position of the help popup */
639 /************************************************************/
640 XtVaSetValues (help_popup
,
645 /************************************************************/
646 /* Create help label */
647 /************************************************************/
648 XmString text
= XmStringCreateSimple ((char*) (const char*) helpString
);
649 XtVaCreateManagedWidget ("help_label",
650 xmLabelWidgetClass
, help_popup
,
651 XmNlabelString
, text
,
653 XmNforeground
, XtRString
, "black",
656 XmNbackground
, XtRString
, "LightGoldenrod",
657 strlen("LightGoldenrod")+1,
661 /************************************************************/
662 /* Popup help label */
663 /************************************************************/
664 XtPopup (help_popup
, XtGrabNone
);