1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "toolbar.h"
19 #include "wx/motif/toolbar.h"
22 #include <Xm/PushBG.h>
25 #include <Xm/ToggleB.h>
26 #include <Xm/ToggleBG.h>
29 #include "wx/motif/private.h"
31 #if !USE_SHARED_LIBRARY
32 IMPLEMENT_DYNAMIC_CLASS(wxToolBar
, wxToolBarBase
)
34 BEGIN_EVENT_TABLE(wxToolBar
, wxToolBarBase
)
38 static void wxToolButtonCallback (Widget w
, XtPointer clientData
,
40 static void wxToolButtonPopupCallback (Widget w
, XtPointer client_data
,
41 XEvent
*event
, Boolean
*continue_to_dispatch
);
43 class wxToolBarTimer
: public wxTimer
47 virtual void Notify();
49 static Widget help_popup
;
50 static Widget buttonWidget
;
51 static wxString helpString
;
54 static wxToolBarTimer
* wxTheToolBarTimer
= (wxToolBarTimer
*) NULL
;
56 Widget
wxToolBarTimer::help_popup
= (Widget
) 0;
57 Widget
wxToolBarTimer::buttonWidget
= (Widget
) 0;
58 wxString
wxToolBarTimer::helpString
= "";
60 wxToolBar::wxToolBar():
61 m_widgets(wxKEY_INTEGER
)
69 bool wxToolBar::Create(wxWindow
*parent
, wxWindowID id
, const wxPoint
& pos
, const wxSize
& size
,
70 long style
, const wxString
& name
)
78 m_backgroundColour
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
);
79 m_foregroundColour
= parent
->GetForegroundColour();
80 m_windowStyle
= style
;
84 if (parent
) parent
->AddChild(this);
86 Widget parentWidget
= (Widget
) parent
->GetClientWidget();
88 Widget toolbar
= XtVaCreateManagedWidget("toolbar",
89 xmFormWidgetClass
, parentWidget
,
90 XmNtraversalOn
, False
,
91 XmNhorizontalSpacing
, 0,
92 XmNverticalSpacing
, 0,
99 m_mainWidget
= (WXWidget
) toolbar
;
101 SetCanAddEventHandler(TRUE
);
102 AttachWidget (parent
, m_mainWidget
, (WXWidget
) NULL
, pos
.x
, pos
.y
, size
.x
, size
.y
);
104 SetFont(* parent
->GetFont());
105 ChangeBackgroundColour();
110 wxToolBar::~wxToolBar()
112 delete wxTheToolBarTimer
;
113 wxTheToolBarTimer
= NULL
;
118 bool wxToolBar::CreateTools()
120 if (m_tools
.Number() == 0)
124 const int separatorSize
= GetToolSeparation(); // 8;
126 int currentSpacing
= 0;
129 Widget prevButton
= (Widget
) 0;
130 wxNode
* node
= m_tools
.First();
133 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
135 if (tool
->m_toolStyle
== wxTOOL_STYLE_SEPARATOR
)
136 currentSpacing
= separatorSize
;
137 else if (tool
->m_bitmap1
.Ok())
139 Widget button
= (Widget
) 0;
141 if (tool
->m_isToggle
)
143 button
= XtVaCreateManagedWidget("toggleButton",
144 xmToggleButtonWidgetClass
, (Widget
) m_mainWidget
,
145 XmNleftAttachment
, (prevButton
== (Widget
) 0) ? XmATTACH_FORM
: XmATTACH_WIDGET
,
146 XmNleftWidget
, (prevButton
== (Widget
) 0) ? NULL
: prevButton
,
147 XmNleftOffset
, currentSpacing
,
148 XmNtopAttachment
, XmATTACH_FORM
,
149 // XmNpushButtonEnabled, True,
150 XmNmultiClick
, XmMULTICLICK_KEEP
,
151 XmNlabelType
, XmPIXMAP
,
153 XtAddCallback ((Widget
) button
, XmNvalueChangedCallback
, (XtCallbackProc
) wxToolButtonCallback
,
158 button
= XtVaCreateManagedWidget("button",
159 xmPushButtonWidgetClass
, (Widget
) m_mainWidget
,
160 XmNleftAttachment
, (prevButton
== (Widget
) 0) ? XmATTACH_FORM
: XmATTACH_WIDGET
,
161 XmNleftWidget
, (prevButton
== (Widget
) 0) ? NULL
: prevButton
,
162 XmNleftOffset
, currentSpacing
,
163 XmNtopAttachment
, XmATTACH_FORM
,
164 XmNpushButtonEnabled
, True
,
165 XmNmultiClick
, XmMULTICLICK_KEEP
,
166 XmNlabelType
, XmPIXMAP
,
168 XtAddCallback (button
,
169 XmNactivateCallback
, (XtCallbackProc
) wxToolButtonCallback
,
173 // For each button, if there is a mask, we must create
174 // a new wxBitmap that has the correct background colour
175 // for the button. Otherwise the background will just be
176 // e.g. black if a transparent XPM has been loaded.
177 wxBitmap originalBitmap
= tool
->m_bitmap1
;
179 if (tool
->m_bitmap1
.GetMask())
182 XtVaGetValues(button
, XmNbackground
, &backgroundPixel
,
187 col
.SetPixel(backgroundPixel
);
189 wxBitmap newBitmap
= wxCreateMaskedBitmap(tool
->m_bitmap1
, col
);
191 tool
->m_bitmap1
= newBitmap
;
194 // Create a selected/toggled bitmap. If there isn't a m_bitmap2,
195 // we need to create it (with a darker, selected background)
197 if (tool
->m_isToggle
)
198 XtVaGetValues(button
, XmNselectColor
, &backgroundPixel
,
201 XtVaGetValues(button
, XmNarmColor
, &backgroundPixel
,
205 col
.SetPixel(backgroundPixel
);
207 if (tool
->m_bitmap2
.Ok() && tool
->m_bitmap2
.GetMask())
210 wxBitmap newBitmap
= wxCreateMaskedBitmap(tool
->m_bitmap2
, col
);
211 tool
->m_bitmap2
= newBitmap
;
215 // Use unselected bitmap
216 if (originalBitmap
.GetMask())
218 wxBitmap newBitmap
= wxCreateMaskedBitmap(originalBitmap
, col
);
219 tool
->m_bitmap2
= newBitmap
;
222 tool
->m_bitmap2
= tool
->m_bitmap1
;
225 Pixmap pixmap
= (Pixmap
) tool
->m_bitmap1
.GetPixmap();
226 Pixmap insensPixmap
= (Pixmap
) tool
->m_bitmap1
.GetInsensPixmap();
228 if (tool
->m_isToggle
)
231 Pixmap pixmap2
= (Pixmap
) 0;
232 Pixmap insensPixmap2
= (Pixmap
) 0;
234 // If there's a bitmap for the toggled state, use it,
235 // otherwise generate one.
236 if (tool
->m_bitmap2
.Ok())
238 pixmap2
= (Pixmap
) tool
->m_bitmap2
.GetPixmap();
239 insensPixmap2
= (Pixmap
) tool
->m_bitmap2
.GetInsensPixmap();
243 pixmap2
= (Pixmap
) tool
->m_bitmap1
.GetArmPixmap(button
);
244 insensPixmap2
= XCreateInsensitivePixmap((Display
*) wxGetDisplay(), pixmap2
);
245 m_pixmaps
.Append((wxObject
*) insensPixmap2
); // Store for later deletion
247 XtVaSetValues (button
,
248 XmNindicatorOn
, False
,
249 XmNshadowThickness
, 2,
250 // XmNborderWidth, 0,
254 XmNfillOnSelect
, True
,
255 XmNlabelPixmap
, pixmap
,
256 XmNselectPixmap
, pixmap2
,
257 XmNlabelInsensitivePixmap
, insensPixmap
,
258 XmNselectInsensitivePixmap
, insensPixmap2
,
259 XmNlabelType
, XmPIXMAP
,
264 Pixmap pixmap2
= (Pixmap
) 0;
266 // If there's a bitmap for the armed state, use it,
267 // otherwise generate one.
268 if (tool
->m_bitmap2
.Ok())
270 pixmap2
= (Pixmap
) tool
->m_bitmap2
.GetPixmap();
274 pixmap2
= (Pixmap
) tool
->m_bitmap1
.GetArmPixmap(button
);
278 XtVaSetValues(button
,
279 XmNlabelPixmap
, pixmap
,
280 XmNlabelInsensitivePixmap
, insensPixmap
,
281 XmNarmPixmap
, pixmap2
,
285 XtAddEventHandler (button
, EnterWindowMask
| LeaveWindowMask
,
286 False
, wxToolButtonPopupCallback
, (XtPointer
) this);
287 m_widgets
.Append(tool
->m_index
, (wxObject
*) button
);
298 void wxToolBar::SetToolBitmapSize(const wxSize
& size
)
300 m_defaultWidth
= size
.x
; m_defaultHeight
= size
.y
;
304 wxSize
wxToolBar::GetMaxSize() const
310 // The button size is bigger than the bitmap size
311 wxSize
wxToolBar::GetToolSize() const
314 return wxSize(m_defaultWidth
+ 8, m_defaultHeight
+ 7);
317 void wxToolBar::EnableTool(int toolIndex
, bool enable
)
319 wxNode
*node
= m_tools
.Find((long)toolIndex
);
322 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
323 tool
->m_enabled
= enable
;
325 WXWidget widget
= FindWidgetForIndex(tool
->m_index
);
326 if (widget
== (WXWidget
) 0)
329 XtSetSensitive((Widget
) widget
, (Boolean
) enable
);
333 void wxToolBar::ToggleTool(int toolIndex
, bool toggle
)
335 wxNode
*node
= m_tools
.Find((long)toolIndex
);
338 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
339 if (tool
->m_isToggle
)
341 tool
->m_toggleState
= toggle
;
343 WXWidget widget
= FindWidgetForIndex(tool
->m_index
);
344 if (widget
== (WXWidget
) 0)
347 XmToggleButtonSetState((Widget
) widget
, (Boolean
) toggle
, False
);
352 void wxToolBar::ClearTools()
354 wxNode
* node
= m_widgets
.First();
357 Widget button
= (Widget
) node
->Data();
358 XtDestroyWidget(button
);
364 wxToolBarBase::ClearTools();
367 void wxToolBar::DestroyPixmaps()
369 wxNode
* node
= m_pixmaps
.First();
372 Pixmap pixmap
= (Pixmap
) node
->Data();
373 XmDestroyPixmap (DefaultScreenOfDisplay ((Display
*) GetXDisplay()), pixmap
);
379 // If pushedBitmap is NULL, a reversed version of bitmap is
380 // created and used as the pushed/toggled image.
381 // If toggle is TRUE, the button toggles between the two states.
383 wxToolBarTool
*wxToolBar::AddTool(int index
, const wxBitmap
& bitmap
, const wxBitmap
& pushedBitmap
,
384 bool toggle
, long xPos
, long yPos
, wxObject
*clientData
, const wxString
& helpString1
, const wxString
& helpString2
)
386 wxToolBarTool
*tool
= new wxToolBarTool(index
, bitmap
, (wxBitmap
*)NULL
, toggle
, xPos
, yPos
, helpString1
, helpString2
);
387 tool
->m_clientData
= clientData
;
392 tool
->m_x
= m_xMargin
;
397 tool
->m_y
= m_yMargin
;
399 tool
->SetSize(GetDefaultButtonWidth(), GetDefaultButtonHeight());
401 m_tools
.Append((long)index
, tool
);
405 int wxToolBar::FindIndexForWidget(WXWidget w
)
407 wxNode
* node
= m_widgets
.First();
410 WXWidget widget
= (WXWidget
) node
->Data();
412 return (int) node
->key
.integer
;
418 WXWidget
wxToolBar::FindWidgetForIndex(int index
)
420 wxNode
* node
= m_widgets
.Find((long) index
);
424 return (WXWidget
) node
->Data();
427 void wxToolButtonCallback (Widget w
, XtPointer clientData
,
430 wxToolBar
*toolBar
= (wxToolBar
*) clientData
;
431 int index
= toolBar
->FindIndexForWidget((WXWidget
) w
);
435 wxNode
*node
= toolBar
->GetTools().Find((long)index
);
438 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
439 if (tool
->m_isToggle
)
440 tool
->m_toggleState
= toolBar
->GetToolState(index
);
442 (void) toolBar
->OnLeftClick(index
, tool
->m_toggleState
);
448 static void wxToolButtonPopupCallback (Widget w
, XtPointer client_data
,
449 XEvent
*event
, Boolean
*continue_to_dispatch
)
451 // TODO: retrieve delay before popping up tooltip from wxSystemSettings.
452 int delayMilli
= 800;
453 wxToolBar
* toolBar
= (wxToolBar
*) client_data
;
455 int index
= toolBar
->FindIndexForWidget((WXWidget
) w
);
459 wxNode
*node
= toolBar
->GetTools().Find((long)index
);
462 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->Data();
463 wxString
str(toolBar
->GetToolShortHelp(index
));
464 if (str
.IsNull() || str
== "")
467 if (!wxTheToolBarTimer
)
468 wxTheToolBarTimer
= new wxToolBarTimer
;
470 wxToolBarTimer::buttonWidget
= w
;
471 wxToolBarTimer::helpString
= str
;
474 /************************************************************/
475 /* Popup help label */
476 /************************************************************/
477 if (event
->type
== EnterNotify
)
479 if (wxToolBarTimer::help_popup
!= (Widget
) 0)
481 XtDestroyWidget (wxToolBarTimer::help_popup
);
482 XtPopdown (wxToolBarTimer::help_popup
);
484 wxToolBarTimer::help_popup
= (Widget
) 0;
487 wxTheToolBarTimer
->Start(delayMilli
, TRUE
);
490 /************************************************************/
491 /* Popdown help label */
492 /************************************************************/
493 else if (event
->type
== LeaveNotify
)
495 if (wxTheToolBarTimer
)
496 wxTheToolBarTimer
->Stop();
497 if (wxToolBarTimer::help_popup
!= (Widget
) 0)
499 XtDestroyWidget (wxToolBarTimer::help_popup
);
500 XtPopdown (wxToolBarTimer::help_popup
);
502 wxToolBarTimer::help_popup
= (Widget
) 0;
507 void wxToolBarTimer::Notify()
511 /************************************************************/
512 /* Create shell without window decorations */
513 /************************************************************/
514 help_popup
= XtVaCreatePopupShell ("shell",
515 overrideShellWidgetClass
, (Widget
) wxTheApp
->GetTopLevelWidget(),
518 /************************************************************/
519 /* Get absolute position on display of toolbar button */
520 /************************************************************/
521 XtTranslateCoords (buttonWidget
,
526 // Move the tooltip more or less above the button
527 int yOffset
= 20; // TODO: What should be really?
529 if (y
< yOffset
) y
= 0;
531 /************************************************************/
532 /* Set the position of the help popup */
533 /************************************************************/
534 XtVaSetValues (help_popup
,
539 /************************************************************/
540 /* Create help label */
541 /************************************************************/
542 XmString text
= XmStringCreateSimple ((char*) (const char*) helpString
);
543 XtVaCreateManagedWidget ("help_label",
544 xmLabelWidgetClass
, help_popup
,
545 XmNlabelString
, text
,
547 XmNforeground
, XtRString
, "black",
550 XmNbackground
, XtRString
, "LightGoldenrod",
551 strlen("LightGoldenrod")+1,
555 /************************************************************/
556 /* Popup help label */
557 /************************************************************/
558 XtPopup (help_popup
, XtGrabNone
);