1 /////////////////////////////////////////////////////////////////////////////
2 // Name: x11/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 #pragma message enable nosimpint
42 #include "wx/x11/private.h"
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 IMPLEMENT_DYNAMIC_CLASS(wxToolBar
, wxToolBarBase
)
50 // TODO: a decent generic toolbar implementation that
51 // we can put in src/generic
54 // ----------------------------------------------------------------------------
56 // ----------------------------------------------------------------------------
58 static void wxToolButtonCallback (Widget w
, XtPointer clientData
,
60 static void wxToolButtonPopupCallback (Widget w
, XtPointer client_data
,
61 XEvent
*event
, Boolean
*continue_to_dispatch
);
63 // ----------------------------------------------------------------------------
65 // ----------------------------------------------------------------------------
67 class wxToolBarTimer
: public wxTimer
70 virtual void Notify();
72 static Widget help_popup
;
73 static Widget buttonWidget
;
74 static wxString helpString
;
77 class wxToolBarTool
: public wxToolBarToolBase
80 wxToolBarTool(wxToolBar
*tbar
,
82 const wxBitmap
& bitmap1
,
83 const wxBitmap
& bitmap2
,
86 const wxString
& shortHelpString
,
87 const wxString
& longHelpString
)
88 : wxToolBarToolBase(tbar
, id
, bitmap1
, bitmap2
, toggle
,
89 clientData
, shortHelpString
, longHelpString
)
94 wxToolBarTool(wxToolBar
*tbar
, wxControl
*control
)
95 : wxToolBarToolBase(tbar
, control
)
100 virtual ~wxToolBarTool();
103 void SetWidget(Widget widget
) { m_widget
= widget
; }
104 Widget
GetButtonWidget() const { return m_widget
; }
106 void SetPixmap(Pixmap pixmap
) { m_pixmap
= pixmap
; }
107 Pixmap
GetPixmap() const { return m_pixmap
; }
116 // ----------------------------------------------------------------------------
118 // ----------------------------------------------------------------------------
120 static wxToolBarTimer
* wxTheToolBarTimer
= (wxToolBarTimer
*) NULL
;
122 Widget
wxToolBarTimer::help_popup
= (Widget
) 0;
123 Widget
wxToolBarTimer::buttonWidget
= (Widget
) 0;
124 wxString
wxToolBarTimer::helpString
;
126 // ============================================================================
128 // ============================================================================
130 // ----------------------------------------------------------------------------
132 // ----------------------------------------------------------------------------
134 wxToolBarToolBase
*wxToolBar::CreateTool(int id
,
135 const wxBitmap
& bitmap1
,
136 const wxBitmap
& bitmap2
,
138 wxObject
*clientData
,
139 const wxString
& shortHelpString
,
140 const wxString
& longHelpString
)
142 return new wxToolBarTool(this, id
, bitmap1
, bitmap2
, toggle
,
143 clientData
, shortHelpString
, longHelpString
);
146 wxToolBarToolBase
*wxToolBar::CreateTool(wxControl
*control
)
148 return new wxToolBarTool(this, control
);
151 void wxToolBarTool::Init()
153 m_widget
= (Widget
)0;
154 m_pixmap
= (Pixmap
)0;
157 wxToolBarTool::~wxToolBarTool()
160 XtDestroyWidget(m_widget
);
162 XmDestroyPixmap(DefaultScreenOfDisplay((Display
*)wxGetDisplay()),
166 // ----------------------------------------------------------------------------
167 // wxToolBar construction
168 // ----------------------------------------------------------------------------
170 void wxToolBar::Init()
175 m_defaultHeight
= 22;
177 m_toolSeparation
= 8;
184 bool wxToolBar::Create(wxWindow
*parent
,
189 const wxString
& name
)
196 m_backgroundColour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
197 m_foregroundColour
= parent
->GetForegroundColour();
198 m_windowStyle
= style
;
202 if (parent
) parent
->AddChild(this);
204 Widget parentWidget
= (Widget
) parent
->GetClientWidget();
206 Widget toolbar
= XtVaCreateManagedWidget("toolbar",
207 xmBulletinBoardWidgetClass
, (Widget
) parentWidget
,
210 XmNresizePolicy
, XmRESIZE_NONE
,
213 Widget toolbar = XtVaCreateManagedWidget("toolbar",
214 xmFormWidgetClass, (Widget) m_clientWidget,
215 XmNtraversalOn, False,
216 XmNhorizontalSpacing, 0,
217 XmNverticalSpacing, 0,
225 m_mainWidget
= (WXWidget
) toolbar
;
227 m_font
= parent
->GetFont();
230 SetCanAddEventHandler(TRUE
);
231 AttachWidget (parent
, m_mainWidget
, (WXWidget
) NULL
, pos
.x
, pos
.y
, size
.x
, size
.y
);
233 ChangeBackgroundColour();
238 wxToolBar::~wxToolBar()
240 delete wxTheToolBarTimer
;
241 wxTheToolBarTimer
= NULL
;
244 bool wxToolBar::Realize()
246 if ( m_tools
.GetCount() == 0 )
253 const int separatorSize
= GetToolSeparation(); // 8;
254 wxSize margins
= GetToolMargins();
255 int packing
= GetToolPacking();
256 int marginX
= margins
.x
;
257 int marginY
= margins
.y
;
259 int currentX
= marginX
;
260 int currentY
= marginY
;
262 int buttonHeight
= 0;
264 int currentSpacing
= 0;
267 Pixmap pixmap
, insensPixmap
;
270 wxToolBarToolsList::Node
*node
= m_tools
.GetFirst();
273 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->GetData();
275 switch ( tool
->GetStyle() )
277 case wxTOOL_STYLE_CONTROL
:
279 wxControl
* control
= tool
->GetControl();
280 wxSize sz
= control
->GetSize();
281 wxPoint pos
= control
->GetPosition();
282 control
->Move(currentX
, pos
.y
);
283 currentX
+= sz
.x
+ packing
;
287 case wxTOOL_STYLE_SEPARATOR
:
288 currentX
+= separatorSize
;
291 case wxTOOL_STYLE_BUTTON
:
294 if ( tool
->CanBeToggled() )
296 button
= XtVaCreateWidget("toggleButton",
297 xmToggleButtonWidgetClass
, (Widget
) m_mainWidget
,
298 XmNx
, currentX
, XmNy
, currentY
,
299 XmNindicatorOn
, False
,
300 XmNshadowThickness
, 2,
305 XmNmultiClick
, XmMULTICLICK_KEEP
,
306 XmNlabelType
, XmPIXMAP
,
308 XtAddCallback ((Widget
) button
, XmNvalueChangedCallback
, (XtCallbackProc
) wxToolButtonCallback
,
311 XtVaSetValues ((Widget
) button
,
312 XmNselectColor
, m_backgroundColour
.AllocColour(XtDisplay((Widget
) button
)),
317 button
= XtVaCreateWidget("button",
318 xmPushButtonWidgetClass
, (Widget
) m_mainWidget
,
319 XmNx
, currentX
, XmNy
, currentY
,
320 XmNpushButtonEnabled
, True
,
321 XmNmultiClick
, XmMULTICLICK_KEEP
,
322 XmNlabelType
, XmPIXMAP
,
324 XtAddCallback (button
,
325 XmNactivateCallback
, (XtCallbackProc
) wxToolButtonCallback
,
329 DoChangeBackgroundColour((WXWidget
) button
, m_backgroundColour
, TRUE
);
331 tool
->SetWidget(button
);
333 // For each button, if there is a mask, we must create
334 // a new wxBitmap that has the correct background colour
335 // for the button. Otherwise the background will just be
336 // e.g. black if a transparent XPM has been loaded.
337 bmp
= tool
->GetBitmap1();
341 XtVaGetValues(button
, XmNbackground
, &backgroundPixel
,
345 col
.SetPixel(backgroundPixel
);
347 bmp
= wxCreateMaskedBitmap(bmp
, col
);
349 tool
->SetBitmap1(bmp
);
352 // Create a selected/toggled bitmap. If there isn't a 2nd
353 // bitmap, we need to create it (with a darker, selected
356 if ( tool
->CanBeToggled() )
357 XtVaGetValues(button
, XmNselectColor
, &backgroundPixel
,
360 XtVaGetValues(button
, XmNarmColor
, &backgroundPixel
,
364 col
.SetPixel(backgroundPixel
);
366 if (tool
->GetBitmap2().Ok() && tool
->GetBitmap2().GetMask())
369 wxBitmap newBitmap
= wxCreateMaskedBitmap(tool
->GetBitmap2(), col
);
370 tool
->SetBitmap2(newBitmap
);
374 // Use unselected bitmap
377 wxBitmap newBitmap
= wxCreateMaskedBitmap(bmp
, col
);
378 tool
->SetBitmap2(newBitmap
);
381 tool
->SetBitmap2(bmp
);
384 pixmap
= (Pixmap
) bmp
.GetPixmap();
385 insensPixmap
= (Pixmap
) bmp
.GetInsensPixmap();
387 if (tool
->CanBeToggled())
390 Pixmap pixmap2
= (Pixmap
) 0;
391 Pixmap insensPixmap2
= (Pixmap
) 0;
393 // If there's a bitmap for the toggled state, use it,
394 // otherwise generate one.
395 if (tool
->GetBitmap2().Ok())
397 wxBitmap bmp2
= tool
->GetBitmap2();
398 pixmap2
= (Pixmap
) bmp2
.GetPixmap();
399 insensPixmap2
= (Pixmap
) bmp2
.GetInsensPixmap();
403 pixmap2
= (Pixmap
) bmp
.GetArmPixmap(button
);
404 insensPixmap2
= XCreateInsensitivePixmap((Display
*) wxGetDisplay(), pixmap2
);
407 tool
->SetPixmap(pixmap2
);
409 XtVaSetValues (button
,
410 XmNfillOnSelect
, True
,
411 XmNlabelPixmap
, pixmap
,
412 XmNselectPixmap
, pixmap2
,
413 XmNlabelInsensitivePixmap
, insensPixmap
,
414 XmNselectInsensitivePixmap
, insensPixmap2
,
415 XmNlabelType
, XmPIXMAP
,
420 Pixmap pixmap2
= (Pixmap
) 0;
422 // If there's a bitmap for the armed state, use it,
423 // otherwise generate one.
424 if (tool
->GetBitmap2().Ok())
426 pixmap2
= (Pixmap
) tool
->GetBitmap2().GetPixmap();
430 pixmap2
= (Pixmap
) bmp
.GetArmPixmap(button
);
434 tool
->SetPixmap(pixmap2
);
437 XtVaSetValues(button
,
438 XmNlabelPixmap
, pixmap
,
439 XmNlabelInsensitivePixmap
, insensPixmap
,
440 XmNarmPixmap
, pixmap2
,
444 XtManageChild(button
);
447 Dimension width
, height
;
448 XtVaGetValues(button
,
452 currentX
+= width
+ packing
;
453 buttonHeight
= wxMax(buttonHeight
, height
);
456 XtAddEventHandler (button
, EnterWindowMask
| LeaveWindowMask
,
457 False
, wxToolButtonPopupCallback
, (XtPointer
) this);
463 node
= node
->GetNext();
466 SetSize(-1, -1, currentX
, buttonHeight
+ 2*marginY
);
471 wxToolBarToolBase
*wxToolBar::FindToolForPosition(wxCoord
WXUNUSED(x
),
472 wxCoord
WXUNUSED(y
)) const
474 wxFAIL_MSG( _T("TODO") );
476 return (wxToolBarToolBase
*)NULL
;
479 bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos
), wxToolBarToolBase
*tool
)
486 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos
), wxToolBarToolBase
*tool
)
493 void wxToolBar::DoEnableTool(wxToolBarToolBase
*toolBase
, bool enable
)
495 wxToolBarTool
*tool
= (wxToolBarTool
*)toolBase
;
497 XtSetSensitive(tool
->GetButtonWidget(), (Boolean
) enable
);
500 void wxToolBar::DoToggleTool(wxToolBarToolBase
*toolBase
, bool toggle
)
502 wxToolBarTool
*tool
= (wxToolBarTool
*)toolBase
;
504 XmToggleButtonSetState(tool
->GetButtonWidget(), (Boolean
) toggle
, False
);
507 void wxToolBar::DoSetToggle(wxToolBarToolBase
* WXUNUSED(tool
),
508 bool WXUNUSED(toggle
))
513 // ----------------------------------------------------------------------------
515 // ----------------------------------------------------------------------------
517 wxToolBarToolBase
*wxToolBar::FindToolByWidget(WXWidget w
) const
519 wxToolBarToolsList::Node
* node
= m_tools
.GetFirst();
522 wxToolBarTool
*tool
= (wxToolBarTool
*)node
->GetData();
523 if ( tool
->GetButtonWidget() == w
)
528 node
= node
->GetNext();
531 return (wxToolBarToolBase
*)NULL
;
534 static void wxToolButtonCallback(Widget w
,
535 XtPointer clientData
,
536 XtPointer
WXUNUSED(ptr
))
538 wxToolBar
*toolBar
= (wxToolBar
*) clientData
;
539 wxToolBarToolBase
*tool
= toolBar
->FindToolByWidget((WXWidget
) w
);
543 if ( tool
->CanBeToggled() )
546 if ( !toolBar
->OnLeftClick(tool
->GetId(), tool
->IsToggled()) )
554 static void wxToolButtonPopupCallback(Widget w
,
555 XtPointer client_data
,
557 Boolean
*WXUNUSED(continue_to_dispatch
))
559 // TODO: retrieve delay before popping up tooltip from wxSystemSettings.
560 static const int delayMilli
= 800;
562 wxToolBar
* toolBar
= (wxToolBar
*) client_data
;
563 wxToolBarToolBase
*tool
= toolBar
->FindToolByWidget((WXWidget
) w
);
568 wxString tooltip
= tool
->GetShortHelp();
572 if (!wxTheToolBarTimer
)
573 wxTheToolBarTimer
= new wxToolBarTimer
;
575 wxToolBarTimer::buttonWidget
= w
;
576 wxToolBarTimer::helpString
= tooltip
;
578 /************************************************************/
579 /* Popup help label */
580 /************************************************************/
581 if (event
->type
== EnterNotify
)
583 if (wxToolBarTimer::help_popup
!= (Widget
) 0)
585 XtDestroyWidget (wxToolBarTimer::help_popup
);
586 XtPopdown (wxToolBarTimer::help_popup
);
588 wxToolBarTimer::help_popup
= (Widget
) 0;
591 wxTheToolBarTimer
->Start(delayMilli
, TRUE
);
594 /************************************************************/
595 /* Popdown help label */
596 /************************************************************/
597 else if (event
->type
== LeaveNotify
)
599 if (wxTheToolBarTimer
)
600 wxTheToolBarTimer
->Stop();
601 if (wxToolBarTimer::help_popup
!= (Widget
) 0)
603 XtDestroyWidget (wxToolBarTimer::help_popup
);
604 XtPopdown (wxToolBarTimer::help_popup
);
606 wxToolBarTimer::help_popup
= (Widget
) 0;
610 void wxToolBarTimer::Notify()
614 /************************************************************/
615 /* Create shell without window decorations */
616 /************************************************************/
617 help_popup
= XtVaCreatePopupShell ("shell",
618 overrideShellWidgetClass
, (Widget
) wxTheApp
->GetTopLevelWidget(),
621 /************************************************************/
622 /* Get absolute position on display of toolbar button */
623 /************************************************************/
624 XtTranslateCoords (buttonWidget
,
629 // Move the tooltip more or less above the button
630 int yOffset
= 20; // TODO: What should be really?
632 if (y
< yOffset
) y
= 0;
634 /************************************************************/
635 /* Set the position of the help popup */
636 /************************************************************/
637 XtVaSetValues (help_popup
,
642 /************************************************************/
643 /* Create help label */
644 /************************************************************/
645 XmString text
= XmStringCreateSimple ((char*) (const char*) helpString
);
646 XtVaCreateManagedWidget ("help_label",
647 xmLabelWidgetClass
, help_popup
,
648 XmNlabelString
, text
,
650 XmNforeground
, XtRString
, "black",
653 XmNbackground
, XtRString
, "LightGoldenrod",
654 strlen("LightGoldenrod")+1,
658 /************************************************************/
659 /* Popup help label */
660 /************************************************************/
661 XtPopup (help_popup
, XtGrabNone
);