1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/ribbon/toolbar.cpp
3 // Purpose: Ribbon-style tool bar
4 // Author: Peter Cawley
8 // Copyright: (C) Peter Cawley
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
20 #include "wx/ribbon/toolbar.h"
21 #include "wx/ribbon/art.h"
22 #include "wx/ribbon/bar.h"
23 #include "wx/dcbuffer.h"
29 #include "wx/msw/private.h"
32 class wxRibbonToolBarToolBase
37 wxBitmap bitmap_disabled
;
41 wxObject
* client_data
;
43 wxRibbonButtonKind kind
;
47 WX_DEFINE_ARRAY_PTR(wxRibbonToolBarToolBase
*, wxArrayRibbonToolBarToolBase
);
49 class wxRibbonToolBarToolGroup
52 // To identify the group as a wxRibbonToolBarToolBase*
53 wxRibbonToolBarToolBase dummy_tool
;
55 wxArrayRibbonToolBarToolBase tools
;
60 wxDEFINE_EVENT(wxEVT_COMMAND_RIBBONTOOL_CLICKED
, wxRibbonToolBarEvent
);
61 wxDEFINE_EVENT(wxEVT_COMMAND_RIBBONTOOL_DROPDOWN_CLICKED
, wxRibbonToolBarEvent
);
63 IMPLEMENT_DYNAMIC_CLASS(wxRibbonToolBarEvent
, wxCommandEvent
)
64 IMPLEMENT_CLASS(wxRibbonToolBar
, wxRibbonControl
)
66 BEGIN_EVENT_TABLE(wxRibbonToolBar
, wxRibbonControl
)
67 EVT_ENTER_WINDOW(wxRibbonToolBar::OnMouseEnter
)
68 EVT_ERASE_BACKGROUND(wxRibbonToolBar::OnEraseBackground
)
69 EVT_LEAVE_WINDOW(wxRibbonToolBar::OnMouseLeave
)
70 EVT_LEFT_DOWN(wxRibbonToolBar::OnMouseDown
)
71 EVT_LEFT_UP(wxRibbonToolBar::OnMouseUp
)
72 EVT_MOTION(wxRibbonToolBar::OnMouseMove
)
73 EVT_PAINT(wxRibbonToolBar::OnPaint
)
74 EVT_SIZE(wxRibbonToolBar::OnSize
)
77 wxRibbonToolBar::wxRibbonToolBar()
81 wxRibbonToolBar::wxRibbonToolBar(wxWindow
* parent
,
86 : wxRibbonControl(parent
, id
, pos
, size
, wxBORDER_NONE
)
91 bool wxRibbonToolBar::Create(wxWindow
* parent
,
97 if(!wxRibbonControl::Create(parent
, id
, pos
, size
, wxBORDER_NONE
))
106 void wxRibbonToolBar::CommonInit(long WXUNUSED(style
))
110 m_active_tool
= NULL
;
113 m_sizes
= new wxSize
[1];
114 m_sizes
[0] = wxSize(0, 0);
115 SetBackgroundStyle(wxBG_STYLE_CUSTOM
);
118 wxRibbonToolBar::~wxRibbonToolBar()
120 size_t count
= m_groups
.GetCount();
122 for(i
= 0; i
< count
; ++i
)
124 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(i
);
125 size_t tool_count
= group
->tools
.GetCount();
126 for(t
= 0; t
< tool_count
; ++t
)
128 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
137 wxRibbonToolBarToolBase
* wxRibbonToolBar::AddTool(
139 const wxBitmap
& bitmap
,
140 const wxString
& help_string
,
141 wxRibbonButtonKind kind
)
143 return AddTool(tool_id
, bitmap
, wxNullBitmap
, help_string
, kind
, NULL
);
146 wxRibbonToolBarToolBase
* wxRibbonToolBar::AddDropdownTool(
148 const wxBitmap
& bitmap
,
149 const wxString
& help_string
)
151 return AddTool(tool_id
, bitmap
, wxNullBitmap
, help_string
,
152 wxRIBBON_BUTTON_DROPDOWN
, NULL
);
155 wxRibbonToolBarToolBase
* wxRibbonToolBar::AddHybridTool(
157 const wxBitmap
& bitmap
,
158 const wxString
& help_string
)
160 return AddTool(tool_id
, bitmap
, wxNullBitmap
, help_string
,
161 wxRIBBON_BUTTON_HYBRID
, NULL
);
164 wxRibbonToolBarToolBase
* wxRibbonToolBar::AddToggleTool(
166 const wxBitmap
& bitmap
,
167 const wxString
& help_string
)
169 return AddTool(tool_id
, bitmap
, wxNullBitmap
, help_string
,
170 wxRIBBON_BUTTON_TOGGLE
, NULL
);
173 wxRibbonToolBarToolBase
* wxRibbonToolBar::AddTool(
175 const wxBitmap
& bitmap
,
176 const wxBitmap
& bitmap_disabled
,
177 const wxString
& help_string
,
178 wxRibbonButtonKind kind
,
179 wxObject
* client_data
)
181 return InsertTool(GetToolCount(), tool_id
, bitmap
, bitmap_disabled
,
182 help_string
, kind
, client_data
);
185 wxRibbonToolBarToolBase
* wxRibbonToolBar::AddSeparator()
187 if(m_groups
.Last()->tools
.IsEmpty())
191 return &m_groups
.Last()->dummy_tool
;
195 wxRibbonToolBarToolBase
* wxRibbonToolBar::InsertTool(
198 const wxBitmap
& bitmap
,
199 const wxString
& help_string
,
200 wxRibbonButtonKind kind
)
202 return InsertTool(pos
, tool_id
, bitmap
, wxNullBitmap
, help_string
, kind
,
206 wxRibbonToolBarToolBase
* wxRibbonToolBar::InsertDropdownTool(
209 const wxBitmap
& bitmap
,
210 const wxString
& help_string
)
212 return InsertTool(pos
, tool_id
, bitmap
, wxNullBitmap
, help_string
,
213 wxRIBBON_BUTTON_DROPDOWN
, NULL
);
216 wxRibbonToolBarToolBase
* wxRibbonToolBar::InsertHybridTool(
219 const wxBitmap
& bitmap
,
220 const wxString
& help_string
)
222 return InsertTool(pos
, tool_id
, bitmap
, wxNullBitmap
, help_string
,
223 wxRIBBON_BUTTON_HYBRID
, NULL
);
226 wxRibbonToolBarToolBase
* wxRibbonToolBar::InsertToggleTool(
229 const wxBitmap
& bitmap
,
230 const wxString
& help_string
)
232 return InsertTool(pos
, tool_id
, bitmap
, wxNullBitmap
, help_string
,
233 wxRIBBON_BUTTON_TOGGLE
, NULL
);
236 wxRibbonToolBarToolBase
* wxRibbonToolBar::InsertTool(
239 const wxBitmap
& bitmap
,
240 const wxBitmap
& bitmap_disabled
,
241 const wxString
& help_string
,
242 wxRibbonButtonKind kind
,
243 wxObject
* client_data
)
245 wxASSERT(bitmap
.IsOk());
247 // Create the wxRibbonToolBarToolBase with parameters
248 wxRibbonToolBarToolBase
* tool
= new wxRibbonToolBarToolBase
;
250 tool
->bitmap
= bitmap
;
251 if(bitmap_disabled
.IsOk())
253 wxASSERT(bitmap
.GetSize() == bitmap_disabled
.GetSize());
254 tool
->bitmap_disabled
= bitmap_disabled
;
257 tool
->bitmap_disabled
= MakeDisabledBitmap(bitmap
);
258 tool
->help_string
= help_string
;
260 tool
->client_data
= client_data
;
261 tool
->position
= wxPoint(0, 0);
262 tool
->size
= wxSize(0, 0);
265 // Find the position where insert tool
266 size_t group_count
= m_groups
.GetCount();
268 for(g
= 0; g
< group_count
; ++g
)
270 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
271 size_t tool_count
= group
->tools
.GetCount();
272 if(pos
<= tool_count
)
274 group
->tools
.Insert(tool
, pos
);
277 pos
-= tool_count
+ 1;
279 wxFAIL_MSG("Tool position out of toolbar bounds.");
283 wxRibbonToolBarToolBase
* wxRibbonToolBar::InsertSeparator(size_t pos
)
285 size_t group_count
= m_groups
.GetCount();
287 for(g
= 0; g
< group_count
; ++g
)
289 if(pos
==0) // Prepend group
290 return &InsertGroup(g
)->dummy_tool
;
291 if(pos
==group_count
) // Append group
292 return &InsertGroup(g
+1)->dummy_tool
;
294 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
295 size_t tool_count
= group
->tools
.GetCount();
298 wxRibbonToolBarToolGroup
* new_group
= InsertGroup(g
+1);
300 for(size_t t
= pos
; t
< tool_count
; t
++)
301 new_group
->tools
.Add(group
->tools
[t
]);
302 group
->tools
.RemoveAt(pos
, tool_count
-pos
);
304 return &group
->dummy_tool
;
306 pos
-= tool_count
+ 1;
308 // Add an empty group at the end of the bar.
309 if(m_groups
.Last()->tools
.IsEmpty())
312 return &m_groups
.Last()->dummy_tool
;
315 wxRibbonToolBarToolGroup
* wxRibbonToolBar::InsertGroup(size_t pos
)
317 wxRibbonToolBarToolGroup
* group
= new wxRibbonToolBarToolGroup
;
318 group
->position
= wxPoint(0, 0);
319 group
->size
= wxSize(0, 0);
320 m_groups
.Insert(group
, pos
);
324 void wxRibbonToolBar::ClearTools()
326 size_t count
= m_groups
.GetCount();
328 for(i
= 0; i
< count
; ++i
)
330 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(i
);
331 size_t tool_count
= group
->tools
.GetCount();
332 for(t
= 0; t
< tool_count
; ++t
)
334 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
342 bool wxRibbonToolBar::DeleteTool(int tool_id
)
344 size_t group_count
= m_groups
.GetCount();
346 for(g
= 0; g
< group_count
; ++g
)
348 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
349 size_t tool_count
= group
->tools
.GetCount();
350 for(t
= 0; t
< tool_count
; ++t
)
352 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
353 if(tool
->id
== tool_id
)
355 group
->tools
.RemoveAt(t
);
364 bool wxRibbonToolBar::DeleteToolByPos(size_t pos
)
366 size_t group_count
= m_groups
.GetCount();
368 for(g
= 0; g
< group_count
; ++g
)
370 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
371 size_t tool_count
= group
->tools
.GetCount();
375 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(pos
);
376 group
->tools
.RemoveAt(pos
);
380 else if(pos
==tool_count
)
383 if(g
< group_count
- 1)
385 wxRibbonToolBarToolGroup
* next_group
= m_groups
.Item(g
+1);
386 for(t
= 0; t
< next_group
->tools
.GetCount(); ++t
)
387 group
->tools
.Add(next_group
->tools
[t
]);
388 m_groups
.RemoveAt(g
+1);
397 wxRibbonToolBarToolBase
* wxRibbonToolBar::FindById(int tool_id
)const
399 size_t group_count
= m_groups
.GetCount();
401 for(g
= 0; g
< group_count
; ++g
)
403 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
404 size_t tool_count
= group
->tools
.GetCount();
405 for(t
= 0; t
< tool_count
; ++t
)
407 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
408 if(tool
->id
== tool_id
)
417 wxRibbonToolBarToolBase
* wxRibbonToolBar::GetToolByPos(size_t pos
)const
419 size_t group_count
= m_groups
.GetCount();
421 for(g
= 0; g
< group_count
; ++g
)
423 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
424 size_t tool_count
= group
->tools
.GetCount();
427 return group
->tools
[pos
];
429 else if(pos
==tool_count
)
437 size_t wxRibbonToolBar::GetToolCount() const
440 for(size_t g
= 0; g
< m_groups
.GetCount(); ++g
)
442 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
443 count
+= group
->tools
.GetCount();
445 // There is a splitter in front of every group except for the first
446 // If only one group, no separator.
447 if(m_groups
.GetCount()>1)
448 count
+= m_groups
.GetCount() - 1;
452 int wxRibbonToolBar::GetToolId(const wxRibbonToolBarToolBase
* tool
)const
454 wxCHECK_MSG(tool
!= NULL
, wxNOT_FOUND
, "The tool pointer must not be NULL");
458 wxObject
* wxRibbonToolBar::GetToolClientData(int tool_id
)const
460 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
461 wxCHECK_MSG(tool
!= NULL
, NULL
, "Invalid tool id");
462 return tool
->client_data
;
465 bool wxRibbonToolBar::GetToolEnabled(int tool_id
)const
467 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
468 wxCHECK_MSG(tool
!= NULL
, false, "Invalid tool id");
469 return (tool
->state
& wxRIBBON_TOOLBAR_TOOL_DISABLED
) == 0;
472 wxString
wxRibbonToolBar::GetToolHelpString(int tool_id
)const
474 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
475 wxCHECK_MSG(tool
!= NULL
, wxEmptyString
, "Invalid tool id");
476 return tool
->help_string
;
479 wxRibbonButtonKind
wxRibbonToolBar::GetToolKind(int tool_id
)const
481 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
482 wxCHECK_MSG(tool
!= NULL
, wxRIBBON_BUTTON_NORMAL
, "Invalid tool id");
486 int wxRibbonToolBar::GetToolPos(int tool_id
)const
488 size_t group_count
= m_groups
.GetCount();
491 for(g
= 0; g
< group_count
; ++g
)
493 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
494 size_t tool_count
= group
->tools
.GetCount();
495 for(t
= 0; t
< tool_count
; ++t
)
497 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
498 if(tool
->id
== tool_id
)
504 ++pos
; // Increment pos for group separator.
509 bool wxRibbonToolBar::GetToolState(int tool_id
)const
511 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
512 wxCHECK_MSG(tool
!= NULL
, false, "Invalid tool id");
513 return (tool
->state
& wxRIBBON_TOOLBAR_TOOL_TOGGLED
) != 0;
516 wxBitmap
wxRibbonToolBar::MakeDisabledBitmap(const wxBitmap
& original
)
518 wxImage
img(original
.ConvertToImage());
519 return wxBitmap(img
.ConvertToGreyscale());
522 void wxRibbonToolBar::AppendGroup()
524 wxRibbonToolBarToolGroup
* group
= new wxRibbonToolBarToolGroup
;
525 group
->position
= wxPoint(0, 0);
526 group
->size
= wxSize(0, 0);
530 bool wxRibbonToolBar::IsSizingContinuous() const
535 void wxRibbonToolBar::SetToolClientData(int tool_id
, wxObject
* clientData
)
537 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
538 wxCHECK_RET(tool
!= NULL
, "Invalid tool id");
539 tool
->client_data
= clientData
;
542 void wxRibbonToolBar::SetToolDisabledBitmap(int tool_id
, const wxBitmap
&bitmap
)
544 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
545 wxCHECK_RET(tool
!= NULL
, "Invalid tool id");
546 tool
->bitmap_disabled
= bitmap
;
549 void wxRibbonToolBar::SetToolHelpString(int tool_id
, const wxString
& helpString
)
551 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
552 wxCHECK_RET(tool
!= NULL
, "Invalid tool id");
553 tool
->help_string
= helpString
;
556 void wxRibbonToolBar::SetToolNormalBitmap(int tool_id
, const wxBitmap
&bitmap
)
558 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
559 wxCHECK_RET(tool
!= NULL
, "Invalid tool id");
560 tool
->bitmap
= bitmap
;
563 void wxRibbonToolBar::EnableTool(int tool_id
, bool enable
)
565 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
566 wxCHECK_RET(tool
!= NULL
, "Invalid tool id");
569 if(tool
->state
& wxRIBBON_TOOLBAR_TOOL_DISABLED
)
571 tool
->state
&= ~wxRIBBON_TOOLBAR_TOOL_DISABLED
;
577 if((tool
->state
& wxRIBBON_TOOLBAR_TOOL_DISABLED
)==0)
579 tool
->state
|= wxRIBBON_TOOLBAR_TOOL_DISABLED
;
585 void wxRibbonToolBar::ToggleTool(int tool_id
, bool checked
)
587 wxRibbonToolBarToolBase
* tool
= FindById(tool_id
);
588 wxCHECK_RET(tool
!= NULL
, "Invalid tool id");
591 if((tool
->state
& wxRIBBON_TOOLBAR_TOOL_TOGGLED
) == 0)
593 tool
->state
|= wxRIBBON_TOOLBAR_TOOL_TOGGLED
;
599 if(tool
->state
& wxRIBBON_TOOLBAR_TOOL_TOGGLED
)
601 tool
->state
&= ~wxRIBBON_TOOLBAR_TOOL_TOGGLED
;
607 static int GetSizeInOrientation(wxSize size
, wxOrientation orientation
)
611 case wxHORIZONTAL
: return size
.GetWidth();
612 case wxVERTICAL
: return size
.GetHeight();
613 case wxBOTH
: return size
.GetWidth() * size
.GetHeight();
618 wxSize
wxRibbonToolBar::DoGetNextSmallerSize(wxOrientation direction
,
619 wxSize relative_to
) const
621 wxSize
result(relative_to
);
624 for(nrows
= m_nrows_min
; nrows
<= m_nrows_max
; ++nrows
)
626 wxSize
size(m_sizes
[nrows
- m_nrows_min
]);
627 wxSize
original(size
);
631 if(size
.GetWidth() < relative_to
.GetWidth()
632 && size
.GetHeight() <= relative_to
.GetHeight())
634 size
.SetHeight(relative_to
.GetHeight());
639 if(size
.GetWidth() <= relative_to
.GetWidth()
640 && size
.GetHeight() < relative_to
.GetHeight())
642 size
.SetWidth(relative_to
.GetWidth());
647 if(size
.GetWidth() < relative_to
.GetWidth()
648 && size
.GetHeight() < relative_to
.GetHeight())
654 if(GetSizeInOrientation(original
, direction
) > area
)
657 area
= GetSizeInOrientation(original
, direction
);
663 wxSize
wxRibbonToolBar::DoGetNextLargerSize(wxOrientation direction
,
664 wxSize relative_to
) const
666 // Pick the smallest of our sizes which are larger than the given size
667 wxSize
result(relative_to
);
670 for(nrows
= m_nrows_min
; nrows
<= m_nrows_max
; ++nrows
)
672 wxSize
size(m_sizes
[nrows
- m_nrows_min
]);
673 wxSize
original(size
);
677 if(size
.GetWidth() > relative_to
.GetWidth()
678 && size
.GetHeight() <= relative_to
.GetHeight())
680 size
.SetHeight(relative_to
.GetHeight());
685 if(size
.GetWidth() <= relative_to
.GetWidth()
686 && size
.GetHeight() > relative_to
.GetHeight())
688 size
.SetWidth(relative_to
.GetWidth());
693 if(size
.GetWidth() > relative_to
.GetWidth()
694 && size
.GetHeight() > relative_to
.GetHeight())
700 if(GetSizeInOrientation(original
, direction
) < area
)
703 area
= GetSizeInOrientation(original
, direction
);
710 void wxRibbonToolBar::SetRows(int nMin
, int nMax
)
716 wxASSERT(nMin
<= nMax
);
722 m_sizes
= new wxSize
[m_nrows_max
- m_nrows_min
+ 1];
723 for(int i
= m_nrows_min
; i
<= m_nrows_max
; ++i
)
724 m_sizes
[i
- m_nrows_min
] = wxSize(0, 0);
729 bool wxRibbonToolBar::Realize()
734 // Calculate the size of each group and the position/size of each tool
736 size_t group_count
= m_groups
.GetCount();
738 for(g
= 0; g
< group_count
; ++g
)
740 wxRibbonToolBarToolBase
* prev
= NULL
;
741 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
742 size_t tool_count
= group
->tools
.GetCount();
744 for(t
= 0; t
< tool_count
; ++t
)
746 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
747 tool
->size
= m_art
->GetToolSize(temp_dc
, this,
748 tool
->bitmap
.GetSize(), tool
->kind
, t
== 0,
749 t
== (tool_count
- 1), &tool
->dropdown
);
751 tool
->state
|= wxRIBBON_TOOLBAR_TOOL_FIRST
;
752 if(t
== tool_count
- 1)
753 tool
->state
|= wxRIBBON_TOOLBAR_TOOL_LAST
;
754 if(tool
->size
.GetHeight() > tallest
)
755 tallest
= tool
->size
.GetHeight();
758 tool
->position
= prev
->position
;
759 tool
->position
.x
+= prev
->size
.x
;
763 tool
->position
= wxPoint(0, 0);
768 group
->size
= wxSize(0, 0);
771 group
->size
= wxSize(prev
->position
.x
+ prev
->size
.x
, tallest
);
772 for(t
= 0; t
< tool_count
; ++t
)
773 group
->tools
.Item(t
)->size
.SetHeight(tallest
);
777 // Calculate the minimum size for each possible number of rows
779 int sep
= m_art
->GetMetric(wxRIBBON_ART_TOOL_GROUP_SEPARATION_SIZE
);
780 int smallest_area
= INT_MAX
;
781 wxSize
* row_sizes
= new wxSize
[m_nrows_max
];
782 wxOrientation major_axis
= m_art
->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL
?
783 wxVERTICAL
: wxHORIZONTAL
;
785 SetMinSize(wxSize(0, 0));
786 wxSize
minSize(INT_MAX
, INT_MAX
);
788 // See if we're sizing flexibly (i.e. wrapping), and set min size differently
789 bool sizingFlexibly
= false;
790 wxRibbonPanel
* panel
= wxDynamicCast(GetParent(), wxRibbonPanel
);
791 if (panel
&& (panel
->GetFlags() & wxRIBBON_PANEL_FLEXIBLE
))
792 sizingFlexibly
= true;
794 // Without this, there will be redundant horizontal space because SetMinSize will
795 // use the smallest possible height (and therefore largest width).
797 major_axis
= wxHORIZONTAL
;
799 for(nrows
= m_nrows_min
; nrows
<= m_nrows_max
; ++nrows
)
801 for(r
= 0; r
< nrows
; ++r
)
802 row_sizes
[r
] = wxSize(0, 0);
803 for(g
= 0; g
< group_count
; ++g
)
805 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
806 int shortest_row
= 0;
807 for(r
= 1; r
< nrows
; ++r
)
809 if(row_sizes
[r
].GetWidth() < row_sizes
[shortest_row
].GetWidth())
812 row_sizes
[shortest_row
].x
+= group
->size
.x
+ sep
;
813 if(group
->size
.y
> row_sizes
[shortest_row
].y
)
814 row_sizes
[shortest_row
].y
= group
->size
.y
;
817 for(r
= 0; r
< nrows
; ++r
)
819 if(row_sizes
[r
].GetWidth() != 0)
820 row_sizes
[r
].DecBy(sep
, 0);
821 if(row_sizes
[r
].GetWidth() > size
.GetWidth())
822 size
.SetWidth(row_sizes
[r
].GetWidth());
823 size
.IncBy(0, row_sizes
[r
].y
);
825 m_sizes
[nrows
- m_nrows_min
] = size
;
827 if(GetSizeInOrientation(size
, major_axis
) < smallest_area
)
829 smallest_area
= GetSizeInOrientation(size
, major_axis
);
835 if (size
.x
< minSize
.x
)
837 if (size
.y
< minSize
.y
)
844 // Give it the min size in either direction regardless of row,
845 // so that we're able to vary the size of the panel according to
846 // the space the toolbar takes up.
851 // Position the groups
852 wxSizeEvent
dummy_event(GetSize());
858 void wxRibbonToolBar::OnSize(wxSizeEvent
& evt
)
863 // Choose row count with largest possible area
864 wxSize size
= evt
.GetSize();
865 int row_count
= m_nrows_max
;
866 wxOrientation major_axis
= m_art
->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL
?
867 wxVERTICAL
: wxHORIZONTAL
;
869 // See if we're sizing flexibly, and set min size differently
870 bool sizingFlexibly
= false;
871 wxRibbonPanel
* panel
= wxDynamicCast(GetParent(), wxRibbonPanel
);
872 if (panel
&& (panel
->GetFlags() & wxRIBBON_PANEL_FLEXIBLE
))
873 sizingFlexibly
= true;
875 // Without this, there will be redundant horizontal space because SetMinSize will
876 // use the smallest possible height (and therefore largest width).
878 major_axis
= wxHORIZONTAL
;
880 wxSize bestSize
= m_sizes
[0];
882 if(m_nrows_max
!= m_nrows_min
)
885 for(int i
= 0; i
<= m_nrows_max
- m_nrows_min
; ++i
)
887 if(m_sizes
[i
].x
<= size
.x
&& m_sizes
[i
].y
<= size
.y
&&
888 GetSizeInOrientation(m_sizes
[i
], major_axis
) > area
)
890 area
= GetSizeInOrientation(m_sizes
[i
], major_axis
);
891 row_count
= m_nrows_min
+ i
;
892 bestSize
= m_sizes
[i
];
897 // Assign groups to rows and calculate row widths
898 wxSize
* row_sizes
= new wxSize
[row_count
];
899 int sep
= m_art
->GetMetric(wxRIBBON_ART_TOOL_GROUP_SEPARATION_SIZE
);
902 for(r
= 0; r
< row_count
; ++r
)
903 row_sizes
[r
] = wxSize(0, 0);
905 size_t group_count
= m_groups
.GetCount();
906 for(g
= 0; g
< group_count
; ++g
)
908 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
909 int shortest_row
= 0;
910 for(r
= 1; r
< row_count
; ++r
)
912 if(row_sizes
[r
].GetWidth() < row_sizes
[shortest_row
].GetWidth())
915 group
->position
= wxPoint(row_sizes
[shortest_row
].x
, shortest_row
);
916 row_sizes
[shortest_row
].x
+= group
->size
.x
+ sep
;
917 if(group
->size
.y
> row_sizes
[shortest_row
].y
)
918 row_sizes
[shortest_row
].y
= group
->size
.y
;
921 // Calculate row positions
922 int total_height
= 0;
923 for(r
= 0; r
< row_count
; ++r
)
924 total_height
+= row_sizes
[r
].GetHeight();
925 int rowsep
= (size
.GetHeight() - total_height
) / (row_count
+ 1);
926 int* rowypos
= new int[row_count
];
928 for(r
= 1; r
< row_count
; ++r
)
930 rowypos
[r
] = rowypos
[r
- 1] + row_sizes
[r
- 1].GetHeight() + rowsep
;
933 // Set group y positions
934 for(g
= 0; g
< group_count
; ++g
)
936 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
937 group
->position
.y
= rowypos
[group
->position
.y
];
944 // Finds the best width and height given the parents' width and height
945 wxSize
wxRibbonToolBar::GetBestSizeForParentSize(const wxSize
& parentSize
) const
950 // Choose row count with largest possible area
951 wxSize size
= parentSize
;
952 int row_count
= m_nrows_max
;
953 wxOrientation major_axis
= m_art
->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL
?
954 wxVERTICAL
: wxHORIZONTAL
;
956 // A toolbar should maximize its width whether vertical or horizontal, so
957 // force the major axis to be horizontal. Without this, there will be
958 // redundant horizontal space.
959 major_axis
= wxHORIZONTAL
;
960 wxSize bestSize
= m_sizes
[0];
962 if(m_nrows_max
!= m_nrows_min
)
965 for(int i
= 0; i
<= m_nrows_max
- m_nrows_min
; ++i
)
967 if(m_sizes
[i
].x
<= size
.x
&& m_sizes
[i
].y
<= size
.y
&&
968 GetSizeInOrientation(m_sizes
[i
], major_axis
) > area
)
970 area
= GetSizeInOrientation(m_sizes
[i
], major_axis
);
971 row_count
= m_nrows_min
+ i
;
972 bestSize
= m_sizes
[i
];
979 wxSize
wxRibbonToolBar::DoGetBestSize() const
984 void wxRibbonToolBar::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
986 // All painting done in main paint handler to minimise flicker
989 void wxRibbonToolBar::OnPaint(wxPaintEvent
& WXUNUSED(evt
))
991 wxAutoBufferedPaintDC
dc(this);
995 m_art
->DrawToolBarBackground(dc
, this, GetSize());
997 size_t group_count
= m_groups
.GetCount();
999 for(g
= 0; g
< group_count
; ++g
)
1001 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
1002 size_t tool_count
= group
->tools
.GetCount();
1005 m_art
->DrawToolGroupBackground(dc
, this,
1006 wxRect(group
->position
, group
->size
));
1007 for(t
= 0; t
< tool_count
; ++t
)
1009 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
1010 wxRect
rect(group
->position
+ tool
->position
, tool
->size
);
1011 if(tool
->state
& wxRIBBON_TOOLBAR_TOOL_DISABLED
)
1012 m_art
->DrawTool(dc
, this, rect
, tool
->bitmap_disabled
,
1013 tool
->kind
, tool
->state
);
1015 m_art
->DrawTool(dc
, this, rect
, tool
->bitmap
, tool
->kind
,
1022 void wxRibbonToolBar::OnMouseMove(wxMouseEvent
& evt
)
1024 wxPoint
pos(evt
.GetPosition());
1025 wxRibbonToolBarToolBase
*new_hover
= NULL
;
1027 size_t group_count
= m_groups
.GetCount();
1029 for(g
= 0; g
< group_count
; ++g
)
1031 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
1032 if(group
->position
.x
<= pos
.x
&& pos
.x
< group
->position
.x
+ group
->size
.x
1033 && group
->position
.y
<= pos
.y
&& pos
.y
< group
->position
.y
+ group
->size
.y
)
1035 size_t tool_count
= group
->tools
.GetCount();
1036 pos
-= group
->position
;
1037 for(t
= 0; t
< tool_count
; ++t
)
1039 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
1040 if(tool
->position
.x
<= pos
.x
&& pos
.x
< tool
->position
.x
+ tool
->size
.x
1041 && tool
->position
.y
<= pos
.y
&& pos
.y
< tool
->position
.y
+ tool
->size
.y
)
1043 pos
-= tool
->position
;
1055 SetToolTip(new_hover
->help_string
);
1057 else if(GetToolTip())
1063 if(new_hover
&& new_hover
->state
& wxRIBBON_TOOLBAR_TOOL_DISABLED
)
1065 new_hover
= NULL
; // A disabled tool can not be hilighted
1068 if(new_hover
!= m_hover_tool
)
1072 m_hover_tool
->state
&= ~(wxRIBBON_TOOLBAR_TOOL_HOVER_MASK
1073 | wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK
);
1075 m_hover_tool
= new_hover
;
1078 long what
= wxRIBBON_TOOLBAR_TOOL_NORMAL_HOVERED
;
1079 if(new_hover
->dropdown
.Contains(pos
))
1080 what
= wxRIBBON_TOOLBAR_TOOL_DROPDOWN_HOVERED
;
1082 new_hover
->state
|= what
;
1084 if(new_hover
== m_active_tool
)
1086 new_hover
->state
&= ~wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK
;
1087 new_hover
->state
|= (what
<< 2);
1092 else if(m_hover_tool
&& m_hover_tool
->kind
== wxRIBBON_BUTTON_HYBRID
)
1094 long newstate
= m_hover_tool
->state
&~wxRIBBON_TOOLBAR_TOOL_HOVER_MASK
;
1095 long what
= wxRIBBON_TOOLBAR_TOOL_NORMAL_HOVERED
;
1096 if(m_hover_tool
->dropdown
.Contains(pos
))
1097 what
= wxRIBBON_TOOLBAR_TOOL_DROPDOWN_HOVERED
;
1099 if(newstate
!= m_hover_tool
->state
)
1101 m_hover_tool
->state
= newstate
;
1102 if(m_hover_tool
== m_active_tool
)
1104 m_hover_tool
->state
&= ~wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK
;
1105 m_hover_tool
->state
|= (what
<< 2);
1112 void wxRibbonToolBar::OnMouseDown(wxMouseEvent
& evt
)
1117 m_active_tool
= m_hover_tool
;
1118 m_active_tool
->state
|=
1119 (m_active_tool
->state
& wxRIBBON_TOOLBAR_TOOL_HOVER_MASK
) << 2;
1124 void wxRibbonToolBar::OnMouseLeave(wxMouseEvent
& WXUNUSED(evt
))
1128 m_hover_tool
->state
&= ~wxRIBBON_TOOLBAR_TOOL_HOVER_MASK
;
1129 m_hover_tool
= NULL
;
1134 void wxRibbonToolBar::OnMouseUp(wxMouseEvent
& WXUNUSED(evt
))
1138 if(m_active_tool
->state
& wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK
)
1140 wxEventType evt_type
= wxEVT_COMMAND_RIBBONTOOL_CLICKED
;
1141 if(m_active_tool
->state
& wxRIBBON_TOOLBAR_TOOL_DROPDOWN_ACTIVE
)
1142 evt_type
= wxEVT_COMMAND_RIBBONTOOL_DROPDOWN_CLICKED
;
1143 wxRibbonToolBarEvent
notification(evt_type
, m_active_tool
->id
);
1144 if(m_active_tool
->kind
== wxRIBBON_BUTTON_TOGGLE
)
1146 m_active_tool
->state
^=
1147 wxRIBBON_BUTTONBAR_BUTTON_TOGGLED
;
1148 notification
.SetInt(m_active_tool
->state
&
1149 wxRIBBON_BUTTONBAR_BUTTON_TOGGLED
);
1151 notification
.SetEventObject(this);
1152 notification
.SetBar(this);
1153 ProcessEvent(notification
);
1156 // Notice that m_active_tool could have been reset by the event handler
1157 // above so we need to test it again.
1160 m_active_tool
->state
&= ~wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK
;
1161 m_active_tool
= NULL
;
1167 void wxRibbonToolBar::OnMouseEnter(wxMouseEvent
& evt
)
1169 if(m_active_tool
&& !evt
.LeftIsDown())
1171 m_active_tool
= NULL
;
1175 void wxRibbonToolBar::UpdateWindowUI(long flags
)
1177 wxWindowBase::UpdateWindowUI(flags
);
1179 // don't waste time updating state of tools in a hidden toolbar
1183 size_t group_count
= m_groups
.GetCount();
1185 for(g
= 0; g
< group_count
; ++g
)
1187 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
1188 size_t tool_count
= group
->tools
.GetCount();
1189 for(t
= 0; t
< tool_count
; ++t
)
1191 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
1194 wxUpdateUIEvent
event(id
);
1195 event
.SetEventObject(this);
1197 if ( ProcessWindowEvent(event
) )
1199 if ( event
.GetSetEnabled() )
1200 EnableTool(id
, event
.GetEnabled());
1201 if ( event
.GetSetChecked() )
1202 ToggleTool(id
, event
.GetChecked());
1208 bool wxRibbonToolBarEvent::PopupMenu(wxMenu
* menu
)
1210 wxPoint pos
= wxDefaultPosition
;
1211 if(m_bar
->m_active_tool
)
1213 // Find the group which contains the tool
1214 size_t group_count
= m_bar
->m_groups
.GetCount();
1216 for(g
= 0; g
< group_count
; ++g
)
1218 wxRibbonToolBarToolGroup
* group
= m_bar
->m_groups
.Item(g
);
1219 size_t tool_count
= group
->tools
.GetCount();
1220 for(t
= 0; t
< tool_count
; ++t
)
1222 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
1223 if(tool
== m_bar
->m_active_tool
)
1225 pos
= group
->position
;
1226 pos
+= tool
->position
;
1227 pos
.y
+= tool
->size
.GetHeight();
1234 return m_bar
->PopupMenu(menu
, pos
);
1237 #endif // wxUSE_RIBBON