1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/buttonbar.cpp
3 // Purpose: wxButtonToolBar implementation
4 // Author: Julian Smart, after Robert Roebling, Vadim Zeitlin, SciTech
7 // Copyright: (c) Julian Smart, Robert Roebling, Vadim Zeitlin,
8 // SciTech Software, Inc.
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
27 // Currently, only for Mac as a toolbar replacement.
28 #if defined(__WXMAC__) && wxUSE_TOOLBAR && wxUSE_BMPBUTTON
30 #include "wx/generic/buttonbar.h"
37 #include "wx/dcclient.h"
38 #include "wx/settings.h"
42 // ----------------------------------------------------------------------------
43 // wxButtonToolBarTool: our implementation of wxToolBarToolBase
44 // ----------------------------------------------------------------------------
46 class WXDLLEXPORT wxButtonToolBarTool
: public wxToolBarToolBase
49 wxButtonToolBarTool(wxButtonToolBar
*tbar
,
51 const wxString
& label
,
52 const wxBitmap
& bmpNormal
,
53 const wxBitmap
& bmpDisabled
,
56 const wxString
& shortHelp
,
57 const wxString
& longHelp
)
58 : wxToolBarToolBase(tbar
, id
, label
, bmpNormal
, bmpDisabled
, kind
,
59 clientData
, shortHelp
, longHelp
)
61 m_x
= m_y
= wxDefaultCoord
;
68 wxButtonToolBarTool(wxButtonToolBar
*tbar
,
70 const wxString
& label
)
71 : wxToolBarToolBase(tbar
, control
, label
)
73 m_x
= m_y
= wxDefaultCoord
;
79 wxBitmapButton
* GetButton() const { return m_button
; }
80 void SetButton(wxBitmapButton
* button
) { m_button
= button
; }
83 // the tool position (for controls)
90 // the control representing the button
91 wxBitmapButton
* m_button
;
94 // ============================================================================
95 // wxButtonToolBar implementation
96 // ============================================================================
98 IMPLEMENT_DYNAMIC_CLASS(wxButtonToolBar
, wxControl
)
100 BEGIN_EVENT_TABLE(wxButtonToolBar
, wxControl
)
101 EVT_BUTTON(wxID_ANY
, wxButtonToolBar::OnCommand
)
102 EVT_PAINT(wxButtonToolBar::OnPaint
)
103 EVT_LEFT_UP(wxButtonToolBar::OnLeftUp
)
106 // ----------------------------------------------------------------------------
107 // wxButtonToolBar creation
108 // ----------------------------------------------------------------------------
110 void wxButtonToolBar::Init()
113 m_needsLayout
= false;
115 // unknown widths for the tools and separators
116 m_widthSeparator
= wxDefaultCoord
;
118 m_maxWidth
= m_maxHeight
= 0;
127 bool wxButtonToolBar::Create(wxWindow
*parent
,
132 const wxString
& name
)
134 if ( !wxToolBarBase::Create(parent
, id
, pos
, size
, style
,
135 wxDefaultValidator
, name
) )
140 // wxColour lightBackground(244, 244, 244);
142 wxFont
font(wxSMALL_FONT
->GetPointSize(),
143 wxNORMAL_FONT
->GetFamily(),
144 wxNORMAL_FONT
->GetStyle(),
145 wxFONTWEIGHT_NORMAL
);
148 // Calculate the label height if necessary
149 if (GetWindowStyle() & wxTB_TEXT
)
154 dc
.GetTextExtent(wxT("X"), & w
, & h
);
160 wxButtonToolBar::~wxButtonToolBar()
164 // ----------------------------------------------------------------------------
165 // wxButtonToolBar tool-related methods
166 // ----------------------------------------------------------------------------
168 wxToolBarToolBase
*wxButtonToolBar::FindToolForPosition(wxCoord x
, wxCoord y
) const
170 // check the "other" direction first: it must be inside the toolbar or we
171 // don't risk finding anything
174 if ( x
< 0 || x
> m_maxWidth
)
177 // we always use x, even for a vertical toolbar, this makes the code
183 if ( y
< 0 || y
> m_maxHeight
)
187 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
189 node
= node
->GetNext() )
191 wxButtonToolBarTool
*tool
= (wxButtonToolBarTool
*) node
->GetData();
192 wxRect rectTool
= GetToolRect(tool
);
194 wxCoord startTool
, endTool
;
195 GetRectLimits(rectTool
, &startTool
, &endTool
);
197 if ( x
>= startTool
&& x
<= endTool
)
199 // don't return the separators from here, they don't accept any
201 return tool
->IsSeparator() ? NULL
: tool
;
208 void wxButtonToolBar::GetRectLimits(const wxRect
& rect
,
212 wxCHECK_RET( start
&& end
, wxT("NULL pointer in GetRectLimits") );
216 *start
= rect
.GetTop();
217 *end
= rect
.GetBottom();
221 *start
= rect
.GetLeft();
222 *end
= rect
.GetRight();
227 void wxButtonToolBar::SetToolShortHelp(int id
, const wxString
& help
)
229 wxToolBarToolBase
*tool
= FindById(id
);
231 wxCHECK_RET( tool
, wxT("SetToolShortHelp: no such tool") );
233 // TODO: set tooltip/short help
234 tool
->SetShortHelp(help
);
237 bool wxButtonToolBar::DoInsertTool(size_t WXUNUSED(pos
),
238 wxToolBarToolBase
* WXUNUSED(tool
))
243 bool wxButtonToolBar::DoDeleteTool(size_t WXUNUSED(pos
),
244 wxToolBarToolBase
* WXUNUSED(tool
))
250 void wxButtonToolBar::DoEnableTool(wxToolBarToolBase
*WXUNUSED(tool
), bool WXUNUSED(enable
))
255 void wxButtonToolBar::DoToggleTool(wxToolBarToolBase
*WXUNUSED(tool
), bool WXUNUSED(toggle
))
260 void wxButtonToolBar::DoSetToggle(wxToolBarToolBase
*WXUNUSED(tool
), bool WXUNUSED(toggle
))
265 wxToolBarToolBase
*wxButtonToolBar::CreateTool(int id
,
266 const wxString
& label
,
267 const wxBitmap
& bmpNormal
,
268 const wxBitmap
& bmpDisabled
,
270 wxObject
*clientData
,
271 const wxString
& shortHelp
,
272 const wxString
& longHelp
)
274 return new wxButtonToolBarTool(this, id
, label
, bmpNormal
, bmpDisabled
, kind
,
275 clientData
, shortHelp
, longHelp
);
278 wxToolBarToolBase
*wxButtonToolBar::CreateTool(wxControl
*control
,
279 const wxString
& label
)
281 return new wxButtonToolBarTool(this, control
, label
);
284 // ----------------------------------------------------------------------------
285 // wxButtonToolBar geometry
286 // ----------------------------------------------------------------------------
288 wxRect
wxButtonToolBar::GetToolRect(wxToolBarToolBase
*toolBase
) const
290 const wxButtonToolBarTool
*tool
= (wxButtonToolBarTool
*)toolBase
;
294 wxCHECK_MSG( tool
, rect
, wxT("GetToolRect: NULL tool") );
296 // ensure that we always have the valid tool position
299 wxConstCast(this, wxButtonToolBar
)->DoLayout();
302 rect
.x
= tool
->m_x
- (m_toolPacking
/2);
307 if (tool
->IsButton())
309 rect
.width
= m_defaultWidth
;
310 rect
.height
= m_defaultHeight
;
311 if (tool
->GetButton())
312 rect
.SetSize(wxSize(tool
->m_width
, tool
->m_height
));
314 else if (tool
->IsSeparator())
316 rect
.width
= m_defaultWidth
;
317 rect
.height
= m_widthSeparator
;
321 rect
.width
= tool
->m_width
;
322 rect
.height
= tool
->m_height
;
327 if (tool
->IsButton())
329 rect
.width
= m_defaultWidth
;
330 rect
.height
= m_defaultHeight
;
331 if (tool
->GetButton())
332 rect
.SetSize(wxSize(tool
->m_width
, tool
->m_height
));
334 else if (tool
->IsSeparator())
336 rect
.width
= m_widthSeparator
;
337 rect
.height
= m_defaultHeight
;
341 rect
.width
= tool
->m_width
;
342 rect
.height
= tool
->m_height
;
346 rect
.width
+= m_toolPacking
;
351 bool wxButtonToolBar::Realize()
353 if ( !wxToolBarBase::Realize() )
356 m_needsLayout
= true;
359 SetInitialSize(wxSize(m_maxWidth
, m_maxHeight
));
364 void wxButtonToolBar::DoLayout()
366 m_needsLayout
= false;
368 wxCoord x
= m_xMargin
,
373 const wxCoord widthTool
= IsVertical() ? m_defaultHeight
: m_defaultWidth
;
374 wxCoord margin
= IsVertical() ? m_xMargin
: m_yMargin
;
375 wxCoord
*pCur
= IsVertical() ? &y
: &x
;
377 // calculate the positions of all elements
378 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
380 node
= node
->GetNext() )
382 wxButtonToolBarTool
*tool
= (wxButtonToolBarTool
*) node
->GetData();
387 if (tool
->IsButton())
389 if (!tool
->GetButton())
391 wxBitmapButton
* bmpButton
= new wxBitmapButton(this, tool
->GetId(), tool
->GetNormalBitmap(), wxPoint(tool
->m_x
, tool
->m_y
), wxDefaultSize
,
392 wxBU_AUTODRAW
|wxBORDER_NONE
);
393 if (!tool
->GetShortHelp().empty())
394 bmpButton
->SetLabel(tool
->GetShortHelp());
396 tool
->SetButton(bmpButton
);
400 tool
->GetButton()->Move(wxPoint(tool
->m_x
, tool
->m_y
));
404 if (tool
->GetButton())
406 wxSize sz
= tool
->GetButton()->GetSize();
409 if (m_labelHeight
> 0)
411 sz
.y
+= (m_labelHeight
+ m_labelMargin
);
413 if (!tool
->GetShortHelp().empty())
416 dc
.SetFont(GetFont());
418 dc
.GetTextExtent(tool
->GetShortHelp(), & tw
, & th
);
420 // If the label is bigger than the icon, the label width
421 // becomes the new tool width, and we need to centre the
422 // the bitmap in this box.
425 int newX
= int(tool
->m_x
+ (tw
- sz
.x
)/2.0);
426 tool
->GetButton()->Move(newX
, tool
->m_y
);
432 maxHeight
= wxMax(maxHeight
, sz
.y
);
434 tool
->m_width
= sz
.x
;
435 tool
->m_height
= sz
.y
;
439 *pCur
+= (w
+ GetToolPacking());
441 else if (tool
->IsSeparator())
443 *pCur
+= m_widthSeparator
;
445 else if (!IsVertical()) // horizontal control
447 wxControl
*control
= tool
->GetControl();
448 wxSize size
= control
->GetSize();
449 tool
->m_y
+= (m_defaultHeight
- size
.y
)/2;
450 tool
->m_width
= size
.x
;
451 tool
->m_height
= size
.y
;
453 *pCur
+= tool
->m_width
;
455 maxHeight
= wxMax(maxHeight
, size
.y
);
460 // calculate the total toolbar size
461 m_maxWidth
= x
+ 2*m_xMargin
;
462 m_maxHeight
= maxHeight
+ 2*m_yMargin
;
464 if ((GetWindowStyle() & wxTB_NODIVIDER
) == 0)
469 wxSize
wxButtonToolBar::DoGetBestClientSize() const
471 return wxSize(m_maxWidth
, m_maxHeight
);
474 // receives button commands
475 void wxButtonToolBar::OnCommand(wxCommandEvent
& event
)
477 wxButtonToolBarTool
* tool
= (wxButtonToolBarTool
*) FindById(event
.GetId());
484 if (tool
->CanBeToggled())
485 tool
->Toggle(tool
->IsToggled());
487 // TODO: handle toggle items
488 OnLeftClick(event
.GetId(), false);
490 if (tool
->GetKind() == wxITEM_RADIO
)
491 UnToggleRadioGroup(tool
);
493 if (tool
->CanBeToggled())
498 void wxButtonToolBar::OnPaint(wxPaintEvent
& WXUNUSED(event
))
502 dc
.SetFont(GetFont());
503 dc
.SetBackgroundMode(wxTRANSPARENT
);
505 for ( wxToolBarToolsList::compatibility_iterator node
= m_tools
.GetFirst();
507 node
= node
->GetNext() )
509 wxButtonToolBarTool
*tool
= (wxButtonToolBarTool
*) node
->GetData();
510 wxRect rectTool
= GetToolRect(tool
);
511 if (tool
->IsToggled())
513 wxRect backgroundRect
= rectTool
;
514 backgroundRect
.y
= -1; backgroundRect
.height
= GetClientSize().y
+ 1;
515 wxBrush
brush(wxColour(219, 219, 219));
516 wxPen
pen(wxColour(159, 159, 159));
519 dc
.DrawRectangle(backgroundRect
);
522 if (m_labelHeight
> 0 && !tool
->GetShortHelp().empty())
525 dc
.GetTextExtent(tool
->GetShortHelp(), & tw
, & th
);
528 dc
.DrawText(tool
->GetShortHelp(), x
, tool
->m_y
+ tool
->GetButton()->GetSize().y
+ m_labelMargin
);
532 if ((GetWindowStyle() & wxTB_NODIVIDER
) == 0)
534 wxPen
pen(wxColour(159, 159, 159));
537 int y1
= GetClientSize().y
-1;
538 int x2
= GetClientSize().x
;
540 dc
.DrawLine(x1
, y1
, x2
, y2
);
544 // detects mouse clicks outside buttons
545 void wxButtonToolBar::OnLeftUp(wxMouseEvent
& event
)
547 if (m_labelHeight
> 0)
549 wxButtonToolBarTool
* tool
= (wxButtonToolBarTool
*) FindToolForPosition(event
.GetX(), event
.GetY());
550 if (tool
&& tool
->GetButton() && (event
.GetY() > (tool
->m_y
+ tool
->GetButton()->GetSize().y
)))
552 wxCommandEvent
event(wxEVT_BUTTON
, tool
->GetId());
553 event
.SetEventObject(tool
->GetButton());
554 if (!GetEventHandler()->ProcessEvent(event
))
560 #endif // wxUSE_TOOLBAR && wxUSE_BMPBUTTON