1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/buttonbar.cpp
3 // Purpose: wxButtonToolBar implementation
4 // Author: Julian Smart, after Robert Roebling, Vadim Zeitlin, SciTech
8 // Copyright: (c) Julian Smart, Robert Roebling, Vadim Zeitlin,
9 // SciTech Software, Inc.
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
13 // ============================================================================
15 // ============================================================================
17 // ----------------------------------------------------------------------------
19 // ----------------------------------------------------------------------------
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
28 // Currently, only for Mac as a toolbar replacement.
29 #if defined(__WXMAC__) && wxUSE_TOOLBAR && wxUSE_BMPBUTTON
31 #include "wx/generic/buttonbar.h"
38 #include "wx/dcclient.h"
39 #include "wx/settings.h"
43 // ----------------------------------------------------------------------------
44 // wxButtonToolBarTool: our implementation of wxToolBarToolBase
45 // ----------------------------------------------------------------------------
47 class WXDLLEXPORT wxButtonToolBarTool
: public wxToolBarToolBase
50 wxButtonToolBarTool(wxButtonToolBar
*tbar
,
52 const wxString
& label
,
53 const wxBitmap
& bmpNormal
,
54 const wxBitmap
& bmpDisabled
,
57 const wxString
& shortHelp
,
58 const wxString
& longHelp
)
59 : wxToolBarToolBase(tbar
, id
, label
, bmpNormal
, bmpDisabled
, kind
,
60 clientData
, shortHelp
, longHelp
)
62 m_x
= m_y
= wxDefaultCoord
;
69 wxButtonToolBarTool(wxButtonToolBar
*tbar
,
71 const wxString
& label
)
72 : wxToolBarToolBase(tbar
, control
, label
)
74 m_x
= m_y
= wxDefaultCoord
;
80 wxBitmapButton
* GetButton() const { return m_button
; }
81 void SetButton(wxBitmapButton
* button
) { m_button
= button
; }
84 // the tool position (for controls)
91 // the control representing the button
92 wxBitmapButton
* m_button
;
95 // ============================================================================
96 // wxButtonToolBar implementation
97 // ============================================================================
99 IMPLEMENT_DYNAMIC_CLASS(wxButtonToolBar
, wxControl
)
101 BEGIN_EVENT_TABLE(wxButtonToolBar
, wxControl
)
102 EVT_BUTTON(wxID_ANY
, wxButtonToolBar::OnCommand
)
103 EVT_PAINT(wxButtonToolBar::OnPaint
)
104 EVT_LEFT_UP(wxButtonToolBar::OnLeftUp
)
107 // ----------------------------------------------------------------------------
108 // wxButtonToolBar creation
109 // ----------------------------------------------------------------------------
111 void wxButtonToolBar::Init()
114 m_needsLayout
= false;
116 // unknown widths for the tools and separators
117 m_widthSeparator
= wxDefaultCoord
;
119 m_maxWidth
= m_maxHeight
= 0;
128 bool wxButtonToolBar::Create(wxWindow
*parent
,
133 const wxString
& name
)
135 if ( !wxToolBarBase::Create(parent
, id
, pos
, size
, style
,
136 wxDefaultValidator
, name
) )
141 // wxColour lightBackground(244, 244, 244);
143 wxFont
font(wxSMALL_FONT
->GetPointSize(), wxNORMAL_FONT
->GetFamily(), wxNORMAL_FONT
->GetStyle(), wxNORMAL
);
146 // Calculate the label height if necessary
147 if (GetWindowStyle() & wxTB_TEXT
)
152 dc
.GetTextExtent(wxT("X"), & w
, & h
);
158 wxButtonToolBar::~wxButtonToolBar()
162 // ----------------------------------------------------------------------------
163 // wxButtonToolBar tool-related methods
164 // ----------------------------------------------------------------------------
166 wxToolBarToolBase
*wxButtonToolBar::FindToolForPosition(wxCoord x
, wxCoord y
) const
168 // check the "other" direction first: it must be inside the toolbar or we
169 // don't risk finding anything
172 if ( x
< 0 || x
> m_maxWidth
)
175 // we always use x, even for a vertical toolbar, this makes the code
181 if ( y
< 0 || y
> m_maxHeight
)
185 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
187 node
= node
->GetNext() )
189 wxButtonToolBarTool
*tool
= (wxButtonToolBarTool
*) node
->GetData();
190 wxRect rectTool
= GetToolRect(tool
);
192 wxCoord startTool
, endTool
;
193 GetRectLimits(rectTool
, &startTool
, &endTool
);
195 if ( x
>= startTool
&& x
<= endTool
)
197 // don't return the separators from here, they don't accept any
199 return tool
->IsSeparator() ? NULL
: tool
;
206 void wxButtonToolBar::GetRectLimits(const wxRect
& rect
,
210 wxCHECK_RET( start
&& end
, _T("NULL pointer in GetRectLimits") );
214 *start
= rect
.GetTop();
215 *end
= rect
.GetBottom();
219 *start
= rect
.GetLeft();
220 *end
= rect
.GetRight();
225 void wxButtonToolBar::SetToolShortHelp(int id
, const wxString
& help
)
227 wxToolBarToolBase
*tool
= FindById(id
);
229 wxCHECK_RET( tool
, _T("SetToolShortHelp: no such tool") );
231 // TODO: set tooltip/short help
232 tool
->SetShortHelp(help
);
235 bool wxButtonToolBar::DoInsertTool(size_t WXUNUSED(pos
),
236 wxToolBarToolBase
* WXUNUSED(tool
))
241 bool wxButtonToolBar::DoDeleteTool(size_t WXUNUSED(pos
),
242 wxToolBarToolBase
* WXUNUSED(tool
))
248 void wxButtonToolBar::DoEnableTool(wxToolBarToolBase
*WXUNUSED(tool
), bool WXUNUSED(enable
))
253 void wxButtonToolBar::DoToggleTool(wxToolBarToolBase
*WXUNUSED(tool
), bool WXUNUSED(toggle
))
258 void wxButtonToolBar::DoSetToggle(wxToolBarToolBase
*WXUNUSED(tool
), bool WXUNUSED(toggle
))
263 wxToolBarToolBase
*wxButtonToolBar::CreateTool(int id
,
264 const wxString
& label
,
265 const wxBitmap
& bmpNormal
,
266 const wxBitmap
& bmpDisabled
,
268 wxObject
*clientData
,
269 const wxString
& shortHelp
,
270 const wxString
& longHelp
)
272 return new wxButtonToolBarTool(this, id
, label
, bmpNormal
, bmpDisabled
, kind
,
273 clientData
, shortHelp
, longHelp
);
276 wxToolBarToolBase
*wxButtonToolBar::CreateTool(wxControl
*control
,
277 const wxString
& label
)
279 return new wxButtonToolBarTool(this, control
, label
);
282 // ----------------------------------------------------------------------------
283 // wxButtonToolBar geometry
284 // ----------------------------------------------------------------------------
286 wxRect
wxButtonToolBar::GetToolRect(wxToolBarToolBase
*toolBase
) const
288 const wxButtonToolBarTool
*tool
= (wxButtonToolBarTool
*)toolBase
;
292 wxCHECK_MSG( tool
, rect
, _T("GetToolRect: NULL tool") );
294 // ensure that we always have the valid tool position
297 wxConstCast(this, wxButtonToolBar
)->DoLayout();
300 rect
.x
= tool
->m_x
- (m_toolPacking
/2);
305 if (tool
->IsButton())
307 rect
.width
= m_defaultWidth
;
308 rect
.height
= m_defaultHeight
;
309 if (tool
->GetButton())
310 rect
.SetSize(wxSize(tool
->m_width
, tool
->m_height
));
312 else if (tool
->IsSeparator())
314 rect
.width
= m_defaultWidth
;
315 rect
.height
= m_widthSeparator
;
319 rect
.width
= tool
->m_width
;
320 rect
.height
= tool
->m_height
;
325 if (tool
->IsButton())
327 rect
.width
= m_defaultWidth
;
328 rect
.height
= m_defaultHeight
;
329 if (tool
->GetButton())
330 rect
.SetSize(wxSize(tool
->m_width
, tool
->m_height
));
332 else if (tool
->IsSeparator())
334 rect
.width
= m_widthSeparator
;
335 rect
.height
= m_defaultHeight
;
339 rect
.width
= tool
->m_width
;
340 rect
.height
= tool
->m_height
;
344 rect
.width
+= m_toolPacking
;
349 bool wxButtonToolBar::Realize()
351 if ( !wxToolBarBase::Realize() )
354 m_needsLayout
= true;
357 SetInitialSize(wxSize(m_maxWidth
, m_maxHeight
));
362 void wxButtonToolBar::DoLayout()
364 m_needsLayout
= false;
366 wxCoord x
= m_xMargin
,
371 const wxCoord widthTool
= IsVertical() ? m_defaultHeight
: m_defaultWidth
;
372 wxCoord margin
= IsVertical() ? m_xMargin
: m_yMargin
;
373 wxCoord
*pCur
= IsVertical() ? &y
: &x
;
375 // calculate the positions of all elements
376 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
378 node
= node
->GetNext() )
380 wxButtonToolBarTool
*tool
= (wxButtonToolBarTool
*) node
->GetData();
385 if (tool
->IsButton())
387 if (!tool
->GetButton())
389 wxBitmapButton
* bmpButton
= new wxBitmapButton(this, tool
->GetId(), tool
->GetNormalBitmap(), wxPoint(tool
->m_x
, tool
->m_y
), wxDefaultSize
,
390 wxBU_AUTODRAW
|wxBORDER_NONE
);
391 if (!tool
->GetShortHelp().empty())
392 bmpButton
->SetLabel(tool
->GetShortHelp());
394 tool
->SetButton(bmpButton
);
398 tool
->GetButton()->Move(wxPoint(tool
->m_x
, tool
->m_y
));
402 if (tool
->GetButton())
404 wxSize sz
= tool
->GetButton()->GetSize();
407 if (m_labelHeight
> 0)
409 sz
.y
+= (m_labelHeight
+ m_labelMargin
);
411 if (!tool
->GetShortHelp().empty())
414 dc
.SetFont(GetFont());
416 dc
.GetTextExtent(tool
->GetShortHelp(), & tw
, & th
);
418 // If the label is bigger than the icon, the label width
419 // becomes the new tool width, and we need to centre the
420 // the bitmap in this box.
423 int newX
= int(tool
->m_x
+ (tw
- sz
.x
)/2.0);
424 tool
->GetButton()->Move(newX
, tool
->m_y
);
430 maxHeight
= wxMax(maxHeight
, sz
.y
);
432 tool
->m_width
= sz
.x
;
433 tool
->m_height
= sz
.y
;
437 *pCur
+= (w
+ GetToolPacking());
439 else if (tool
->IsSeparator())
441 *pCur
+= m_widthSeparator
;
443 else if (!IsVertical()) // horizontal control
445 wxControl
*control
= tool
->GetControl();
446 wxSize size
= control
->GetSize();
447 tool
->m_y
+= (m_defaultHeight
- size
.y
)/2;
448 tool
->m_width
= size
.x
;
449 tool
->m_height
= size
.y
;
451 *pCur
+= tool
->m_width
;
453 maxHeight
= wxMax(maxHeight
, size
.y
);
458 // calculate the total toolbar size
459 m_maxWidth
= x
+ 2*m_xMargin
;
460 m_maxHeight
= maxHeight
+ 2*m_yMargin
;
462 if ((GetWindowStyle() & wxTB_NODIVIDER
) == 0)
467 wxSize
wxButtonToolBar::DoGetBestClientSize() const
469 return wxSize(m_maxWidth
, m_maxHeight
);
472 // receives button commands
473 void wxButtonToolBar::OnCommand(wxCommandEvent
& event
)
475 wxButtonToolBarTool
* tool
= (wxButtonToolBarTool
*) FindById(event
.GetId());
482 if (tool
->CanBeToggled())
483 tool
->Toggle(tool
->IsToggled());
485 // TODO: handle toggle items
486 OnLeftClick(event
.GetId(), false);
488 if (tool
->GetKind() == wxITEM_RADIO
)
489 UnToggleRadioGroup(tool
);
491 if (tool
->CanBeToggled())
496 void wxButtonToolBar::OnPaint(wxPaintEvent
& event
)
500 dc
.SetFont(GetFont());
501 dc
.SetBackgroundMode(wxTRANSPARENT
);
503 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
505 node
= node
->GetNext() )
507 wxButtonToolBarTool
*tool
= (wxButtonToolBarTool
*) node
->GetData();
508 wxRect rectTool
= GetToolRect(tool
);
509 if (tool
->IsToggled())
511 wxRect backgroundRect
= rectTool
;
512 backgroundRect
.y
= -1; backgroundRect
.height
= GetClientSize().y
+ 1;
513 wxBrush
brush(wxColour(219, 219, 219));
514 wxPen
pen(wxColour(159, 159, 159));
517 dc
.DrawRectangle(backgroundRect
);
520 if (m_labelHeight
> 0 && !tool
->GetShortHelp().empty())
523 dc
.GetTextExtent(tool
->GetShortHelp(), & tw
, & th
);
526 dc
.DrawText(tool
->GetShortHelp(), x
, tool
->m_y
+ tool
->GetButton()->GetSize().y
+ m_labelMargin
);
530 if ((GetWindowStyle() & wxTB_NODIVIDER
) == 0)
532 wxPen
pen(wxColour(159, 159, 159));
535 int y1
= GetClientSize().y
-1;
536 int x2
= GetClientSize().x
;
538 dc
.DrawLine(x1
, y1
, x2
, y2
);
542 // detects mouse clicks outside buttons
543 void wxButtonToolBar::OnLeftUp(wxMouseEvent
& event
)
545 if (m_labelHeight
> 0)
547 wxButtonToolBarTool
* tool
= (wxButtonToolBarTool
*) FindToolForPosition(event
.GetX(), event
.GetY());
548 if (tool
&& tool
->GetButton() && (event
.GetY() > (tool
->m_y
+ tool
->GetButton()->GetSize().y
)))
550 wxCommandEvent
event(wxEVT_COMMAND_BUTTON_CLICKED
, tool
->GetId());
551 event
.SetEventObject(tool
->GetButton());
552 if (!ProcessEvent(event
))
558 #endif // wxUSE_TOOLBAR && wxUSE_BMPBUTTON