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
;
784 SetMinSize(wxSize(0, 0));
785 for(nrows
= m_nrows_min
; nrows
<= m_nrows_max
; ++nrows
)
787 for(r
= 0; r
< nrows
; ++r
)
788 row_sizes
[r
] = wxSize(0, 0);
789 for(g
= 0; g
< group_count
; ++g
)
791 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
792 int shortest_row
= 0;
793 for(r
= 1; r
< nrows
; ++r
)
795 if(row_sizes
[r
].GetWidth() < row_sizes
[shortest_row
].GetWidth())
798 row_sizes
[shortest_row
].x
+= group
->size
.x
+ sep
;
799 if(group
->size
.y
> row_sizes
[shortest_row
].y
)
800 row_sizes
[shortest_row
].y
= group
->size
.y
;
803 for(r
= 0; r
< nrows
; ++r
)
805 if(row_sizes
[r
].GetWidth() != 0)
806 row_sizes
[r
].DecBy(sep
, 0);
807 if(row_sizes
[r
].GetWidth() > size
.GetWidth())
808 size
.SetWidth(row_sizes
[r
].GetWidth());
809 size
.IncBy(0, row_sizes
[r
].y
);
811 m_sizes
[nrows
- m_nrows_min
] = size
;
812 if(GetSizeInOrientation(size
, major_axis
) < smallest_area
)
815 smallest_area
= GetSizeInOrientation(size
, major_axis
);
820 // Position the groups
821 wxSizeEvent
dummy_event(GetSize());
827 void wxRibbonToolBar::OnSize(wxSizeEvent
& evt
)
832 // Choose row count with largest possible area
833 wxSize size
= evt
.GetSize();
834 int row_count
= m_nrows_max
;
835 wxOrientation major_axis
= m_art
->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL
?
836 wxVERTICAL
: wxHORIZONTAL
;
837 if(m_nrows_max
!= m_nrows_min
)
840 for(int i
= 0; i
<= m_nrows_max
- m_nrows_min
; ++i
)
842 if(m_sizes
[i
].x
<= size
.x
&& m_sizes
[i
].y
<= size
.y
&&
843 GetSizeInOrientation(m_sizes
[i
], major_axis
) > area
)
845 area
= GetSizeInOrientation(m_sizes
[i
], major_axis
);
846 row_count
= m_nrows_min
+ i
;
851 // Assign groups to rows and calculate row widths
852 wxSize
* row_sizes
= new wxSize
[row_count
];
853 int sep
= m_art
->GetMetric(wxRIBBON_ART_TOOL_GROUP_SEPARATION_SIZE
);
856 for(r
= 0; r
< row_count
; ++r
)
857 row_sizes
[r
] = wxSize(0, 0);
859 size_t group_count
= m_groups
.GetCount();
860 for(g
= 0; g
< group_count
; ++g
)
862 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
863 int shortest_row
= 0;
864 for(r
= 1; r
< row_count
; ++r
)
866 if(row_sizes
[r
].GetWidth() < row_sizes
[shortest_row
].GetWidth())
869 group
->position
= wxPoint(row_sizes
[shortest_row
].x
, shortest_row
);
870 row_sizes
[shortest_row
].x
+= group
->size
.x
+ sep
;
871 if(group
->size
.y
> row_sizes
[shortest_row
].y
)
872 row_sizes
[shortest_row
].y
= group
->size
.y
;
875 // Calculate row positions
876 int total_height
= 0;
877 for(r
= 0; r
< row_count
; ++r
)
878 total_height
+= row_sizes
[r
].GetHeight();
879 int rowsep
= (size
.GetHeight() - total_height
) / (row_count
+ 1);
880 int* rowypos
= new int[row_count
];
882 for(r
= 1; r
< row_count
; ++r
)
884 rowypos
[r
] = rowypos
[r
- 1] + row_sizes
[r
- 1].GetHeight() + rowsep
;
887 // Set group y positions
888 for(g
= 0; g
< group_count
; ++g
)
890 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
891 group
->position
.y
= rowypos
[group
->position
.y
];
898 wxSize
wxRibbonToolBar::DoGetBestSize() const
903 void wxRibbonToolBar::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
905 // All painting done in main paint handler to minimise flicker
908 void wxRibbonToolBar::OnPaint(wxPaintEvent
& WXUNUSED(evt
))
910 wxAutoBufferedPaintDC
dc(this);
914 m_art
->DrawToolBarBackground(dc
, this, GetSize());
916 size_t group_count
= m_groups
.GetCount();
918 for(g
= 0; g
< group_count
; ++g
)
920 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
921 size_t tool_count
= group
->tools
.GetCount();
924 m_art
->DrawToolGroupBackground(dc
, this,
925 wxRect(group
->position
, group
->size
));
926 for(t
= 0; t
< tool_count
; ++t
)
928 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
929 wxRect
rect(group
->position
+ tool
->position
, tool
->size
);
930 if(tool
->state
& wxRIBBON_TOOLBAR_TOOL_DISABLED
)
931 m_art
->DrawTool(dc
, this, rect
, tool
->bitmap_disabled
,
932 tool
->kind
, tool
->state
);
934 m_art
->DrawTool(dc
, this, rect
, tool
->bitmap
, tool
->kind
,
941 void wxRibbonToolBar::OnMouseMove(wxMouseEvent
& evt
)
943 wxPoint
pos(evt
.GetPosition());
944 wxRibbonToolBarToolBase
*new_hover
= NULL
;
946 size_t group_count
= m_groups
.GetCount();
948 for(g
= 0; g
< group_count
; ++g
)
950 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
951 if(group
->position
.x
<= pos
.x
&& pos
.x
< group
->position
.x
+ group
->size
.x
952 && group
->position
.y
<= pos
.y
&& pos
.y
< group
->position
.y
+ group
->size
.y
)
954 size_t tool_count
= group
->tools
.GetCount();
955 pos
-= group
->position
;
956 for(t
= 0; t
< tool_count
; ++t
)
958 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
959 if(tool
->position
.x
<= pos
.x
&& pos
.x
< tool
->position
.x
+ tool
->size
.x
960 && tool
->position
.y
<= pos
.y
&& pos
.y
< tool
->position
.y
+ tool
->size
.y
)
962 pos
-= tool
->position
;
974 SetToolTip(new_hover
->help_string
);
976 else if(GetToolTip())
982 if(new_hover
&& new_hover
->state
& wxRIBBON_TOOLBAR_TOOL_DISABLED
)
984 new_hover
= NULL
; // A disabled tool can not be hilighted
987 if(new_hover
!= m_hover_tool
)
991 m_hover_tool
->state
&= ~(wxRIBBON_TOOLBAR_TOOL_HOVER_MASK
992 | wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK
);
994 m_hover_tool
= new_hover
;
997 long what
= wxRIBBON_TOOLBAR_TOOL_NORMAL_HOVERED
;
998 if(new_hover
->dropdown
.Contains(pos
))
999 what
= wxRIBBON_TOOLBAR_TOOL_DROPDOWN_HOVERED
;
1001 new_hover
->state
|= what
;
1003 if(new_hover
== m_active_tool
)
1005 new_hover
->state
&= ~wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK
;
1006 new_hover
->state
|= (what
<< 2);
1011 else if(m_hover_tool
&& m_hover_tool
->kind
== wxRIBBON_BUTTON_HYBRID
)
1013 long newstate
= m_hover_tool
->state
&~wxRIBBON_TOOLBAR_TOOL_HOVER_MASK
;
1014 long what
= wxRIBBON_TOOLBAR_TOOL_NORMAL_HOVERED
;
1015 if(m_hover_tool
->dropdown
.Contains(pos
))
1016 what
= wxRIBBON_TOOLBAR_TOOL_DROPDOWN_HOVERED
;
1018 if(newstate
!= m_hover_tool
->state
)
1020 m_hover_tool
->state
= newstate
;
1021 if(m_hover_tool
== m_active_tool
)
1023 m_hover_tool
->state
&= ~wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK
;
1024 m_hover_tool
->state
|= (what
<< 2);
1031 void wxRibbonToolBar::OnMouseDown(wxMouseEvent
& evt
)
1036 m_active_tool
= m_hover_tool
;
1037 m_active_tool
->state
|=
1038 (m_active_tool
->state
& wxRIBBON_TOOLBAR_TOOL_HOVER_MASK
) << 2;
1043 void wxRibbonToolBar::OnMouseLeave(wxMouseEvent
& WXUNUSED(evt
))
1047 m_hover_tool
->state
&= ~wxRIBBON_TOOLBAR_TOOL_HOVER_MASK
;
1048 m_hover_tool
= NULL
;
1053 void wxRibbonToolBar::OnMouseUp(wxMouseEvent
& WXUNUSED(evt
))
1057 if(m_active_tool
->state
& wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK
)
1059 wxEventType evt_type
= wxEVT_COMMAND_RIBBONTOOL_CLICKED
;
1060 if(m_active_tool
->state
& wxRIBBON_TOOLBAR_TOOL_DROPDOWN_ACTIVE
)
1061 evt_type
= wxEVT_COMMAND_RIBBONTOOL_DROPDOWN_CLICKED
;
1062 wxRibbonToolBarEvent
notification(evt_type
, m_active_tool
->id
);
1063 if(m_active_tool
->kind
== wxRIBBON_BUTTON_TOGGLE
)
1065 m_active_tool
->state
^=
1066 wxRIBBON_BUTTONBAR_BUTTON_TOGGLED
;
1067 notification
.SetInt(m_active_tool
->state
&
1068 wxRIBBON_BUTTONBAR_BUTTON_TOGGLED
);
1070 notification
.SetEventObject(this);
1071 notification
.SetBar(this);
1072 ProcessEvent(notification
);
1075 // Notice that m_active_tool could have been reset by the event handler
1076 // above so we need to test it again.
1079 m_active_tool
->state
&= ~wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK
;
1080 m_active_tool
= NULL
;
1086 void wxRibbonToolBar::OnMouseEnter(wxMouseEvent
& evt
)
1088 if(m_active_tool
&& !evt
.LeftIsDown())
1090 m_active_tool
= NULL
;
1094 void wxRibbonToolBar::UpdateWindowUI(long flags
)
1096 wxWindowBase::UpdateWindowUI(flags
);
1098 // don't waste time updating state of tools in a hidden toolbar
1102 size_t group_count
= m_groups
.GetCount();
1104 for(g
= 0; g
< group_count
; ++g
)
1106 wxRibbonToolBarToolGroup
* group
= m_groups
.Item(g
);
1107 size_t tool_count
= group
->tools
.GetCount();
1108 for(t
= 0; t
< tool_count
; ++t
)
1110 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
1113 wxUpdateUIEvent
event(id
);
1114 event
.SetEventObject(this);
1116 if ( ProcessWindowEvent(event
) )
1118 if ( event
.GetSetEnabled() )
1119 EnableTool(id
, event
.GetEnabled());
1120 if ( event
.GetSetChecked() )
1121 ToggleTool(id
, event
.GetChecked());
1127 bool wxRibbonToolBarEvent::PopupMenu(wxMenu
* menu
)
1129 wxPoint pos
= wxDefaultPosition
;
1130 if(m_bar
->m_active_tool
)
1132 // Find the group which contains the tool
1133 size_t group_count
= m_bar
->m_groups
.GetCount();
1135 for(g
= 0; g
< group_count
; ++g
)
1137 wxRibbonToolBarToolGroup
* group
= m_bar
->m_groups
.Item(g
);
1138 size_t tool_count
= group
->tools
.GetCount();
1139 for(t
= 0; t
< tool_count
; ++t
)
1141 wxRibbonToolBarToolBase
* tool
= group
->tools
.Item(t
);
1142 if(tool
== m_bar
->m_active_tool
)
1144 pos
= group
->position
;
1145 pos
+= tool
->position
;
1146 pos
.y
+= tool
->size
.GetHeight();
1153 return m_bar
->PopupMenu(menu
, pos
);
1156 #endif // wxUSE_RIBBON