]> git.saurik.com Git - wxWidgets.git/blob - src/ribbon/toolbar.cpp
minor cleanup
[wxWidgets.git] / src / ribbon / toolbar.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/ribbon/toolbar.cpp
3 // Purpose: Ribbon-style tool bar
4 // Author: Peter Cawley
5 // Modified by:
6 // Created: 2009-07-06
7 // RCS-ID: $Id$
8 // Copyright: (C) Peter Cawley
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17
18 #include "wx/ribbon/toolbar.h"
19
20 #if wxUSE_RIBBON
21
22 #include "wx/ribbon/art.h"
23 #include "wx/ribbon/bar.h"
24 #include "wx/dcbuffer.h"
25
26 #ifndef WX_PRECOMP
27 #endif
28
29 #ifdef __WXMSW__
30 #include "wx/msw/private.h"
31 #endif
32
33 class wxRibbonToolBarToolBase
34 {
35 public:
36 wxString help_string;
37 wxBitmap bitmap;
38 wxBitmap bitmap_disabled;
39 wxRect dropdown;
40 wxPoint position;
41 wxSize size;
42 wxObject* client_data;
43 int id;
44 wxRibbonButtonKind kind;
45 long state;
46 };
47
48 WX_DEFINE_ARRAY(wxRibbonToolBarToolBase*, wxArrayRibbonToolBarToolBase);
49
50 class wxRibbonToolBarToolGroup
51 {
52 public:
53 // To identify the group as a wxRibbonToolBarToolBase*
54 wxRibbonToolBarToolBase dummy_tool;
55
56 wxArrayRibbonToolBarToolBase tools;
57 wxPoint position;
58 wxSize size;
59 };
60
61 wxDEFINE_EVENT(wxEVT_COMMAND_RIBBONTOOL_CLICKED, wxRibbonToolBarEvent);
62 wxDEFINE_EVENT(wxEVT_COMMAND_RIBBONTOOL_DROPDOWN_CLICKED, wxRibbonToolBarEvent);
63
64 IMPLEMENT_DYNAMIC_CLASS(wxRibbonToolBarEvent, wxCommandEvent)
65 IMPLEMENT_CLASS(wxRibbonToolBar, wxRibbonControl)
66
67 BEGIN_EVENT_TABLE(wxRibbonToolBar, wxRibbonControl)
68 EVT_ENTER_WINDOW(wxRibbonToolBar::OnMouseEnter)
69 EVT_ERASE_BACKGROUND(wxRibbonToolBar::OnEraseBackground)
70 EVT_LEAVE_WINDOW(wxRibbonToolBar::OnMouseLeave)
71 EVT_LEFT_DOWN(wxRibbonToolBar::OnMouseDown)
72 EVT_LEFT_UP(wxRibbonToolBar::OnMouseUp)
73 EVT_MOTION(wxRibbonToolBar::OnMouseMove)
74 EVT_PAINT(wxRibbonToolBar::OnPaint)
75 EVT_SIZE(wxRibbonToolBar::OnSize)
76 END_EVENT_TABLE()
77
78 wxRibbonToolBar::wxRibbonToolBar()
79 {
80 }
81
82 wxRibbonToolBar::wxRibbonToolBar(wxWindow* parent,
83 wxWindowID id,
84 const wxPoint& pos,
85 const wxSize& size,
86 long style)
87 : wxRibbonControl(parent, id, pos, size, wxBORDER_NONE)
88 {
89 CommonInit(style);
90 }
91
92 bool wxRibbonToolBar::Create(wxWindow* parent,
93 wxWindowID id,
94 const wxPoint& pos,
95 const wxSize& size,
96 long style)
97 {
98 if(!wxRibbonControl::Create(parent, id, pos, size, wxBORDER_NONE))
99 {
100 return false;
101 }
102
103 CommonInit(style);
104 return true;
105 }
106
107 void wxRibbonToolBar::CommonInit(long WXUNUSED(style))
108 {
109 AppendGroup();
110 m_hover_tool = NULL;
111 m_active_tool = NULL;
112 m_nrows_min = 1;
113 m_nrows_max = 1;
114 m_sizes = new wxSize[1];
115 m_sizes[0] = wxSize(0, 0);
116 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
117 }
118
119 wxRibbonToolBar::~wxRibbonToolBar()
120 {
121 size_t count = m_groups.GetCount();
122 size_t i, t;
123 for(i = 0; i < count; ++i)
124 {
125 wxRibbonToolBarToolGroup* group = m_groups.Item(i);
126 size_t tool_count = group->tools.GetCount();
127 for(t = 0; t < tool_count; ++t)
128 {
129 wxRibbonToolBarToolBase* tool = group->tools.Item(t);
130 delete tool;
131 }
132 delete group;
133 }
134 m_groups.Clear();
135 delete[] m_sizes;
136 }
137
138 wxRibbonToolBarToolBase* wxRibbonToolBar::AddTool(
139 int tool_id,
140 const wxBitmap& bitmap,
141 const wxString& help_string,
142 wxRibbonButtonKind kind)
143 {
144 return AddTool(tool_id, bitmap, wxNullBitmap, help_string, kind, NULL);
145 }
146
147 wxRibbonToolBarToolBase* wxRibbonToolBar::AddDropdownTool(
148 int tool_id,
149 const wxBitmap& bitmap,
150 const wxString& help_string)
151 {
152 return AddTool(tool_id, bitmap, wxNullBitmap, help_string,
153 wxRIBBON_BUTTON_DROPDOWN, NULL);
154 }
155
156 wxRibbonToolBarToolBase* wxRibbonToolBar::AddHybridTool(
157 int tool_id,
158 const wxBitmap& bitmap,
159 const wxString& help_string)
160 {
161 return AddTool(tool_id, bitmap, wxNullBitmap, help_string,
162 wxRIBBON_BUTTON_HYBRID, NULL);
163 }
164
165 wxRibbonToolBarToolBase* wxRibbonToolBar::AddTool(
166 int tool_id,
167 const wxBitmap& bitmap,
168 const wxBitmap& bitmap_disabled,
169 const wxString& help_string,
170 wxRibbonButtonKind kind,
171 wxObject* client_data)
172 {
173 wxASSERT(bitmap.IsOk());
174
175 wxRibbonToolBarToolBase* tool = new wxRibbonToolBarToolBase;
176 tool->id = tool_id;
177 tool->bitmap = bitmap;
178 if(bitmap_disabled.IsOk())
179 {
180 wxASSERT(bitmap.GetSize() == bitmap_disabled.GetSize());
181 tool->bitmap_disabled = bitmap_disabled;
182 }
183 else
184 tool->bitmap_disabled = MakeDisabledBitmap(bitmap);
185 tool->help_string = help_string;
186 tool->kind = kind;
187 tool->client_data = client_data;
188 tool->position = wxPoint(0, 0);
189 tool->size = wxSize(0, 0);
190 tool->state = 0;
191
192 m_groups.Last()->tools.Add(tool);
193 return tool;
194 }
195
196 wxRibbonToolBarToolBase* wxRibbonToolBar::AddSeparator()
197 {
198 if(m_groups.Last()->tools.IsEmpty())
199 return NULL;
200
201 AppendGroup();
202 return &m_groups.Last()->dummy_tool;
203 }
204
205 wxBitmap wxRibbonToolBar::MakeDisabledBitmap(const wxBitmap& original)
206 {
207 wxImage img(original.ConvertToImage());
208 return wxBitmap(img.ConvertToGreyscale());
209 }
210
211 void wxRibbonToolBar::AppendGroup()
212 {
213 wxRibbonToolBarToolGroup* group = new wxRibbonToolBarToolGroup;
214 group->position = wxPoint(0, 0);
215 group->size = wxSize(0, 0);
216 m_groups.Add(group);
217 }
218
219 bool wxRibbonToolBar::IsSizingContinuous() const
220 {
221 return false;
222 }
223
224 static int GetSizeInOrientation(wxSize size, wxOrientation orientation)
225 {
226 switch(orientation)
227 {
228 case wxHORIZONTAL: return size.GetWidth();
229 case wxVERTICAL: return size.GetHeight();
230 case wxBOTH: return size.GetWidth() * size.GetHeight();
231 default: return 0;
232 }
233 }
234
235 wxSize wxRibbonToolBar::DoGetNextSmallerSize(wxOrientation direction,
236 wxSize relative_to) const
237 {
238 wxSize result(relative_to);
239 int area = 0;
240 int nrows;
241 for(nrows = m_nrows_min; nrows <= m_nrows_max; ++nrows)
242 {
243 wxSize size(m_sizes[nrows - m_nrows_min]);
244 wxSize original(size);
245 switch(direction)
246 {
247 case wxHORIZONTAL:
248 if(size.GetWidth() < relative_to.GetWidth()
249 && size.GetHeight() <= relative_to.GetHeight())
250 {
251 size.SetHeight(relative_to.GetHeight());
252 break;
253 }
254 continue;
255 case wxVERTICAL:
256 if(size.GetWidth() <= relative_to.GetWidth()
257 && size.GetHeight() < relative_to.GetHeight())
258 {
259 size.SetWidth(relative_to.GetWidth());
260 break;
261 }
262 continue;
263 case wxBOTH:
264 if(size.GetWidth() < relative_to.GetWidth()
265 && size.GetHeight() < relative_to.GetHeight())
266 {
267 break;
268 }
269 continue;
270 }
271 if(GetSizeInOrientation(original, direction) > area)
272 {
273 result = size;
274 area = GetSizeInOrientation(original, direction);
275 }
276 }
277 return result;
278 }
279
280 wxSize wxRibbonToolBar::DoGetNextLargerSize(wxOrientation direction,
281 wxSize relative_to) const
282 {
283 // Pick the smallest of our sizes which are larger than the given size
284 wxSize result(relative_to);
285 int area = INT_MAX;
286 int nrows;
287 for(nrows = m_nrows_min; nrows <= m_nrows_max; ++nrows)
288 {
289 wxSize size(m_sizes[nrows - m_nrows_min]);
290 wxSize original(size);
291 switch(direction)
292 {
293 case wxHORIZONTAL:
294 if(size.GetWidth() > relative_to.GetWidth()
295 && size.GetHeight() <= relative_to.GetHeight())
296 {
297 size.SetHeight(relative_to.GetHeight());
298 break;
299 }
300 continue;
301 case wxVERTICAL:
302 if(size.GetWidth() <= relative_to.GetWidth()
303 && size.GetHeight() > relative_to.GetHeight())
304 {
305 size.SetWidth(relative_to.GetWidth());
306 break;
307 }
308 continue;
309 case wxBOTH:
310 if(size.GetWidth() > relative_to.GetWidth()
311 && size.GetHeight() > relative_to.GetHeight())
312 {
313 break;
314 }
315 continue;
316 }
317 if(GetSizeInOrientation(original, direction) < area)
318 {
319 result = size;
320 area = GetSizeInOrientation(original, direction);
321 }
322 }
323
324 return result;
325 }
326
327 void wxRibbonToolBar::SetRows(int nMin, int nMax)
328 {
329 if(nMax == -1)
330 nMax = nMin;
331
332 wxASSERT(1 <= nMin);
333 wxASSERT(nMin <= nMax);
334
335 m_nrows_min = nMin;
336 m_nrows_max = nMax;
337
338 delete[] m_sizes;
339 m_sizes = new wxSize[m_nrows_max - m_nrows_min + 1];
340 for(int i = m_nrows_min; i <= m_nrows_max; ++i)
341 m_sizes[i - m_nrows_min] = wxSize(0, 0);
342
343 Realize();
344 }
345
346 bool wxRibbonToolBar::Realize()
347 {
348 if(m_art == NULL)
349 return false;
350
351 // Calculate the size of each group and the position/size of each tool
352 wxMemoryDC temp_dc;
353 size_t group_count = m_groups.GetCount();
354 size_t g, t;
355 for(g = 0; g < group_count; ++g)
356 {
357 wxRibbonToolBarToolBase* prev = NULL;
358 wxRibbonToolBarToolGroup* group = m_groups.Item(g);
359 size_t tool_count = group->tools.GetCount();
360 int tallest = 0;
361 for(t = 0; t < tool_count; ++t)
362 {
363 wxRibbonToolBarToolBase* tool = group->tools.Item(t);
364 tool->size = m_art->GetToolSize(temp_dc, this,
365 tool->bitmap.GetSize(), tool->kind, t == 0,
366 t == (tool_count - 1), &tool->dropdown);
367 tool->state = tool->state & ~wxRIBBON_TOOLBAR_TOOL_DISABLED;
368 if(t == 0)
369 tool->state |= wxRIBBON_TOOLBAR_TOOL_FIRST;
370 if(t == tool_count - 1)
371 tool->state |= wxRIBBON_TOOLBAR_TOOL_LAST;
372 if(tool->size.GetHeight() > tallest)
373 tallest = tool->size.GetHeight();
374 if(prev)
375 {
376 tool->position = prev->position;
377 tool->position.x += prev->size.x;
378 }
379 else
380 {
381 tool->position = wxPoint(0, 0);
382 }
383 prev = tool;
384 }
385 if(tool_count == 0)
386 group->size = wxSize(0, 0);
387 else
388 {
389 group->size = wxSize(prev->position.x + prev->size.x, tallest);
390 for(t = 0; t < tool_count; ++t)
391 group->tools.Item(t)->size.SetHeight(tallest);
392 }
393 }
394
395 // Calculate the minimum size for each possible number of rows
396 int nrows, r;
397 int sep = m_art->GetMetric(wxRIBBON_ART_TOOL_GROUP_SEPARATION_SIZE);
398 int smallest_area = INT_MAX;
399 wxSize* row_sizes = new wxSize[m_nrows_max];
400 wxOrientation major_axis = m_art->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL ?
401 wxVERTICAL : wxHORIZONTAL;
402 SetMinSize(wxSize(0, 0));
403 for(nrows = m_nrows_min; nrows <= m_nrows_max; ++nrows)
404 {
405 for(r = 0; r < nrows; ++r)
406 row_sizes[r] = wxSize(0, 0);
407 for(g = 0; g < group_count; ++g)
408 {
409 wxRibbonToolBarToolGroup* group = m_groups.Item(g);
410 int shortest_row = 0;
411 for(r = 1; r < nrows; ++r)
412 {
413 if(row_sizes[r].GetWidth() < row_sizes[shortest_row].GetWidth())
414 shortest_row = r;
415 }
416 row_sizes[shortest_row].x += group->size.x + sep;
417 if(group->size.y > row_sizes[shortest_row].y)
418 row_sizes[shortest_row].y = group->size.y;
419 }
420 wxSize size(0, 0);
421 for(r = 0; r < nrows; ++r)
422 {
423 if(row_sizes[r].GetWidth() != 0)
424 row_sizes[r].DecBy(sep, 0);
425 if(row_sizes[r].GetWidth() > size.GetWidth())
426 size.SetWidth(row_sizes[r].GetWidth());
427 size.IncBy(0, row_sizes[r].y);
428 }
429 m_sizes[nrows - m_nrows_min] = size;
430 if(GetSizeInOrientation(size, major_axis) < smallest_area)
431 {
432 SetMinSize(size);
433 smallest_area = GetSizeInOrientation(size, major_axis);
434 }
435 }
436
437 // Position the groups
438 wxSizeEvent dummy_event(GetSize());
439 OnSize(dummy_event);
440
441 return true;
442 }
443
444 void wxRibbonToolBar::OnSize(wxSizeEvent& evt)
445 {
446 if(m_art == NULL)
447 return;
448
449 // Choose row count with largest possible area
450 wxSize size = evt.GetSize();
451 int row_count = m_nrows_max;
452 wxOrientation major_axis = m_art->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL ?
453 wxVERTICAL : wxHORIZONTAL;
454 if(m_nrows_max != m_nrows_min)
455 {
456 int area = 0;
457 for(int i = 0; i <= m_nrows_max - m_nrows_min; ++i)
458 {
459 if(m_sizes[i].x <= size.x && m_sizes[i].y <= size.y &&
460 GetSizeInOrientation(m_sizes[i], major_axis) > area)
461 {
462 area = GetSizeInOrientation(m_sizes[i], major_axis);
463 row_count = m_nrows_min + i;
464 }
465 }
466 }
467
468 // Assign groups to rows and calculate row widths
469 wxSize* row_sizes = new wxSize[row_count];
470 int sep = m_art->GetMetric(wxRIBBON_ART_TOOL_GROUP_SEPARATION_SIZE);
471
472 int r;
473 for(r = 0; r < row_count; ++r)
474 row_sizes[r] = wxSize(0, 0);
475 size_t g;
476 size_t group_count = m_groups.GetCount();
477 for(g = 0; g < group_count; ++g)
478 {
479 wxRibbonToolBarToolGroup* group = m_groups.Item(g);
480 int shortest_row = 0;
481 for(r = 1; r < row_count; ++r)
482 {
483 if(row_sizes[r].GetWidth() < row_sizes[shortest_row].GetWidth())
484 shortest_row = r;
485 }
486 group->position = wxPoint(row_sizes[shortest_row].x, shortest_row);
487 row_sizes[shortest_row].x += group->size.x + sep;
488 if(group->size.y > row_sizes[shortest_row].y)
489 row_sizes[shortest_row].y = group->size.y;
490 }
491
492 // Calculate row positions
493 int total_height = 0;
494 for(r = 0; r < row_count; ++r)
495 total_height += row_sizes[r].GetHeight();
496 int rowsep = (size.GetHeight() - total_height) / (row_count + 1);
497 int* rowypos = new int[row_count];
498 rowypos[0] = rowsep;
499 for(r = 1; r < row_count; ++r)
500 {
501 rowypos[r] = rowypos[r - 1] + row_sizes[r - 1].GetHeight() + rowsep;
502 }
503
504 // Set group y positions
505 for(g = 0; g < group_count; ++g)
506 {
507 wxRibbonToolBarToolGroup* group = m_groups.Item(g);
508 group->position.y = rowypos[group->position.y];
509 }
510
511 delete[] rowypos;
512 delete[] row_sizes;
513 }
514
515 wxSize wxRibbonToolBar::DoGetBestSize() const
516 {
517 return GetMinSize();
518 }
519
520 void wxRibbonToolBar::OnEraseBackground(wxEraseEvent& WXUNUSED(evt))
521 {
522 // All painting done in main paint handler to minimise flicker
523 }
524
525 void wxRibbonToolBar::OnPaint(wxPaintEvent& WXUNUSED(evt))
526 {
527 wxAutoBufferedPaintDC dc(this);
528 if(m_art == NULL)
529 return;
530
531 m_art->DrawToolBarBackground(dc, this, GetSize());
532
533 size_t group_count = m_groups.GetCount();
534 size_t g, t;
535 for(g = 0; g < group_count; ++g)
536 {
537 wxRibbonToolBarToolGroup* group = m_groups.Item(g);
538 size_t tool_count = group->tools.GetCount();
539 if(tool_count != 0)
540 {
541 m_art->DrawToolGroupBackground(dc, this,
542 wxRect(group->position, group->size));
543 for(t = 0; t < tool_count; ++t)
544 {
545 wxRibbonToolBarToolBase* tool = group->tools.Item(t);
546 wxRect rect(group->position + tool->position, tool->size);
547 m_art->DrawTool(dc, this, rect, tool->bitmap, tool->kind,
548 tool->state);
549 }
550 }
551 }
552 }
553
554 void wxRibbonToolBar::OnMouseMove(wxMouseEvent& evt)
555 {
556 wxPoint pos(evt.GetPosition());
557 wxRibbonToolBarToolBase *new_hover = NULL;
558
559 size_t group_count = m_groups.GetCount();
560 size_t g, t;
561 for(g = 0; g < group_count; ++g)
562 {
563 wxRibbonToolBarToolGroup* group = m_groups.Item(g);
564 if(group->position.x <= pos.x && pos.x < group->position.x + group->size.x
565 && group->position.y <= pos.y && pos.y < group->position.y + group->size.y)
566 {
567 size_t tool_count = group->tools.GetCount();
568 pos -= group->position;
569 for(t = 0; t < tool_count; ++t)
570 {
571 wxRibbonToolBarToolBase* tool = group->tools.Item(t);
572 if(tool->position.x <= pos.x && pos.x < tool->position.x + tool->size.x
573 && tool->position.y <= pos.y && pos.y < tool->position.y + tool->size.y)
574 {
575 pos -= tool->position;
576 new_hover = tool;
577 break;
578 }
579 }
580 break;
581 }
582 }
583
584 if(new_hover != m_hover_tool)
585 {
586 if(m_hover_tool)
587 {
588 m_hover_tool->state &= ~(wxRIBBON_TOOLBAR_TOOL_HOVER_MASK
589 | wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK);
590 }
591 m_hover_tool = new_hover;
592 if(new_hover)
593 {
594 long what = wxRIBBON_TOOLBAR_TOOL_NORMAL_HOVERED;
595 if(new_hover->dropdown.Contains(pos))
596 what = wxRIBBON_TOOLBAR_TOOL_DROPDOWN_HOVERED;
597
598 new_hover->state |= what;
599
600 if(new_hover == m_active_tool)
601 {
602 new_hover->state &= ~wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK;
603 new_hover->state |= (what << 2);
604 }
605 }
606 Refresh(false);
607 }
608 else if(m_hover_tool && m_hover_tool->kind == wxRIBBON_BUTTON_HYBRID)
609 {
610 long newstate = m_hover_tool->state &~wxRIBBON_TOOLBAR_TOOL_HOVER_MASK;
611 long what = wxRIBBON_TOOLBAR_TOOL_NORMAL_HOVERED;
612 if(m_hover_tool->dropdown.Contains(pos))
613 what = wxRIBBON_TOOLBAR_TOOL_DROPDOWN_HOVERED;
614 newstate |= what;
615 if(newstate != m_hover_tool->state)
616 {
617 m_hover_tool->state = newstate;
618 if(m_hover_tool == m_active_tool)
619 {
620 m_hover_tool->state &= ~wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK;
621 m_hover_tool->state |= (what << 2);
622 }
623 Refresh(false);
624 }
625 }
626 }
627
628 void wxRibbonToolBar::OnMouseDown(wxMouseEvent& evt)
629 {
630 OnMouseMove(evt);
631 if(m_hover_tool)
632 {
633 m_active_tool = m_hover_tool;
634 m_active_tool->state |=
635 (m_active_tool->state & wxRIBBON_TOOLBAR_TOOL_HOVER_MASK) << 2;
636 Refresh(false);
637 }
638 }
639
640 void wxRibbonToolBar::OnMouseLeave(wxMouseEvent& WXUNUSED(evt))
641 {
642 if(m_hover_tool)
643 {
644 m_hover_tool->state &= ~wxRIBBON_TOOLBAR_TOOL_HOVER_MASK;
645 m_hover_tool = NULL;
646 Refresh(false);
647 }
648 }
649
650 void wxRibbonToolBar::OnMouseUp(wxMouseEvent& WXUNUSED(evt))
651 {
652 if(m_active_tool)
653 {
654 if(m_active_tool->state & wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK)
655 {
656 wxEventType evt_type = wxEVT_COMMAND_RIBBONTOOL_CLICKED;
657 if(m_active_tool->state & wxRIBBON_TOOLBAR_TOOL_DROPDOWN_ACTIVE)
658 evt_type = wxEVT_COMMAND_RIBBONTOOL_DROPDOWN_CLICKED;
659 wxRibbonToolBarEvent notification(evt_type, m_active_tool->id);
660 notification.SetEventObject(this);
661 notification.SetBar(this);
662 ProcessEvent(notification);
663 }
664 m_active_tool->state &= ~wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK;
665 m_active_tool = NULL;
666 Refresh(false);
667 }
668 }
669
670 void wxRibbonToolBar::OnMouseEnter(wxMouseEvent& evt)
671 {
672 if(m_active_tool && !evt.LeftIsDown())
673 {
674 m_active_tool = NULL;
675 }
676 }
677
678 bool wxRibbonToolBarEvent::PopupMenu(wxMenu* menu)
679 {
680 wxPoint pos = wxDefaultPosition;
681 if(m_bar->m_active_tool)
682 {
683 // Find the group which contains the tool
684 size_t group_count = m_bar->m_groups.GetCount();
685 size_t g, t;
686 for(g = 0; g < group_count; ++g)
687 {
688 wxRibbonToolBarToolGroup* group = m_bar->m_groups.Item(g);
689 size_t tool_count = group->tools.GetCount();
690 for(t = 0; t < tool_count; ++t)
691 {
692 wxRibbonToolBarToolBase* tool = group->tools.Item(t);
693 if(tool == m_bar->m_active_tool)
694 {
695 pos = group->position;
696 pos += tool->position;
697 pos.y += tool->size.GetHeight();
698 g = group_count;
699 break;
700 }
701 }
702 }
703 }
704 return m_bar->PopupMenu(menu, pos);
705 }
706
707 #endif // wxUSE_RIBBON