1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/ribbon/toolbar.cpp
3 // Purpose: Ribbon-style tool bar
4 // Author: Peter Cawley
7 // Copyright: (C) Peter Cawley
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 #include "wx/wxprec.h"
19 #include "wx/ribbon/toolbar.h"
20 #include "wx/ribbon/art.h"
21 #include "wx/ribbon/bar.h"
22 #include "wx/dcbuffer.h"
28 #include "wx/msw/private.h"
31 class wxRibbonToolBarToolBase
36 wxBitmap bitmap_disabled
;
40 wxObject
* client_data
;
42 wxRibbonButtonKind kind
;
46 WX_DEFINE_ARRAY_PTR(wxRibbonToolBarToolBase
*, wxArrayRibbonToolBarToolBase
);
48 class wxRibbonToolBarToolGroup
51 // To identify the group as a wxRibbonToolBarToolBase*
52 wxRibbonToolBarToolBase dummy_tool
;
54 wxArrayRibbonToolBarToolBase tools
;
59 wxDEFINE_EVENT(wxEVT_RIBBONTOOLBAR_CLICKED
, wxRibbonToolBarEvent
);
60 wxDEFINE_EVENT(wxEVT_RIBBONTOOLBAR_DROPDOWN_CLICKED
, wxRibbonToolBarEvent
);
62 IMPLEMENT_DYNAMIC_CLASS(wxRibbonToolBarEvent
, wxCommandEvent
)
63 IMPLEMENT_CLASS(wxRibbonToolBar
, wxRibbonControl
)
65 BEGIN_EVENT_TABLE(wxRibbonToolBar
, wxRibbonControl
)
66 EVT_ENTER_WINDOW(wxRibbonToolBar::OnMouseEnter
)
67 EVT_ERASE_BACKGROUND(wxRibbonToolBar::OnEraseBackground
)
68 EVT_LEAVE_WINDOW(wxRibbonToolBar::OnMouseLeave
)
69 EVT_LEFT_DOWN(wxRibbonToolBar::OnMouseDown
)
70 EVT_LEFT_UP(wxRibbonToolBar::OnMouseUp
)
71 EVT_MOTION(wxRibbonToolBar::OnMouseMove
)
72 EVT_PAINT(wxRibbonToolBar::OnPaint
)
73 EVT_SIZE(wxRibbonToolBar::OnSize
)
76 wxRibbonToolBar::wxRibbonToolBar()
80 wxRibbonToolBar::wxRibbonToolBar(wxWindow
* parent
,
85 : wxRibbonControl(parent
, id
, pos
, size
, wxBORDER_NONE
)
90 bool wxRibbonToolBar::Create(wxWindow
* parent
,
96 if(!wxRibbonControl::Create(parent
, id
, pos
, size
, wxBORDER_NONE
))
105 void wxRibbonToolBar::CommonInit(long WXUNUSED(style
))
109 m_active_tool
= NULL
;
112 m_sizes
= new wxSize
[1];
113 m_sizes
[0] = wxSize(0, 0);
114 SetBackgroundStyle(wxBG_STYLE_CUSTOM
);
117 wxRibbonToolBar::~wxRibbonToolBar()
119 size_t count
= m_groups
.GetCount();
121 for(i
= 0; i
< count
; ++i
)
123 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(i
);
124 size_t tool_count
= group
->tools
.GetCount();
125 for(t
= 0; t
< tool_count
; ++t
)
127 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
136 wxRibbonToolBarToolBase
* wxRibbonToolBar::AddTool(
138 const wxBitmap
& bitmap
,
139 const wxString
& help_string
,
140 wxRibbonButtonKind kind
)
142 return AddTool(tool_id
, bitmap
, wxNullBitmap
, help_string
, kind
, NULL
);
145 wxRibbonToolBarToolBase
* wxRibbonToolBar::AddDropdownTool(
147 const wxBitmap
& bitmap
,
148 const wxString
& help_string
)
150 return AddTool(tool_id
, bitmap
, wxNullBitmap
, help_string
,
151 wxRIBBON_BUTTON_DROPDOWN
, NULL
);
154 wxRibbonToolBarToolBase
* wxRibbonToolBar::AddHybridTool(
156 const wxBitmap
& bitmap
,
157 const wxString
& help_string
)
159 return AddTool(tool_id
, bitmap
, wxNullBitmap
, help_string
,
160 wxRIBBON_BUTTON_HYBRID
, NULL
);
163 wxRibbonToolBarToolBase
* wxRibbonToolBar::AddToggleTool(
165 const wxBitmap
& bitmap
,
166 const wxString
& help_string
)
168 return AddTool(tool_id
, bitmap
, wxNullBitmap
, help_string
,
169 wxRIBBON_BUTTON_TOGGLE
, NULL
);
172 wxRibbonToolBarToolBase
* wxRibbonToolBar::AddTool(
174 const wxBitmap
& bitmap
,
175 const wxBitmap
& bitmap_disabled
,
176 const wxString
& help_string
,
177 wxRibbonButtonKind kind
,
178 wxObject
* client_data
)
180 return InsertTool(GetToolCount(), tool_id
, bitmap
, bitmap_disabled
,
181 help_string
, kind
, client_data
);
184 wxRibbonToolBarToolBase
* wxRibbonToolBar::AddSeparator()
186 if(m_groups
.Last()->tools
.IsEmpty())
190 return &m_groups
.Last()->dummy_tool
;
194 wxRibbonToolBarToolBase
* wxRibbonToolBar::InsertTool(
197 const wxBitmap
& bitmap
,
198 const wxString
& help_string
,
199 wxRibbonButtonKind kind
)
201 return InsertTool(pos
, tool_id
, bitmap
, wxNullBitmap
, help_string
, kind
,
205 wxRibbonToolBarToolBase
* wxRibbonToolBar::InsertDropdownTool(
208 const wxBitmap
& bitmap
,
209 const wxString
& help_string
)
211 return InsertTool(pos
, tool_id
, bitmap
, wxNullBitmap
, help_string
,
212 wxRIBBON_BUTTON_DROPDOWN
, NULL
);
215 wxRibbonToolBarToolBase
* wxRibbonToolBar::InsertHybridTool(
218 const wxBitmap
& bitmap
,
219 const wxString
& help_string
)
221 return InsertTool(pos
, tool_id
, bitmap
, wxNullBitmap
, help_string
,
222 wxRIBBON_BUTTON_HYBRID
, NULL
);
225 wxRibbonToolBarToolBase
* wxRibbonToolBar::InsertToggleTool(
228 const wxBitmap
& bitmap
,
229 const wxString
& help_string
)
231 return InsertTool(pos
, tool_id
, bitmap
, wxNullBitmap
, help_string
,
232 wxRIBBON_BUTTON_TOGGLE
, NULL
);
235 wxRibbonToolBarToolBase
* wxRibbonToolBar::InsertTool(
238 const wxBitmap
& bitmap
,
239 const wxBitmap
& bitmap_disabled
,
240 const wxString
& help_string
,
241 wxRibbonButtonKind kind
,
242 wxObject
* client_data
)
244 wxASSERT(bitmap
.IsOk());
246 // Create the wxRibbonToolBarToolBase with parameters
247 wxRibbonToolBarToolBase
* tool
= new wxRibbonToolBarToolBase
;
249 tool
->bitmap
= bitmap
;
250 if(bitmap_disabled
.IsOk())
252 wxASSERT(bitmap
.GetSize() == bitmap_disabled
.GetSize());
253 tool
->bitmap_disabled
= bitmap_disabled
;
256 tool
->bitmap_disabled
= MakeDisabledBitmap(bitmap
);
257 tool
->help_string
= help_string
;
259 tool
->client_data
= client_data
;
260 tool
->position
= wxPoint(0, 0);
261 tool
->size
= wxSize(0, 0);
264 // Find the position where insert tool
265 size_t group_count
= m_groups
.GetCount();
267 for(g
= 0; g
< group_count
; ++g
)
269 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
270 size_t tool_count
= group
->tools
.GetCount();
271 if(pos
<= tool_count
)
273 group
->tools
.Insert(tool
, pos
);
276 pos
-= tool_count
+ 1;
278 wxFAIL_MSG("Tool position out of toolbar bounds.");
282 wxRibbonToolBarToolBase
* wxRibbonToolBar::InsertSeparator(size_t pos
)
284 size_t group_count
= m_groups
.GetCount();
286 for(g
= 0; g
< group_count
; ++g
)
288 if(pos
==0) // Prepend group
289 return &InsertGroup(g
)->dummy_tool
;
290 if(pos
==group_count
) // Append group
291 return &InsertGroup(g
+1)->dummy_tool
;
293 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
294 size_t tool_count
= group
->tools
.GetCount();
297 wxRibbonToolBarToolGroup
* new_group
= InsertGroup(g
+1);
299 for(size_t t
= pos
; t
< tool_count
; t
++)
300 new_group
->tools
.Add(group
->tools
[t
]);
301 group
->tools
.RemoveAt(pos
, tool_count
-pos
);
303 return &group
->dummy_tool
;
305 pos
-= tool_count
+ 1;
307 // Add an empty group at the end of the bar.
308 if(m_groups
.Last()->tools
.IsEmpty())
311 return &m_groups
.Last()->dummy_tool
;
314 wxRibbonToolBarToolGroup
* wxRibbonToolBar::InsertGroup(size_t pos
)
316 wxRibbonToolBarToolGroup
* group
= new wxRibbonToolBarToolGroup
;
317 group
->position
= wxPoint(0, 0);
318 group
->size
= wxSize(0, 0);
319 m_groups
.Insert(group
, pos
);
323 void wxRibbonToolBar::ClearTools()
325 size_t count
= m_groups
.GetCount();
327 for(i
= 0; i
< count
; ++i
)
329 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(i
);
330 size_t tool_count
= group
->tools
.GetCount();
331 for(t
= 0; t
< tool_count
; ++t
)
333 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
341 bool wxRibbonToolBar::DeleteTool(int tool_id
)
343 size_t group_count
= m_groups
.GetCount();
345 for(g
= 0; g
< group_count
; ++g
)
347 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
348 size_t tool_count
= group
->tools
.GetCount();
349 for(t
= 0; t
< tool_count
; ++t
)
351 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
352 if(tool
->id
== tool_id
)
354 group
->tools
.RemoveAt(t
);
363 bool wxRibbonToolBar::DeleteToolByPos(size_t pos
)
365 size_t group_count
= m_groups
.GetCount();
367 for(g
= 0; g
< group_count
; ++g
)
369 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
370 size_t tool_count
= group
->tools
.GetCount();
374 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(pos
);
375 group
->tools
.RemoveAt(pos
);
379 else if(pos
==tool_count
)
382 if(g
< group_count
- 1)
384 wxRibbonToolBarToolGroup
* next_group
= m_groups
.Item(g
+1);
385 for(t
= 0; t
< next_group
->tools
.GetCount(); ++t
)
386 group
->tools
.Add(next_group
->tools
[t
]);
387 m_groups
.RemoveAt(g
+1);
396 wxRibbonToolBarToolBase
* wxRibbonToolBar::FindById(int tool_id
)const
398 size_t group_count
= m_groups
.GetCount();
400 for(g
= 0; g
< group_count
; ++g
)
402 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
403 size_t tool_count
= group
->tools
.GetCount();
404 for(t
= 0; t
< tool_count
; ++t
)
406 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
407 if(tool
->id
== tool_id
)
416 wxRibbonToolBarToolBase
* wxRibbonToolBar::GetToolByPos(size_t pos
)const
418 size_t group_count
= m_groups
.GetCount();
420 for(g
= 0; g
< group_count
; ++g
)
422 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
423 size_t tool_count
= group
->tools
.GetCount();
426 return group
->tools
[pos
];
428 else if(pos
==tool_count
)
436 size_t wxRibbonToolBar::GetToolCount() const
439 for(size_t g
= 0; g
< m_groups
.GetCount(); ++g
)
441 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
442 count
+= group
->tools
.GetCount();
444 // There is a splitter in front of every group except for the first
445 // If only one group, no separator.
446 if(m_groups
.GetCount()>1)
447 count
+= m_groups
.GetCount() - 1;
451 int wxRibbonToolBar::GetToolId(const wxRibbonToolBarToolBase
* tool
)const
453 wxCHECK_MSG(tool
!= NULL
, wxNOT_FOUND
, "The tool pointer must not be NULL");
457 wxObject
* wxRibbonToolBar::GetToolClientData(int tool_id
)const
459 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
460 wxCHECK_MSG(tool
!= NULL
, NULL
, "Invalid tool id");
461 return tool
->client_data
;
464 bool wxRibbonToolBar::GetToolEnabled(int tool_id
)const
466 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
467 wxCHECK_MSG(tool
!= NULL
, false, "Invalid tool id");
468 return (tool
->state
& wxRIBBON_TOOLBAR_TOOL_DISABLED
) == 0;
471 wxString
wxRibbonToolBar::GetToolHelpString(int tool_id
)const
473 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
474 wxCHECK_MSG(tool
!= NULL
, wxEmptyString
, "Invalid tool id");
475 return tool
->help_string
;
478 wxRibbonButtonKind
wxRibbonToolBar::GetToolKind(int tool_id
)const
480 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
481 wxCHECK_MSG(tool
!= NULL
, wxRIBBON_BUTTON_NORMAL
, "Invalid tool id");
485 int wxRibbonToolBar::GetToolPos(int tool_id
)const
487 size_t group_count
= m_groups
.GetCount();
490 for(g
= 0; g
< group_count
; ++g
)
492 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
493 size_t tool_count
= group
->tools
.GetCount();
494 for(t
= 0; t
< tool_count
; ++t
)
496 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
497 if(tool
->id
== tool_id
)
503 ++pos
; // Increment pos for group separator.
508 bool wxRibbonToolBar::GetToolState(int tool_id
)const
510 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
511 wxCHECK_MSG(tool
!= NULL
, false, "Invalid tool id");
512 return (tool
->state
& wxRIBBON_TOOLBAR_TOOL_TOGGLED
) != 0;
515 wxBitmap
wxRibbonToolBar::MakeDisabledBitmap(const wxBitmap
& original
)
517 wxImage
img(original
.ConvertToImage());
518 return wxBitmap(img
.ConvertToGreyscale());
521 void wxRibbonToolBar::AppendGroup()
523 wxRibbonToolBarToolGroup
* group
= new wxRibbonToolBarToolGroup
;
524 group
->position
= wxPoint(0, 0);
525 group
->size
= wxSize(0, 0);
529 bool wxRibbonToolBar::IsSizingContinuous() const
534 void wxRibbonToolBar::SetToolClientData(int tool_id
, wxObject
* clientData
)
536 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
537 wxCHECK_RET(tool
!= NULL
, "Invalid tool id");
538 tool
->client_data
= clientData
;
541 void wxRibbonToolBar::SetToolDisabledBitmap(int tool_id
, const wxBitmap
&bitmap
)
543 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
544 wxCHECK_RET(tool
!= NULL
, "Invalid tool id");
545 tool
->bitmap_disabled
= bitmap
;
548 void wxRibbonToolBar::SetToolHelpString(int tool_id
, const wxString
& helpString
)
550 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
551 wxCHECK_RET(tool
!= NULL
, "Invalid tool id");
552 tool
->help_string
= helpString
;
555 void wxRibbonToolBar::SetToolNormalBitmap(int tool_id
, const wxBitmap
&bitmap
)
557 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
558 wxCHECK_RET(tool
!= NULL
, "Invalid tool id");
559 tool
->bitmap
= bitmap
;
562 void wxRibbonToolBar::EnableTool(int tool_id
, bool enable
)
564 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
565 wxCHECK_RET(tool
!= NULL
, "Invalid tool id");
568 if(tool
->state
& wxRIBBON_TOOLBAR_TOOL_DISABLED
)
570 tool
->state
&= ~wxRIBBON_TOOLBAR_TOOL_DISABLED
;
576 if((tool
->state
& wxRIBBON_TOOLBAR_TOOL_DISABLED
)==0)
578 tool
->state
|= wxRIBBON_TOOLBAR_TOOL_DISABLED
;
584 void wxRibbonToolBar::ToggleTool(int tool_id
, bool checked
)
586 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
587 wxCHECK_RET(tool
!= NULL
, "Invalid tool id");
590 if((tool
->state
& wxRIBBON_TOOLBAR_TOOL_TOGGLED
) == 0)
592 tool
->state
|= wxRIBBON_TOOLBAR_TOOL_TOGGLED
;
598 if(tool
->state
& wxRIBBON_TOOLBAR_TOOL_TOGGLED
)
600 tool
->state
&= ~wxRIBBON_TOOLBAR_TOOL_TOGGLED
;
606 static int GetSizeInOrientation(wxSize size
, wxOrientation orientation
)
610 case wxHORIZONTAL
: return size
.GetWidth();
611 case wxVERTICAL
: return size
.GetHeight();
612 case wxBOTH
: return size
.GetWidth() * size
.GetHeight();
617 wxSize
wxRibbonToolBar::DoGetNextSmallerSize(wxOrientation direction
,
618 wxSize relative_to
) const
620 wxSize
result(relative_to
);
623 for(nrows
= m_nrows_min
; nrows
<= m_nrows_max
; ++nrows
)
625 wxSize
size(m_sizes
[nrows
- m_nrows_min
]);
626 wxSize
original(size
);
630 if(size
.GetWidth() < relative_to
.GetWidth()
631 && size
.GetHeight() <= relative_to
.GetHeight())
633 size
.SetHeight(relative_to
.GetHeight());
638 if(size
.GetWidth() <= relative_to
.GetWidth()
639 && size
.GetHeight() < relative_to
.GetHeight())
641 size
.SetWidth(relative_to
.GetWidth());
646 if(size
.GetWidth() < relative_to
.GetWidth()
647 && size
.GetHeight() < relative_to
.GetHeight())
653 if(GetSizeInOrientation(original
, direction
) > area
)
656 area
= GetSizeInOrientation(original
, direction
);
662 wxSize
wxRibbonToolBar::DoGetNextLargerSize(wxOrientation direction
,
663 wxSize relative_to
) const
665 // Pick the smallest of our sizes which are larger than the given size
666 wxSize
result(relative_to
);
669 for(nrows
= m_nrows_min
; nrows
<= m_nrows_max
; ++nrows
)
671 wxSize
size(m_sizes
[nrows
- m_nrows_min
]);
672 wxSize
original(size
);
676 if(size
.GetWidth() > relative_to
.GetWidth()
677 && size
.GetHeight() <= relative_to
.GetHeight())
679 size
.SetHeight(relative_to
.GetHeight());
684 if(size
.GetWidth() <= relative_to
.GetWidth()
685 && size
.GetHeight() > relative_to
.GetHeight())
687 size
.SetWidth(relative_to
.GetWidth());
692 if(size
.GetWidth() > relative_to
.GetWidth()
693 && size
.GetHeight() > relative_to
.GetHeight())
699 if(GetSizeInOrientation(original
, direction
) < area
)
702 area
= GetSizeInOrientation(original
, direction
);
709 void wxRibbonToolBar::SetRows(int nMin
, int nMax
)
715 wxASSERT(nMin
<= nMax
);
721 m_sizes
= new wxSize
[m_nrows_max
- m_nrows_min
+ 1];
722 for(int i
= m_nrows_min
; i
<= m_nrows_max
; ++i
)
723 m_sizes
[i
- m_nrows_min
] = wxSize(0, 0);
728 bool wxRibbonToolBar::Realize()
733 // Calculate the size of each group and the position/size of each tool
735 size_t group_count
= m_groups
.GetCount();
737 for(g
= 0; g
< group_count
; ++g
)
739 wxRibbonToolBarToolBase
* prev
= NULL
;
740 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
741 size_t tool_count
= group
->tools
.GetCount();
743 for(t
= 0; t
< tool_count
; ++t
)
745 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
746 tool
->size
= m_art
->GetToolSize(temp_dc
, this,
747 tool
->bitmap
.GetSize(), tool
->kind
, t
== 0,
748 t
== (tool_count
- 1), &tool
->dropdown
);
750 tool
->state
|= wxRIBBON_TOOLBAR_TOOL_FIRST
;
751 if(t
== tool_count
- 1)
752 tool
->state
|= wxRIBBON_TOOLBAR_TOOL_LAST
;
753 if(tool
->size
.GetHeight() > tallest
)
754 tallest
= tool
->size
.GetHeight();
757 tool
->position
= prev
->position
;
758 tool
->position
.x
+= prev
->size
.x
;
762 tool
->position
= wxPoint(0, 0);
767 group
->size
= wxSize(0, 0);
770 group
->size
= wxSize(prev
->position
.x
+ prev
->size
.x
, tallest
);
771 for(t
= 0; t
< tool_count
; ++t
)
772 group
->tools
.Item(t
)->size
.SetHeight(tallest
);
776 // Calculate the minimum size for each possible number of rows
778 int sep
= m_art
->GetMetric(wxRIBBON_ART_TOOL_GROUP_SEPARATION_SIZE
);
779 int smallest_area
= INT_MAX
;
780 wxSize
* row_sizes
= new wxSize
[m_nrows_max
];
781 wxOrientation major_axis
= m_art
->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL
?
782 wxVERTICAL
: wxHORIZONTAL
;
784 SetMinSize(wxSize(0, 0));
785 wxSize
minSize(INT_MAX
, INT_MAX
);
787 // See if we're sizing flexibly (i.e. wrapping), and set min size differently
788 bool sizingFlexibly
= false;
789 wxRibbonPanel
* panel
= wxDynamicCast(GetParent(), wxRibbonPanel
);
790 if (panel
&& (panel
->GetFlags() & wxRIBBON_PANEL_FLEXIBLE
))
791 sizingFlexibly
= true;
793 // Without this, there will be redundant horizontal space because SetMinSize will
794 // use the smallest possible height (and therefore largest width).
796 major_axis
= wxHORIZONTAL
;
798 for(nrows
= m_nrows_min
; nrows
<= m_nrows_max
; ++nrows
)
800 for(r
= 0; r
< nrows
; ++r
)
801 row_sizes
[r
] = wxSize(0, 0);
802 for(g
= 0; g
< group_count
; ++g
)
804 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
805 int shortest_row
= 0;
806 for(r
= 1; r
< nrows
; ++r
)
808 if(row_sizes
[r
].GetWidth() < row_sizes
[shortest_row
].GetWidth())
811 row_sizes
[shortest_row
].x
+= group
->size
.x
+ sep
;
812 if(group
->size
.y
> row_sizes
[shortest_row
].y
)
813 row_sizes
[shortest_row
].y
= group
->size
.y
;
816 for(r
= 0; r
< nrows
; ++r
)
818 if(row_sizes
[r
].GetWidth() != 0)
819 row_sizes
[r
].DecBy(sep
, 0);
820 if(row_sizes
[r
].GetWidth() > size
.GetWidth())
821 size
.SetWidth(row_sizes
[r
].GetWidth());
822 size
.IncBy(0, row_sizes
[r
].y
);
824 m_sizes
[nrows
- m_nrows_min
] = size
;
826 if(GetSizeInOrientation(size
, major_axis
) < smallest_area
)
828 smallest_area
= GetSizeInOrientation(size
, major_axis
);
834 if (size
.x
< minSize
.x
)
836 if (size
.y
< minSize
.y
)
843 // Give it the min size in either direction regardless of row,
844 // so that we're able to vary the size of the panel according to
845 // the space the toolbar takes up.
850 // Position the groups
851 wxSizeEvent
dummy_event(GetSize());
857 void wxRibbonToolBar::OnSize(wxSizeEvent
& evt
)
862 // Choose row count with largest possible area
863 wxSize size
= evt
.GetSize();
864 int row_count
= m_nrows_max
;
865 wxOrientation major_axis
= m_art
->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL
?
866 wxVERTICAL
: wxHORIZONTAL
;
868 // See if we're sizing flexibly, and set min size differently
869 bool sizingFlexibly
= false;
870 wxRibbonPanel
* panel
= wxDynamicCast(GetParent(), wxRibbonPanel
);
871 if (panel
&& (panel
->GetFlags() & wxRIBBON_PANEL_FLEXIBLE
))
872 sizingFlexibly
= true;
874 // Without this, there will be redundant horizontal space because SetMinSize will
875 // use the smallest possible height (and therefore largest width).
877 major_axis
= wxHORIZONTAL
;
879 wxSize bestSize
= m_sizes
[0];
881 if(m_nrows_max
!= m_nrows_min
)
884 for(int i
= 0; i
<= m_nrows_max
- m_nrows_min
; ++i
)
886 if(m_sizes
[i
].x
<= size
.x
&& m_sizes
[i
].y
<= size
.y
&&
887 GetSizeInOrientation(m_sizes
[i
], major_axis
) > area
)
889 area
= GetSizeInOrientation(m_sizes
[i
], major_axis
);
890 row_count
= m_nrows_min
+ i
;
891 bestSize
= m_sizes
[i
];
896 // Assign groups to rows and calculate row widths
897 wxSize
* row_sizes
= new wxSize
[row_count
];
898 int sep
= m_art
->GetMetric(wxRIBBON_ART_TOOL_GROUP_SEPARATION_SIZE
);
901 for(r
= 0; r
< row_count
; ++r
)
902 row_sizes
[r
] = wxSize(0, 0);
904 size_t group_count
= m_groups
.GetCount();
905 for(g
= 0; g
< group_count
; ++g
)
907 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
908 int shortest_row
= 0;
909 for(r
= 1; r
< row_count
; ++r
)
911 if(row_sizes
[r
].GetWidth() < row_sizes
[shortest_row
].GetWidth())
914 group
->position
= wxPoint(row_sizes
[shortest_row
].x
, shortest_row
);
915 row_sizes
[shortest_row
].x
+= group
->size
.x
+ sep
;
916 if(group
->size
.y
> row_sizes
[shortest_row
].y
)
917 row_sizes
[shortest_row
].y
= group
->size
.y
;
920 // Calculate row positions
921 int total_height
= 0;
922 for(r
= 0; r
< row_count
; ++r
)
923 total_height
+= row_sizes
[r
].GetHeight();
924 int rowsep
= (size
.GetHeight() - total_height
) / (row_count
+ 1);
925 int* rowypos
= new int[row_count
];
927 for(r
= 1; r
< row_count
; ++r
)
929 rowypos
[r
] = rowypos
[r
- 1] + row_sizes
[r
- 1].GetHeight() + rowsep
;
932 // Set group y positions
933 for(g
= 0; g
< group_count
; ++g
)
935 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
936 group
->position
.y
= rowypos
[group
->position
.y
];
943 // Finds the best width and height given the parents' width and height
944 wxSize
wxRibbonToolBar::GetBestSizeForParentSize(const wxSize
& parentSize
) const
949 // Choose row count with largest possible area
950 wxSize size
= parentSize
;
952 // A toolbar should maximize its width whether vertical or horizontal, so
953 // force the major axis to be horizontal. Without this, there will be
954 // redundant horizontal space.
955 wxOrientation major_axis
= wxHORIZONTAL
;
956 wxSize bestSize
= m_sizes
[0];
958 if(m_nrows_max
!= m_nrows_min
)
961 for(int i
= 0; i
<= m_nrows_max
- m_nrows_min
; ++i
)
963 if(m_sizes
[i
].x
<= size
.x
&& m_sizes
[i
].y
<= size
.y
&&
964 GetSizeInOrientation(m_sizes
[i
], major_axis
) > area
)
966 area
= GetSizeInOrientation(m_sizes
[i
], major_axis
);
967 bestSize
= m_sizes
[i
];
974 wxSize
wxRibbonToolBar::DoGetBestSize() const
979 void wxRibbonToolBar::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
981 // All painting done in main paint handler to minimise flicker
984 void wxRibbonToolBar::OnPaint(wxPaintEvent
& WXUNUSED(evt
))
986 wxAutoBufferedPaintDC
dc(this);
990 m_art
->DrawToolBarBackground(dc
, this, GetSize());
992 size_t group_count
= m_groups
.GetCount();
994 for(g
= 0; g
< group_count
; ++g
)
996 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
997 size_t tool_count
= group
->tools
.GetCount();
1000 m_art
->DrawToolGroupBackground(dc
, this,
1001 wxRect(group
->position
, group
->size
));
1002 for(t
= 0; t
< tool_count
; ++t
)
1004 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
1005 wxRect
rect(group
->position
+ tool
->position
, tool
->size
);
1006 if(tool
->state
& wxRIBBON_TOOLBAR_TOOL_DISABLED
)
1007 m_art
->DrawTool(dc
, this, rect
, tool
->bitmap_disabled
,
1008 tool
->kind
, tool
->state
);
1010 m_art
->DrawTool(dc
, this, rect
, tool
->bitmap
, tool
->kind
,
1017 void wxRibbonToolBar::OnMouseMove(wxMouseEvent
& evt
)
1019 wxPoint
pos(evt
.GetPosition());
1020 wxRibbonToolBarToolBase
*new_hover
= NULL
;
1022 size_t group_count
= m_groups
.GetCount();
1024 for(g
= 0; g
< group_count
; ++g
)
1026 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
1027 if(group
->position
.x
<= pos
.x
&& pos
.x
< group
->position
.x
+ group
->size
.x
1028 && group
->position
.y
<= pos
.y
&& pos
.y
< group
->position
.y
+ group
->size
.y
)
1030 size_t tool_count
= group
->tools
.GetCount();
1031 pos
-= group
->position
;
1032 for(t
= 0; t
< tool_count
; ++t
)
1034 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
1035 if(tool
->position
.x
<= pos
.x
&& pos
.x
< tool
->position
.x
+ tool
->size
.x
1036 && tool
->position
.y
<= pos
.y
&& pos
.y
< tool
->position
.y
+ tool
->size
.y
)
1038 pos
-= tool
->position
;
1050 SetToolTip(new_hover
->help_string
);
1052 else if(GetToolTip())
1058 if(new_hover
&& new_hover
->state
& wxRIBBON_TOOLBAR_TOOL_DISABLED
)
1060 new_hover
= NULL
; // A disabled tool can not be hilighted
1063 if(new_hover
!= m_hover_tool
)
1067 m_hover_tool
->state
&= ~(wxRIBBON_TOOLBAR_TOOL_HOVER_MASK
1068 | wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK
);
1070 m_hover_tool
= new_hover
;
1073 long what
= wxRIBBON_TOOLBAR_TOOL_NORMAL_HOVERED
;
1074 if(new_hover
->dropdown
.Contains(pos
))
1075 what
= wxRIBBON_TOOLBAR_TOOL_DROPDOWN_HOVERED
;
1077 new_hover
->state
|= what
;
1079 if(new_hover
== m_active_tool
)
1081 new_hover
->state
&= ~wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK
;
1082 new_hover
->state
|= (what
<< 2);
1087 else if(m_hover_tool
&& m_hover_tool
->kind
== wxRIBBON_BUTTON_HYBRID
)
1089 long newstate
= m_hover_tool
->state
&~wxRIBBON_TOOLBAR_TOOL_HOVER_MASK
;
1090 long what
= wxRIBBON_TOOLBAR_TOOL_NORMAL_HOVERED
;
1091 if(m_hover_tool
->dropdown
.Contains(pos
))
1092 what
= wxRIBBON_TOOLBAR_TOOL_DROPDOWN_HOVERED
;
1094 if(newstate
!= m_hover_tool
->state
)
1096 m_hover_tool
->state
= newstate
;
1097 if(m_hover_tool
== m_active_tool
)
1099 m_hover_tool
->state
&= ~wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK
;
1100 m_hover_tool
->state
|= (what
<< 2);
1107 void wxRibbonToolBar::OnMouseDown(wxMouseEvent
& evt
)
1112 m_active_tool
= m_hover_tool
;
1113 m_active_tool
->state
|=
1114 (m_active_tool
->state
& wxRIBBON_TOOLBAR_TOOL_HOVER_MASK
) << 2;
1119 void wxRibbonToolBar::OnMouseLeave(wxMouseEvent
& WXUNUSED(evt
))
1123 m_hover_tool
->state
&= ~wxRIBBON_TOOLBAR_TOOL_HOVER_MASK
;
1124 m_hover_tool
= NULL
;
1129 void wxRibbonToolBar::OnMouseUp(wxMouseEvent
& WXUNUSED(evt
))
1133 if(m_active_tool
->state
& wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK
)
1135 wxEventType evt_type
= wxEVT_RIBBONTOOLBAR_CLICKED
;
1136 if(m_active_tool
->state
& wxRIBBON_TOOLBAR_TOOL_DROPDOWN_ACTIVE
)
1137 evt_type
= wxEVT_RIBBONTOOLBAR_DROPDOWN_CLICKED
;
1138 wxRibbonToolBarEvent
notification(evt_type
, m_active_tool
->id
);
1139 if(m_active_tool
->kind
== wxRIBBON_BUTTON_TOGGLE
)
1141 m_active_tool
->state
^=
1142 wxRIBBON_BUTTONBAR_BUTTON_TOGGLED
;
1143 notification
.SetInt(m_active_tool
->state
&
1144 wxRIBBON_BUTTONBAR_BUTTON_TOGGLED
);
1146 notification
.SetEventObject(this);
1147 notification
.SetBar(this);
1148 ProcessEvent(notification
);
1150 wxStaticCast(m_parent
, wxRibbonPanel
)->HideIfExpanded();
1153 // Notice that m_active_tool could have been reset by the event handler
1154 // above so we need to test it again.
1157 m_active_tool
->state
&= ~wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK
;
1158 m_active_tool
= NULL
;
1164 void wxRibbonToolBar::OnMouseEnter(wxMouseEvent
& evt
)
1166 if(m_active_tool
&& !evt
.LeftIsDown())
1168 m_active_tool
= NULL
;
1172 void wxRibbonToolBar::UpdateWindowUI(long flags
)
1174 wxWindowBase::UpdateWindowUI(flags
);
1176 // don't waste time updating state of tools in a hidden toolbar
1180 size_t group_count
= m_groups
.GetCount();
1182 for(g
= 0; g
< group_count
; ++g
)
1184 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
1185 size_t tool_count
= group
->tools
.GetCount();
1186 for(t
= 0; t
< tool_count
; ++t
)
1188 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
1191 wxUpdateUIEvent
event(id
);
1192 event
.SetEventObject(this);
1194 if ( ProcessWindowEvent(event
) )
1196 if ( event
.GetSetEnabled() )
1197 EnableTool(id
, event
.GetEnabled());
1198 if ( event
.GetSetChecked() )
1199 ToggleTool(id
, event
.GetChecked());
1205 bool wxRibbonToolBarEvent::PopupMenu(wxMenu
* menu
)
1207 wxPoint pos
= wxDefaultPosition
;
1208 if(m_bar
->m_active_tool
)
1210 // Find the group which contains the tool
1211 size_t group_count
= m_bar
->m_groups
.GetCount();
1213 for(g
= 0; g
< group_count
; ++g
)
1215 wxRibbonToolBarToolGroup
* group
= m_bar
->m_groups
.Item(g
);
1216 size_t tool_count
= group
->tools
.GetCount();
1217 for(t
= 0; t
< tool_count
; ++t
)
1219 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
1220 if(tool
== m_bar
->m_active_tool
)
1222 pos
= group
->position
;
1223 pos
+= tool
->position
;
1224 pos
.y
+= tool
->size
.GetHeight();
1231 return m_bar
->PopupMenu(menu
, pos
);
1234 #endif // wxUSE_RIBBON