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"
27 #include "wx/toolbar.h"
30 #pragma message disable nosimpint
33 #include <Xm/PushBG.h>
36 #include <Xm/ToggleB.h>
37 #include <Xm/ToggleBG.h>
40 #pragma message enable nosimpint
43 #include "wx/motif/private.h"
45 // ----------------------------------------------------------------------------
47 // ----------------------------------------------------------------------------
49 #if !USE_SHARED_LIBRARY
50 IMPLEMENT_DYNAMIC_CLASS(wxToolBar
, wxControl
)
53 // ----------------------------------------------------------------------------
55 // ----------------------------------------------------------------------------
57 static void wxToolButtonCallback (Widget w
, XtPointer clientData
,
59 static void wxToolButtonPopupCallback (Widget w
, XtPointer client_data
,
60 XEvent
*event
, Boolean
*continue_to_dispatch
);
62 // ----------------------------------------------------------------------------
64 // ----------------------------------------------------------------------------
66 class wxToolBarTimer
: public wxTimer
69 virtual void Notify();
71 static Widget help_popup
;
72 static Widget buttonWidget
;
73 static wxString helpString
;
76 class wxToolBarTool
: public wxToolBarToolBase
79 wxToolBarTool(wxToolBar
*tbar
,
81 const wxBitmap
& bitmap1
,
82 const wxBitmap
& bitmap2
,
85 const wxString
& shortHelpString
,
86 const wxString
& longHelpString
)
87 : wxToolBarToolBase(tbar
, id
, bitmap1
, bitmap2
, toggle
,
88 clientData
, shortHelpString
, longHelpString
)
93 wxToolBarTool(wxToolBar
*tbar
, wxControl
*control
)
94 : wxToolBarToolBase(tbar
, control
)
99 virtual ~wxToolBarTool();
102 void SetWidget(Widget widget
) { m_widget
= widget
; }
103 Widget
GetButtonWidget() const { return m_widget
; }
105 void SetPixmap(Pixmap pixmap
) { m_pixmap
= pixmap
; }
106 Pixmap
GetPixmap() const { return m_pixmap
; }
115 // ----------------------------------------------------------------------------
117 // ----------------------------------------------------------------------------
119 static wxToolBarTimer
* wxTheToolBarTimer
= (wxToolBarTimer
*) NULL
;
121 Widget
wxToolBarTimer::help_popup
= (Widget
) 0;
122 Widget
wxToolBarTimer::buttonWidget
= (Widget
) 0;
123 wxString
wxToolBarTimer::helpString
;
125 // ============================================================================
127 // ============================================================================
129 // ----------------------------------------------------------------------------
131 // ----------------------------------------------------------------------------
133 wxToolBarToolBase
*wxToolBar::CreateTool(int id
,
134 const wxBitmap
& bitmap1
,
135 const wxBitmap
& bitmap2
,
137 wxObject
*clientData
,
138 const wxString
& shortHelpString
,
139 const wxString
& longHelpString
)
141 return new wxToolBarTool(this, id
, bitmap1
, bitmap2
, toggle
,
142 clientData
, shortHelpString
, longHelpString
);
145 wxToolBarToolBase
*wxToolBar::CreateTool(wxControl
*control
)
147 return new wxToolBarTool(this, control
);
150 void wxToolBarTool::Init()
152 m_widget
= (Widget
)0;
153 m_pixmap
= (Pixmap
)0;
156 wxToolBarTool::~wxToolBarTool()
159 XtDestroyWidget(m_widget
);
161 XmDestroyPixmap(DefaultScreenOfDisplay((Display
*)wxGetDisplay()),
165 // ----------------------------------------------------------------------------
166 // wxToolBar construction
167 // ----------------------------------------------------------------------------
169 void wxToolBar::Init()
174 m_defaultHeight
= 22;
176 m_toolSeparation
= 8;
183 bool wxToolBar::Create(wxWindow
*parent
,
188 const wxString
& name
)
195 m_backgroundColour
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
);
196 m_foregroundColour
= parent
->GetForegroundColour();
197 m_windowStyle
= style
;
201 if (parent
) parent
->AddChild(this);
203 Widget parentWidget
= (Widget
) parent
->GetClientWidget();
205 Widget toolbar
= XtVaCreateManagedWidget("toolbar",
206 xmBulletinBoardWidgetClass
, (Widget
) parentWidget
,
209 XmNresizePolicy
, XmRESIZE_NONE
,
212 Widget toolbar = XtVaCreateManagedWidget("toolbar",
213 xmFormWidgetClass, (Widget) m_clientWidget,
214 XmNtraversalOn, False,
215 XmNhorizontalSpacing, 0,
216 XmNverticalSpacing, 0,
224 m_mainWidget
= (WXWidget
) toolbar
;
226 m_font
= parent
->GetFont();
229 SetCanAddEventHandler(TRUE
);
230 AttachWidget (parent
, m_mainWidget
, (WXWidget
) NULL
, pos
.x
, pos
.y
, size
.x
, size
.y
);
232 ChangeBackgroundColour();
237 wxToolBar::~wxToolBar()
239 delete wxTheToolBarTimer
;
240 wxTheToolBarTimer
= NULL
;
243 bool wxToolBar::Realize()
245 if ( m_tools
.GetCount() == 0 )
252 const int separatorSize
= GetToolSeparation(); // 8;
253 wxSize margins
= GetToolMargins();
254 wxSize packing
= GetToolPacking();
255 int marginX
= margins
.x
;
256 int marginY
= margins
.y
;
258 int currentX
= marginX
;
259 int currentY
= marginY
;
261 int buttonHeight
= 0;
263 int currentSpacing
= 0;
266 Pixmap pixmap
, insensPixmap
;
269 wxToolBarToolsList::Node
*node
= m_tools
.GetFirst();
272 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->GetData();
274 switch ( tool
->GetStyle() )
276 case wxTOOL_STYLE_CONTROL
:
277 wxControl
* control
= tool
->GetControl();
278 wxSize sz
= control
->GetSize();
279 wxSize pos
= control
->GetPosition();
280 control
->Move(currentX
, pos
.y
);
281 currentX
+= sz
.x
+ packing
.x
;
285 case wxTOOL_STYLE_SEPARATOR
:
286 currentX
+= separatorSize
;
289 case wxTOOL_STYLE_BUTTON
:
292 if ( tool
->CanBeToggled() )
294 button
= XtVaCreateWidget("toggleButton",
295 xmToggleButtonWidgetClass
, (Widget
) m_mainWidget
,
296 XmNx
, currentX
, XmNy
, currentY
,
297 XmNindicatorOn
, False
,
298 XmNshadowThickness
, 2,
303 XmNmultiClick
, XmMULTICLICK_KEEP
,
304 XmNlabelType
, XmPIXMAP
,
306 XtAddCallback ((Widget
) button
, XmNvalueChangedCallback
, (XtCallbackProc
) wxToolButtonCallback
,
309 XtVaSetValues ((Widget
) button
,
310 XmNselectColor
, m_backgroundColour
.AllocColour(XtDisplay((Widget
) button
)),
315 button
= XtVaCreateWidget("button",
316 xmPushButtonWidgetClass
, (Widget
) m_mainWidget
,
317 XmNx
, currentX
, XmNy
, currentY
,
318 XmNpushButtonEnabled
, True
,
319 XmNmultiClick
, XmMULTICLICK_KEEP
,
320 XmNlabelType
, XmPIXMAP
,
322 XtAddCallback (button
,
323 XmNactivateCallback
, (XtCallbackProc
) wxToolButtonCallback
,
327 DoChangeBackgroundColour((WXWidget
) button
, m_backgroundColour
, TRUE
);
329 tool
->SetWidget(button
);
331 // For each button, if there is a mask, we must create
332 // a new wxBitmap that has the correct background colour
333 // for the button. Otherwise the background will just be
334 // e.g. black if a transparent XPM has been loaded.
335 bmp
= tool
->GetBitmap1();
339 XtVaGetValues(button
, XmNbackground
, &backgroundPixel
,
343 col
.SetPixel(backgroundPixel
);
345 bmp
= wxCreateMaskedBitmap(bmp
, col
);
347 tool
->SetBitmap1(bmp
);
350 // Create a selected/toggled bitmap. If there isn't a 2nd
351 // bitmap, we need to create it (with a darker, selected
354 if ( tool
->CanBeToggled() )
355 XtVaGetValues(button
, XmNselectColor
, &backgroundPixel
,
358 XtVaGetValues(button
, XmNarmColor
, &backgroundPixel
,
362 col
.SetPixel(backgroundPixel
);
364 if (tool
->GetBitmap2().Ok() && tool
->GetBitmap2().GetMask())
367 wxBitmap newBitmap
= wxCreateMaskedBitmap(tool
->GetBitmap2(), col
);
368 tool
->SetBitmap2(newBitmap
);
372 // Use unselected bitmap
375 wxBitmap newBitmap
= wxCreateMaskedBitmap(bmp
, col
);
376 tool
->SetBitmap2(newBitmap
);
379 tool
->SetBitmap2(bmp
);
382 pixmap
= (Pixmap
) bmp
.GetPixmap();
383 insensPixmap
= (Pixmap
) bmp
.GetInsensPixmap();
385 if (tool
->CanBeToggled())
388 Pixmap pixmap2
= (Pixmap
) 0;
389 Pixmap insensPixmap2
= (Pixmap
) 0;
391 // If there's a bitmap for the toggled state, use it,
392 // otherwise generate one.
393 if (tool
->GetBitmap2().Ok())
395 wxBitmap bmp2
= tool
->GetBitmap2();
396 pixmap2
= (Pixmap
) bmp2
.GetPixmap();
397 insensPixmap2
= (Pixmap
) bmp2
.GetInsensPixmap();
401 pixmap2
= (Pixmap
) bmp
.GetArmPixmap(button
);
402 insensPixmap2
= XCreateInsensitivePixmap((Display
*) wxGetDisplay(), pixmap2
);
405 tool
->SetPixmap(pixmap2
);
407 XtVaSetValues (button
,
408 XmNfillOnSelect
, True
,
409 XmNlabelPixmap
, pixmap
,
410 XmNselectPixmap
, pixmap2
,
411 XmNlabelInsensitivePixmap
, insensPixmap
,
412 XmNselectInsensitivePixmap
, insensPixmap2
,
413 XmNlabelType
, XmPIXMAP
,
418 Pixmap pixmap2
= (Pixmap
) 0;
420 // If there's a bitmap for the armed state, use it,
421 // otherwise generate one.
422 if (tool
->GetBitmap2().Ok())
424 pixmap2
= (Pixmap
) tool
->GetBitmap2().GetPixmap();
428 pixmap2
= (Pixmap
) bmp
.GetArmPixmap(button
);
432 tool
->SetPixmap(pixmap2
);
435 XtVaSetValues(button
,
436 XmNlabelPixmap
, pixmap
,
437 XmNlabelInsensitivePixmap
, insensPixmap
,
438 XmNarmPixmap
, pixmap2
,
442 XtManageChild(button
);
445 Dimension width
, height
;
446 XtVaGetValues(button
,
450 currentX
+= width
+ packing
.x
;
451 buttonHeight
= wxMax(buttonHeight
, height
);
454 XtAddEventHandler (button
, EnterWindowMask
| LeaveWindowMask
,
455 False
, wxToolButtonPopupCallback
, (XtPointer
) this);
461 node
= node
->GetNext();
464 SetSize(-1, -1, currentX
, buttonHeight
+ 2*marginY
);
469 wxToolBarToolBase
*wxToolBar::FindToolForPosition(wxCoord
WXUNUSED(x
),
470 wxCoord
WXUNUSED(y
)) const
472 wxFAIL_MSG( _T("TODO") );
474 return (wxToolBarToolBase
*)NULL
;
477 bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos
), wxToolBarToolBase
*tool
)
484 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos
), wxToolBarToolBase
*tool
)
491 void wxToolBar::DoEnableTool(wxToolBarToolBase
*toolBase
, bool enable
)
493 wxToolBarTool
*tool
= (wxToolBarTool
*)toolBase
;
495 XtSetSensitive(tool
->GetButtonWidget(), (Boolean
) enable
);
498 void wxToolBar::DoToggleTool(wxToolBarToolBase
*toolBase
, bool toggle
)
500 wxToolBarTool
*tool
= (wxToolBarTool
*)toolBase
;
502 XmToggleButtonSetState(tool
->GetButtonWidget(), (Boolean
) toggle
, False
);
505 void wxToolBar::DoSetToggle(wxToolBarToolBase
* WXUNUSED(tool
),
506 bool WXUNUSED(toggle
))
511 // ----------------------------------------------------------------------------
513 // ----------------------------------------------------------------------------
515 wxToolBarToolBase
*wxToolBar::FindToolByWidget(WXWidget w
) const
517 wxToolBarToolsList::Node
* node
= m_tools
.GetFirst();
520 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->GetData();
521 if ( tool
->GetButtonWidget() == w
)
526 node
= node
->GetNext();
529 return (wxToolBarToolBase
*)NULL
;
532 static void wxToolButtonCallback(Widget w
,
533 XtPointer clientData
,
534 XtPointer
WXUNUSED(ptr
))
536 wxToolBar
*toolBar
= (wxToolBar
*) clientData
;
537 wxToolBarToolBase
*tool
= toolBar
->FindToolByWidget((WXWidget
) w
);
541 if ( tool
->CanBeToggled() )
544 if ( !toolBar
->OnLeftClick(tool
->GetId(), tool
->IsToggled()) )
552 static void wxToolButtonPopupCallback(Widget w
,
553 XtPointer client_data
,
555 Boolean
*WXUNUSED(continue_to_dispatch
))
557 // TODO: retrieve delay before popping up tooltip from wxSystemSettings.
558 static const int delayMilli
= 800;
560 wxToolBar
* toolBar
= (wxToolBar
*) client_data
;
561 wxToolBarToolBase
*tool
= toolBar
->FindToolByWidget((WXWidget
) w
);
566 wxString tooltip
= tool
->GetShortHelp();
570 if (!wxTheToolBarTimer
)
571 wxTheToolBarTimer
= new wxToolBarTimer
;
573 wxToolBarTimer::buttonWidget
= w
;
574 wxToolBarTimer::helpString
= tooltip
;
576 /************************************************************/
577 /* Popup help label */
578 /************************************************************/
579 if (event
->type
== EnterNotify
)
581 if (wxToolBarTimer::help_popup
!= (Widget
) 0)
583 XtDestroyWidget (wxToolBarTimer::help_popup
);
584 XtPopdown (wxToolBarTimer::help_popup
);
586 wxToolBarTimer::help_popup
= (Widget
) 0;
589 wxTheToolBarTimer
->Start(delayMilli
, TRUE
);
592 /************************************************************/
593 /* Popdown help label */
594 /************************************************************/
595 else if (event
->type
== LeaveNotify
)
597 if (wxTheToolBarTimer
)
598 wxTheToolBarTimer
->Stop();
599 if (wxToolBarTimer::help_popup
!= (Widget
) 0)
601 XtDestroyWidget (wxToolBarTimer::help_popup
);
602 XtPopdown (wxToolBarTimer::help_popup
);
604 wxToolBarTimer::help_popup
= (Widget
) 0;
608 void wxToolBarTimer::Notify()
612 /************************************************************/
613 /* Create shell without window decorations */
614 /************************************************************/
615 help_popup
= XtVaCreatePopupShell ("shell",
616 overrideShellWidgetClass
, (Widget
) wxTheApp
->GetTopLevelWidget(),
619 /************************************************************/
620 /* Get absolute position on display of toolbar button */
621 /************************************************************/
622 XtTranslateCoords (buttonWidget
,
627 // Move the tooltip more or less above the button
628 int yOffset
= 20; // TODO: What should be really?
630 if (y
< yOffset
) y
= 0;
632 /************************************************************/
633 /* Set the position of the help popup */
634 /************************************************************/
635 XtVaSetValues (help_popup
,
640 /************************************************************/
641 /* Create help label */
642 /************************************************************/
643 XmString text
= XmStringCreateSimple ((char*) (const char*) helpString
);
644 XtVaCreateManagedWidget ("help_label",
645 xmLabelWidgetClass
, help_popup
,
646 XmNlabelString
, text
,
648 XmNforeground
, XtRString
, "black",
651 XmNbackground
, XtRString
, "LightGoldenrod",
652 strlen("LightGoldenrod")+1,
656 /************************************************************/
657 /* Popup help label */
658 /************************************************************/
659 XtPopup (help_popup
, XtGrabNone
);