]> git.saurik.com Git - wxWidgets.git/blob - src/ribbon/toolbar.cpp
non PCH compilation
[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 #if wxUSE_RIBBON
19
20 #include "wx/ribbon/toolbar.h"
21 #include "wx/ribbon/art.h"
22 #include "wx/ribbon/bar.h"
23 #include "wx/dcbuffer.h"
24
25 #ifndef WX_PRECOMP
26 #endif
27
28 #ifdef __WXMSW__
29 #include "wx/msw/private.h"
30 #endif
31
32 class wxRibbonToolBarToolBase
33 {
34 public:
35 wxString help_string;
36 wxBitmap bitmap;
37 wxBitmap bitmap_disabled;
38 wxRect dropdown;
39 wxPoint position;
40 wxSize size;
41 wxObject* client_data;
42 int id;
43 wxRibbonButtonKind kind;
44 long state;
45 };
46
47 WX_DEFINE_ARRAY(wxRibbonToolBarToolBase*, wxArrayRibbonToolBarToolBase);
48
49 class wxRibbonToolBarToolGroup
50 {
51 public:
52 // To identify the group as a wxRibbonToolBarToolBase*
53 wxRibbonToolBarToolBase dummy_tool;
54
55 wxArrayRibbonToolBarToolBase tools;
56 wxPoint position;
57 wxSize size;
58 };
59
60 wxDEFINE_EVENT(wxEVT_COMMAND_RIBBONTOOL_CLICKED, wxRibbonToolBarEvent);
61 wxDEFINE_EVENT(wxEVT_COMMAND_RIBBONTOOL_DROPDOWN_CLICKED, wxRibbonToolBarEvent);
62
63 IMPLEMENT_DYNAMIC_CLASS(wxRibbonToolBarEvent, wxCommandEvent)
64 IMPLEMENT_CLASS(wxRibbonToolBar, wxRibbonControl)
65
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)
75 END_EVENT_TABLE()
76
77 wxRibbonToolBar::wxRibbonToolBar()
78 {
79 }
80
81 wxRibbonToolBar::wxRibbonToolBar(wxWindow* parent,
82 wxWindowID id,
83 const wxPoint& pos,
84 const wxSize& size,
85 long style)
86 : wxRibbonControl(parent, id, pos, size, wxBORDER_NONE)
87 {
88 CommonInit(style);
89 }
90
91 bool wxRibbonToolBar::Create(wxWindow* parent,
92 wxWindowID id,
93 const wxPoint& pos,
94 const wxSize& size,
95 long style)
96 {
97 if(!wxRibbonControl::Create(parent, id, pos, size, wxBORDER_NONE))
98 {
99 return false;
100 }
101
102 CommonInit(style);
103 return true;
104 }
105
106 void wxRibbonToolBar::CommonInit(long WXUNUSED(style))
107 {
108 AppendGroup();
109 m_hover_tool = NULL;
110 m_active_tool = NULL;
111 m_nrows_min = 1;
112 m_nrows_max = 1;
113 m_sizes = new wxSize[1];
114 m_sizes[0] = wxSize(0, 0);
115 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
116 }
117
118 wxRibbonToolBar::~wxRibbonToolBar()
119 {
120 size_t count = m_groups.GetCount();
121 size_t i, t;
122 for(i = 0; i < count; ++i)
123 {
124 wxRibbonToolBarToolGroup* group = m_groups.Item(i);
125 size_t tool_count = group->tools.GetCount();
126 for(t = 0; t < tool_count; ++t)
127 {
128 wxRibbonToolBarToolBase* tool = group->tools.Item(t);
129 delete tool;
130 }
131 delete group;
132 }
133 m_groups.Clear();
134 delete[] m_sizes;
135 }
136
137 wxRibbonToolBarToolBase* wxRibbonToolBar::AddTool(
138 int tool_id,
139 const wxBitmap& bitmap,
140 const wxString& help_string,
141 wxRibbonButtonKind kind)
142 {
143 return AddTool(tool_id, bitmap, wxNullBitmap, help_string, kind, NULL);
144 }
145
146 wxRibbonToolBarToolBase* wxRibbonToolBar::AddDropdownTool(
147 int tool_id,
148 const wxBitmap& bitmap,
149 const wxString& help_string)
150 {
151 return AddTool(tool_id, bitmap, wxNullBitmap, help_string,
152 wxRIBBON_BUTTON_DROPDOWN, NULL);
153 }
154
155 wxRibbonToolBarToolBase* wxRibbonToolBar::AddHybridTool(
156 int tool_id,
157 const wxBitmap& bitmap,
158 const wxString& help_string)
159 {
160 return AddTool(tool_id, bitmap, wxNullBitmap, help_string,
161 wxRIBBON_BUTTON_HYBRID, NULL);
162 }
163
164 wxRibbonToolBarToolBase* wxRibbonToolBar::AddTool(
165 int tool_id,
166 const wxBitmap& bitmap,
167 const wxBitmap& bitmap_disabled,
168 const wxString& help_string,
169 wxRibbonButtonKind kind,
170 wxObject* client_data)
171 {
172 wxASSERT(bitmap.IsOk());
173
174 wxRibbonToolBarToolBase* tool = new wxRibbonToolBarToolBase;
175 tool->id = tool_id;
176 tool->bitmap = bitmap;
177 if(bitmap_disabled.IsOk())
178 {
179 wxASSERT(bitmap.GetSize() == bitmap_disabled.GetSize());
180 tool->bitmap_disabled = bitmap_disabled;
181 }
182 else
183 tool->bitmap_disabled = MakeDisabledBitmap(bitmap);
184 tool->help_string = help_string;
185 tool->kind = kind;
186 tool->client_data = client_data;
187 tool->position = wxPoint(0, 0);
188 tool->size = wxSize(0, 0);
189 tool->state = 0;
190
191 m_groups.Last()->tools.Add(tool);
192 return tool;
193 }
194
195 wxRibbonToolBarToolBase* wxRibbonToolBar::AddSeparator()
196 {
197 if(m_groups.Last()->tools.IsEmpty())
198 return NULL;
199
200 AppendGroup();
201 return &m_groups.Last()->dummy_tool;
202 }
203
204 wxBitmap wxRibbonToolBar::MakeDisabledBitmap(const wxBitmap& original)
205 {
206 wxImage img(original.ConvertToImage());
207 return wxBitmap(img.ConvertToGreyscale());
208 }
209
210 void wxRibbonToolBar::AppendGroup()
211 {
212 wxRibbonToolBarToolGroup* group = new wxRibbonToolBarToolGroup;
213 group->position = wxPoint(0, 0);
214 group->size = wxSize(0, 0);
215 m_groups.Add(group);
216 }
217
218 bool wxRibbonToolBar::IsSizingContinuous() const
219 {
220 return false;
221 }
222
223 static int GetSizeInOrientation(wxSize size, wxOrientation orientation)
224 {
225 switch(orientation)
226 {
227 case wxHORIZONTAL: return size.GetWidth();
228 case wxVERTICAL: return size.GetHeight();
229 case wxBOTH: return size.GetWidth() * size.GetHeight();
230 default: return 0;
231 }
232 }
233
234 wxSize wxRibbonToolBar::DoGetNextSmallerSize(wxOrientation direction,
235 wxSize relative_to) const
236 {
237 wxSize result(relative_to);
238 int area = 0;
239 int nrows;
240 for(nrows = m_nrows_min; nrows <= m_nrows_max; ++nrows)
241 {
242 wxSize size(m_sizes[nrows - m_nrows_min]);
243 wxSize original(size);
244 switch(direction)
245 {
246 case wxHORIZONTAL:
247 if(size.GetWidth() < relative_to.GetWidth()
248 && size.GetHeight() <= relative_to.GetHeight())
249 {
250 size.SetHeight(relative_to.GetHeight());
251 break;
252 }
253 continue;
254 case wxVERTICAL:
255 if(size.GetWidth() <= relative_to.GetWidth()
256 && size.GetHeight() < relative_to.GetHeight())
257 {
258 size.SetWidth(relative_to.GetWidth());
259 break;
260 }
261 continue;
262 case wxBOTH:
263 if(size.GetWidth() < relative_to.GetWidth()
264 && size.GetHeight() < relative_to.GetHeight())
265 {
266 break;
267 }
268 continue;
269 }
270 if(GetSizeInOrientation(original, direction) > area)
271 {
272 result = size;
273 area = GetSizeInOrientation(original, direction);
274 }
275 }
276 return result;
277 }
278
279 wxSize wxRibbonToolBar::DoGetNextLargerSize(wxOrientation direction,
280 wxSize relative_to) const
281 {
282 // Pick the smallest of our sizes which are larger than the given size
283 wxSize result(relative_to);
284 int area = INT_MAX;
285 int nrows;
286 for(nrows = m_nrows_min; nrows <= m_nrows_max; ++nrows)
287 {
288 wxSize size(m_sizes[nrows - m_nrows_min]);
289 wxSize original(size);
290 switch(direction)
291 {
292 case wxHORIZONTAL:
293 if(size.GetWidth() > relative_to.GetWidth()
294 && size.GetHeight() <= relative_to.GetHeight())
295 {
296 size.SetHeight(relative_to.GetHeight());
297 break;
298 }
299 continue;
300 case wxVERTICAL:
301 if(size.GetWidth() <= relative_to.GetWidth()
302 && size.GetHeight() > relative_to.GetHeight())
303 {
304 size.SetWidth(relative_to.GetWidth());
305 break;
306 }
307 continue;
308 case wxBOTH:
309 if(size.GetWidth() > relative_to.GetWidth()
310 && size.GetHeight() > relative_to.GetHeight())
311 {
312 break;
313 }
314 continue;
315 }
316 if(GetSizeInOrientation(original, direction) < area)
317 {
318 result = size;
319 area = GetSizeInOrientation(original, direction);
320 }
321 }
322
323 return result;
324 }
325
326 void wxRibbonToolBar::SetRows(int nMin, int nMax)
327 {
328 if(nMax == -1)
329 nMax = nMin;
330
331 wxASSERT(1 <= nMin);
332 wxASSERT(nMin <= nMax);
333
334 m_nrows_min = nMin;
335 m_nrows_max = nMax;
336
337 delete[] m_sizes;
338 m_sizes = new wxSize[m_nrows_max - m_nrows_min + 1];
339 for(int i = m_nrows_min; i <= m_nrows_max; ++i)
340 m_sizes[i - m_nrows_min] = wxSize(0, 0);
341
342 Realize();
343 }
344
345 bool wxRibbonToolBar::Realize()
346 {
347 if(m_art == NULL)
348 return false;
349
350 // Calculate the size of each group and the position/size of each tool
351 wxMemoryDC temp_dc;
352 size_t group_count = m_groups.GetCount();
353 size_t g, t;
354 for(g = 0; g < group_count; ++g)
355 {
356 wxRibbonToolBarToolBase* prev = NULL;
357 wxRibbonToolBarToolGroup* group = m_groups.Item(g);
358 size_t tool_count = group->tools.GetCount();
359 int tallest = 0;
360 for(t = 0; t < tool_count; ++t)
361 {
362 wxRibbonToolBarToolBase* tool = group->tools.Item(t);
363 tool->size = m_art->GetToolSize(temp_dc, this,
364 tool->bitmap.GetSize(), tool->kind, t == 0,
365 t == (tool_count - 1), &tool->dropdown);
366 tool->state = tool->state & ~wxRIBBON_TOOLBAR_TOOL_DISABLED;
367 if(t == 0)
368 tool->state |= wxRIBBON_TOOLBAR_TOOL_FIRST;
369 if(t == tool_count - 1)
370 tool->state |= wxRIBBON_TOOLBAR_TOOL_LAST;
371 if(tool->size.GetHeight() > tallest)
372 tallest = tool->size.GetHeight();
373 if(prev)
374 {
375 tool->position = prev->position;
376 tool->position.x += prev->size.x;
377 }
378 else
379 {
380 tool->position = wxPoint(0, 0);
381 }
382 prev = tool;
383 }
384 if(tool_count == 0)
385 group->size = wxSize(0, 0);
386 else
387 {
388 group->size = wxSize(prev->position.x + prev->size.x, tallest);
389 for(t = 0; t < tool_count; ++t)
390 group->tools.Item(t)->size.SetHeight(tallest);
391 }
392 }
393
394 // Calculate the minimum size for each possible number of rows
395 int nrows, r;
396 int sep = m_art->GetMetric(wxRIBBON_ART_TOOL_GROUP_SEPARATION_SIZE);
397 int smallest_area = INT_MAX;
398 wxSize* row_sizes = new wxSize[m_nrows_max];
399 wxOrientation major_axis = m_art->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL ?
400 wxVERTICAL : wxHORIZONTAL;
401 SetMinSize(wxSize(0, 0));
402 for(nrows = m_nrows_min; nrows <= m_nrows_max; ++nrows)
403 {
404 for(r = 0; r < nrows; ++r)
405 row_sizes[r] = wxSize(0, 0);
406 for(g = 0; g < group_count; ++g)
407 {
408 wxRibbonToolBarToolGroup* group = m_groups.Item(g);
409 int shortest_row = 0;
410 for(r = 1; r < nrows; ++r)
411 {
412 if(row_sizes[r].GetWidth() < row_sizes[shortest_row].GetWidth())
413 shortest_row = r;
414 }
415 row_sizes[shortest_row].x += group->size.x + sep;
416 if(group->size.y > row_sizes[shortest_row].y)
417 row_sizes[shortest_row].y = group->size.y;
418 }
419 wxSize size(0, 0);
420 for(r = 0; r < nrows; ++r)
421 {
422 if(row_sizes[r].GetWidth() != 0)
423 row_sizes[r].DecBy(sep, 0);
424 if(row_sizes[r].GetWidth() > size.GetWidth())
425 size.SetWidth(row_sizes[r].GetWidth());
426 size.IncBy(0, row_sizes[r].y);
427 }
428 m_sizes[nrows - m_nrows_min] = size;
429 if(GetSizeInOrientation(size, major_axis) < smallest_area)
430 {
431 SetMinSize(size);
432 smallest_area = GetSizeInOrientation(size, major_axis);
433 }
434 }
435 delete[] row_sizes;
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