]> git.saurik.com Git - wxWidgets.git/blame - src/ribbon/gallery.cpp
Don't crash when laying out wxGridBagSizer with only hidden elements.
[wxWidgets.git] / src / ribbon / gallery.cpp
CommitLineData
3c3ead1d
PC
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/ribbon/gallery.cpp
3// Purpose: Ribbon control which displays a gallery of items to choose from
4// Author: Peter Cawley
5// Modified by:
6// Created: 2009-07-22
3c3ead1d
PC
7// Copyright: (C) Peter Cawley
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11#include "wx/wxprec.h"
12
13#ifdef __BORLANDC__
14 #pragma hdrstop
15#endif
16
3c3ead1d
PC
17#if wxUSE_RIBBON
18
4cf018e1 19#include "wx/ribbon/gallery.h"
3c3ead1d
PC
20#include "wx/ribbon/art.h"
21#include "wx/ribbon/bar.h"
22#include "wx/dcbuffer.h"
23#include "wx/clntdata.h"
24
25#ifndef WX_PRECOMP
26#endif
27
28#ifdef __WXMSW__
29#include "wx/msw/private.h"
30#endif
31
ce7fe42e
VZ
32wxDEFINE_EVENT(wxEVT_RIBBONGALLERY_HOVER_CHANGED, wxRibbonGalleryEvent);
33wxDEFINE_EVENT(wxEVT_RIBBONGALLERY_SELECTED, wxRibbonGalleryEvent);
34wxDEFINE_EVENT(wxEVT_RIBBONGALLERY_CLICKED, wxRibbonGalleryEvent);
3c3ead1d
PC
35
36IMPLEMENT_DYNAMIC_CLASS(wxRibbonGalleryEvent, wxCommandEvent)
37IMPLEMENT_CLASS(wxRibbonGallery, wxRibbonControl)
38
39class wxRibbonGalleryItem
40{
41public:
42 wxRibbonGalleryItem()
43 {
44 m_id = 0;
45 m_is_visible = false;
46 }
47
48 void SetId(int id) {m_id = id;}
49 void SetBitmap(const wxBitmap& bitmap) {m_bitmap = bitmap;}
50 const wxBitmap& GetBitmap() const {return m_bitmap;}
51 void SetIsVisible(bool visible) {m_is_visible = visible;}
52 void SetPosition(int x, int y, const wxSize& size)
53 {
54 m_position = wxRect(wxPoint(x, y), size);
55 }
56 bool IsVisible() const {return m_is_visible;}
57 const wxRect& GetPosition() const {return m_position;}
58
59 void SetClientObject(wxClientData *data) {m_client_data.SetClientObject(data);}
60 wxClientData *GetClientObject() const {return m_client_data.GetClientObject();}
61 void SetClientData(void *data) {m_client_data.SetClientData(data);}
62 void *GetClientData() const {return m_client_data.GetClientData();}
63
64protected:
65 wxBitmap m_bitmap;
66 wxClientDataContainer m_client_data;
67 wxRect m_position;
68 int m_id;
69 bool m_is_visible;
70};
71
72BEGIN_EVENT_TABLE(wxRibbonGallery, wxRibbonControl)
73 EVT_ENTER_WINDOW(wxRibbonGallery::OnMouseEnter)
74 EVT_ERASE_BACKGROUND(wxRibbonGallery::OnEraseBackground)
75 EVT_LEAVE_WINDOW(wxRibbonGallery::OnMouseLeave)
76 EVT_LEFT_DOWN(wxRibbonGallery::OnMouseDown)
77 EVT_LEFT_UP(wxRibbonGallery::OnMouseUp)
32eb5603 78 EVT_LEFT_DCLICK(wxRibbonGallery::OnMouseDClick)
3c3ead1d
PC
79 EVT_MOTION(wxRibbonGallery::OnMouseMove)
80 EVT_PAINT(wxRibbonGallery::OnPaint)
81 EVT_SIZE(wxRibbonGallery::OnSize)
82END_EVENT_TABLE()
83
84wxRibbonGallery::wxRibbonGallery()
85{
86}
87
88wxRibbonGallery::wxRibbonGallery(wxWindow* parent,
89 wxWindowID id,
90 const wxPoint& pos,
91 const wxSize& size,
92 long style)
93 : wxRibbonControl(parent, id, pos, size, wxBORDER_NONE)
94{
95 CommonInit(style);
96}
97
98wxRibbonGallery::~wxRibbonGallery()
99{
100 Clear();
101}
102
103bool wxRibbonGallery::Create(wxWindow* parent,
104 wxWindowID id,
105 const wxPoint& pos,
106 const wxSize& size,
107 long style)
108{
109 if(!wxRibbonControl::Create(parent, id, pos, size, wxBORDER_NONE))
110 {
111 return false;
112 }
113
114 CommonInit(style);
115 return true;
116}
117
118void wxRibbonGallery::CommonInit(long WXUNUSED(style))
119{
120 m_selected_item = NULL;
121 m_hovered_item = NULL;
122 m_active_item = NULL;
123 m_scroll_up_button_rect = wxRect(0, 0, 0, 0);
124 m_scroll_down_button_rect = wxRect(0, 0, 0, 0);
125 m_extension_button_rect = wxRect(0, 0, 0, 0);
126 m_mouse_active_rect = NULL;
127 m_bitmap_size = wxSize(64, 32);
128 m_bitmap_padded_size = m_bitmap_size;
129 m_item_separation_x = 0;
130 m_item_separation_y = 0;
131 m_scroll_amount = 0;
132 m_scroll_limit = 0;
133 m_up_button_state = wxRIBBON_GALLERY_BUTTON_DISABLED;
134 m_down_button_state = wxRIBBON_GALLERY_BUTTON_NORMAL;
135 m_extension_button_state = wxRIBBON_GALLERY_BUTTON_NORMAL;
136 m_hovered = false;
137
138 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
139}
140
141void wxRibbonGallery::OnMouseEnter(wxMouseEvent& evt)
142{
143 m_hovered = true;
144 if(m_mouse_active_rect != NULL && !evt.LeftIsDown())
145 {
146 m_mouse_active_rect = NULL;
147 m_active_item = NULL;
148 }
149 Refresh(false);
150}
151
152void wxRibbonGallery::OnMouseMove(wxMouseEvent& evt)
153{
154 bool refresh = false;
155 wxPoint pos = evt.GetPosition();
156
157 if(TestButtonHover(m_scroll_up_button_rect, pos, &m_up_button_state))
158 refresh = true;
159 if(TestButtonHover(m_scroll_down_button_rect, pos, &m_down_button_state))
160 refresh = true;
161 if(TestButtonHover(m_extension_button_rect, pos, &m_extension_button_state))
162 refresh = true;
163
164 wxRibbonGalleryItem *hovered_item = NULL;
165 wxRibbonGalleryItem *active_item = NULL;
166 if(m_client_rect.Contains(pos))
167 {
168 if(m_art && m_art->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL)
169 pos.x += m_scroll_amount;
170 else
171 pos.y += m_scroll_amount;
172
173 size_t item_count = m_items.Count();
174 size_t item_i;
175 for(item_i = 0; item_i < item_count; ++item_i)
176 {
177 wxRibbonGalleryItem *item = m_items.Item(item_i);
178 if(!item->IsVisible())
179 continue;
180
181 if(item->GetPosition().Contains(pos))
182 {
183 if(m_mouse_active_rect == &item->GetPosition())
184 active_item = item;
185 hovered_item = item;
186 break;
187 }
188 }
189 }
190 if(active_item != m_active_item)
191 {
192 m_active_item = active_item;
193 refresh = true;
194 }
195 if(hovered_item != m_hovered_item)
196 {
197 m_hovered_item = hovered_item;
198 wxRibbonGalleryEvent notification(
ce7fe42e 199 wxEVT_RIBBONGALLERY_HOVER_CHANGED, GetId());
3c3ead1d
PC
200 notification.SetEventObject(this);
201 notification.SetGallery(this);
202 notification.SetGalleryItem(hovered_item);
203 ProcessWindowEvent(notification);
204 refresh = true;
205 }
206
207 if(refresh)
208 Refresh(false);
209}
210
211bool wxRibbonGallery::TestButtonHover(const wxRect& rect, wxPoint pos,
212 wxRibbonGalleryButtonState* state)
213{
214 if(*state == wxRIBBON_GALLERY_BUTTON_DISABLED)
215 return false;
216
217 wxRibbonGalleryButtonState new_state;
218 if(rect.Contains(pos))
219 {
220 if(m_mouse_active_rect == &rect)
221 new_state = wxRIBBON_GALLERY_BUTTON_ACTIVE;
222 else
223 new_state = wxRIBBON_GALLERY_BUTTON_HOVERED;
224 }
225 else
226 new_state = wxRIBBON_GALLERY_BUTTON_NORMAL;
227
228 if(new_state != *state)
229 {
230 *state = new_state;
231 return true;
232 }
233 else
234 {
235 return false;
236 }
237}
238
239void wxRibbonGallery::OnMouseLeave(wxMouseEvent& WXUNUSED(evt))
240{
241 m_hovered = false;
242 m_active_item = NULL;
243 if(m_up_button_state != wxRIBBON_GALLERY_BUTTON_DISABLED)
244 m_up_button_state = wxRIBBON_GALLERY_BUTTON_NORMAL;
245 if(m_down_button_state != wxRIBBON_GALLERY_BUTTON_DISABLED)
246 m_down_button_state = wxRIBBON_GALLERY_BUTTON_NORMAL;
247 if(m_extension_button_state != wxRIBBON_GALLERY_BUTTON_DISABLED)
248 m_extension_button_state = wxRIBBON_GALLERY_BUTTON_NORMAL;
249 if(m_hovered_item != NULL)
250 {
251 m_hovered_item = NULL;
252 wxRibbonGalleryEvent notification(
ce7fe42e 253 wxEVT_RIBBONGALLERY_HOVER_CHANGED, GetId());
3c3ead1d
PC
254 notification.SetEventObject(this);
255 notification.SetGallery(this);
256 ProcessWindowEvent(notification);
257 }
258 Refresh(false);
259}
260
261void wxRibbonGallery::OnMouseDown(wxMouseEvent& evt)
262{
263 wxPoint pos = evt.GetPosition();
264 m_mouse_active_rect = NULL;
265 if(m_client_rect.Contains(pos))
266 {
267 if(m_art && m_art->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL)
268 pos.x += m_scroll_amount;
269 else
270 pos.y += m_scroll_amount;
271 size_t item_count = m_items.Count();
272 size_t item_i;
273 for(item_i = 0; item_i < item_count; ++item_i)
274 {
275 wxRibbonGalleryItem *item = m_items.Item(item_i);
276 if(!item->IsVisible())
277 continue;
278
279 const wxRect& rect = item->GetPosition();
280 if(rect.Contains(pos))
281 {
282 m_active_item = item;
283 m_mouse_active_rect = &rect;
284 break;
285 }
286 }
287 }
288 else if(m_scroll_up_button_rect.Contains(pos))
289 {
290 if(m_up_button_state != wxRIBBON_GALLERY_BUTTON_DISABLED)
291 {
292 m_mouse_active_rect = &m_scroll_up_button_rect;
293 m_up_button_state = wxRIBBON_GALLERY_BUTTON_ACTIVE;
294 }
295 }
296 else if(m_scroll_down_button_rect.Contains(pos))
297 {
298 if(m_down_button_state != wxRIBBON_GALLERY_BUTTON_DISABLED)
299 {
300 m_mouse_active_rect = &m_scroll_down_button_rect;
301 m_down_button_state = wxRIBBON_GALLERY_BUTTON_ACTIVE;
302 }
303 }
304 else if(m_extension_button_rect.Contains(pos))
305 {
306 if(m_extension_button_state != wxRIBBON_GALLERY_BUTTON_DISABLED)
307 {
308 m_mouse_active_rect = &m_extension_button_rect;
309 m_extension_button_state = wxRIBBON_GALLERY_BUTTON_ACTIVE;
310 }
311 }
312 if(m_mouse_active_rect != NULL)
313 Refresh(false);
314}
315
316void wxRibbonGallery::OnMouseUp(wxMouseEvent& evt)
317{
318 if(m_mouse_active_rect != NULL)
319 {
320 wxPoint pos = evt.GetPosition();
321 if(m_active_item)
322 {
323 if(m_art && m_art->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL)
324 pos.x += m_scroll_amount;
325 else
326 pos.y += m_scroll_amount;
327 }
328 if(m_mouse_active_rect->Contains(pos))
329 {
330 if(m_mouse_active_rect == &m_scroll_up_button_rect)
331 {
332 m_up_button_state = wxRIBBON_GALLERY_BUTTON_HOVERED;
333 ScrollLines(-1);
334 }
335 else if(m_mouse_active_rect == &m_scroll_down_button_rect)
336 {
337 m_down_button_state = wxRIBBON_GALLERY_BUTTON_HOVERED;
338 ScrollLines(1);
339 }
340 else if(m_mouse_active_rect == &m_extension_button_rect)
341 {
342 m_extension_button_state = wxRIBBON_GALLERY_BUTTON_HOVERED;
ce7fe42e 343 wxCommandEvent notification(wxEVT_BUTTON,
3c3ead1d
PC
344 GetId());
345 notification.SetEventObject(this);
346 ProcessWindowEvent(notification);
347 }
348 else if(m_active_item != NULL)
349 {
350 if(m_selected_item != m_active_item)
351 {
352 m_selected_item = m_active_item;
353 wxRibbonGalleryEvent notification(
ce7fe42e 354 wxEVT_RIBBONGALLERY_SELECTED, GetId());
3c3ead1d
PC
355 notification.SetEventObject(this);
356 notification.SetGallery(this);
357 notification.SetGalleryItem(m_selected_item);
358 ProcessWindowEvent(notification);
359 }
1aff4201
VZ
360
361 wxRibbonGalleryEvent notification(
ce7fe42e 362 wxEVT_RIBBONGALLERY_CLICKED, GetId());
1aff4201
VZ
363 notification.SetEventObject(this);
364 notification.SetGallery(this);
365 notification.SetGalleryItem(m_selected_item);
366 ProcessWindowEvent(notification);
3c3ead1d
PC
367 }
368 }
369 m_mouse_active_rect = NULL;
370 m_active_item = NULL;
371 Refresh(false);
372 }
373}
374
32eb5603
PC
375void wxRibbonGallery::OnMouseDClick(wxMouseEvent& evt)
376{
377 // The 2nd click of a double-click should be handled as a click in the
378 // same way as the 1st click of the double-click. This is useful for
379 // scrolling through the gallery.
380 OnMouseDown(evt);
381 OnMouseUp(evt);
382}
383
3c3ead1d
PC
384void wxRibbonGallery::SetItemClientObject(wxRibbonGalleryItem* itm,
385 wxClientData* data)
386{
387 itm->SetClientObject(data);
388}
389
390wxClientData* wxRibbonGallery::GetItemClientObject(const wxRibbonGalleryItem* itm) const
391{
392 return itm->GetClientObject();
393}
394
395void wxRibbonGallery::SetItemClientData(wxRibbonGalleryItem* itm, void* data)
396{
397 itm->SetClientData(data);
398}
399
400void* wxRibbonGallery::GetItemClientData(const wxRibbonGalleryItem* itm) const
401{
402 return itm->GetClientData();
403}
404
405bool wxRibbonGallery::ScrollLines(int lines)
406{
407 if(m_scroll_limit == 0 || m_art == NULL)
408 return false;
409
32eb5603
PC
410 return ScrollPixels(lines * GetScrollLineSize());
411}
412
413int wxRibbonGallery::GetScrollLineSize() const
414{
415 if(m_art == NULL)
416 return 32;
417
3c3ead1d
PC
418 int line_size = m_bitmap_padded_size.GetHeight();
419 if(m_art->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL)
420 line_size = m_bitmap_padded_size.GetWidth();
32eb5603
PC
421
422 return line_size;
423}
424
425bool wxRibbonGallery::ScrollPixels(int pixels)
426{
427 if(m_scroll_limit == 0 || m_art == NULL)
428 return false;
429
430 if(pixels < 0)
3c3ead1d
PC
431 {
432 if(m_scroll_amount > 0)
433 {
32eb5603 434 m_scroll_amount += pixels;
3c3ead1d
PC
435 if(m_scroll_amount <= 0)
436 {
437 m_scroll_amount = 0;
438 m_up_button_state = wxRIBBON_GALLERY_BUTTON_DISABLED;
439 }
440 else if(m_up_button_state == wxRIBBON_GALLERY_BUTTON_DISABLED)
441 m_up_button_state = wxRIBBON_GALLERY_BUTTON_NORMAL;
442 if(m_down_button_state == wxRIBBON_GALLERY_BUTTON_DISABLED)
443 m_down_button_state = wxRIBBON_GALLERY_BUTTON_NORMAL;
444 return true;
445 }
446 }
32eb5603 447 else if(pixels > 0)
3c3ead1d
PC
448 {
449 if(m_scroll_amount < m_scroll_limit)
450 {
32eb5603 451 m_scroll_amount += pixels;
3c3ead1d
PC
452 if(m_scroll_amount >= m_scroll_limit)
453 {
454 m_scroll_amount = m_scroll_limit;
455 m_down_button_state = wxRIBBON_GALLERY_BUTTON_DISABLED;
456 }
457 else if(m_down_button_state == wxRIBBON_GALLERY_BUTTON_DISABLED)
458 m_down_button_state = wxRIBBON_GALLERY_BUTTON_NORMAL;
459 if(m_up_button_state == wxRIBBON_GALLERY_BUTTON_DISABLED)
460 m_up_button_state = wxRIBBON_GALLERY_BUTTON_NORMAL;
461 return true;
462 }
463 }
464 return false;
465}
466
467void wxRibbonGallery::EnsureVisible(const wxRibbonGalleryItem* item)
468{
469 if(item == NULL || !item->IsVisible() || IsEmpty())
470 return;
471
6f7e96d8
PC
472 if(m_art->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL)
473 {
474 int x = item->GetPosition().GetLeft();
475 int base_x = m_items.Item(0)->GetPosition().GetLeft();
476 int delta = x - base_x - m_scroll_amount;
477 ScrollLines(delta / m_bitmap_padded_size.GetWidth());
478 }
479 else
480 {
481 int y = item->GetPosition().GetTop();
482 int base_y = m_items.Item(0)->GetPosition().GetTop();
483 int delta = y - base_y - m_scroll_amount;
484 ScrollLines(delta / m_bitmap_padded_size.GetHeight());
485 }
3c3ead1d
PC
486}
487
488bool wxRibbonGallery::IsHovered() const
489{
490 return m_hovered;
491}
492
493void wxRibbonGallery::OnEraseBackground(wxEraseEvent& WXUNUSED(evt))
494{
495 // All painting done in main paint handler to minimise flicker
496}
497
498void wxRibbonGallery::OnPaint(wxPaintEvent& WXUNUSED(evt))
499{
500 wxAutoBufferedPaintDC dc(this);
501 if(m_art == NULL)
502 return;
503
3c3ead1d
PC
504 m_art->DrawGalleryBackground(dc, this, GetSize());
505
506 int padding_top = m_art->GetMetric(wxRIBBON_ART_GALLERY_BITMAP_PADDING_TOP_SIZE);
507 int padding_left = m_art->GetMetric(wxRIBBON_ART_GALLERY_BITMAP_PADDING_LEFT_SIZE);
508
509 dc.SetClippingRegion(m_client_rect);
510
511 bool offset_vertical = true;
512 if(m_art->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL)
513 offset_vertical = false;
514 size_t item_count = m_items.Count();
515 size_t item_i;
516 for(item_i = 0; item_i < item_count; ++item_i)
517 {
518 wxRibbonGalleryItem *item = m_items.Item(item_i);
519 if(!item->IsVisible())
520 continue;
521
522 const wxRect& pos = item->GetPosition();
523 wxRect offset_pos(pos);
524 if(offset_vertical)
525 offset_pos.SetTop(offset_pos.GetTop() - m_scroll_amount);
526 else
527 offset_pos.SetLeft(offset_pos.GetLeft() - m_scroll_amount);
528 m_art->DrawGalleryItemBackground(dc, this, offset_pos, item);
529 dc.DrawBitmap(item->GetBitmap(), offset_pos.GetLeft() + padding_left,
530 offset_pos.GetTop() + padding_top);
531 }
532}
533
534void wxRibbonGallery::OnSize(wxSizeEvent& WXUNUSED(evt))
535{
536 Layout();
537}
538
539wxRibbonGalleryItem* wxRibbonGallery::Append(const wxBitmap& bitmap, int id)
540{
541 wxASSERT(bitmap.IsOk());
542 if(m_items.IsEmpty())
543 {
544 m_bitmap_size = bitmap.GetSize();
545 CalculateMinSize();
546 }
547 else
548 {
549 wxASSERT(bitmap.GetSize() == m_bitmap_size);
550 }
551
552 wxRibbonGalleryItem *item = new wxRibbonGalleryItem;
553 item->SetId(id);
554 item->SetBitmap(bitmap);
555 m_items.Add(item);
556 return item;
557}
558
559wxRibbonGalleryItem* wxRibbonGallery::Append(const wxBitmap& bitmap, int id,
560 void* clientData)
561{
562 wxRibbonGalleryItem *item = Append(bitmap, id);
563 item->SetClientData(clientData);
564 return item;
565}
566
567wxRibbonGalleryItem* wxRibbonGallery::Append(const wxBitmap& bitmap, int id,
568 wxClientData* clientData)
569{
570 wxRibbonGalleryItem *item = Append(bitmap, id);
571 item->SetClientObject(clientData);
572 return item;
573}
574
575void wxRibbonGallery::Clear()
576{
577 size_t item_count = m_items.Count();
578 size_t item_i;
579 for(item_i = 0; item_i < item_count; ++item_i)
580 {
581 wxRibbonGalleryItem *item = m_items.Item(item_i);
582 delete item;
583 }
584 m_items.Clear();
585}
586
587bool wxRibbonGallery::IsSizingContinuous() const
588{
589 return false;
590}
591
592void wxRibbonGallery::CalculateMinSize()
593{
594 if(m_art == NULL || !m_bitmap_size.IsFullySpecified())
595 {
596 SetMinSize(wxSize(20, 20));
597 }
598 else
599 {
600 m_bitmap_padded_size = m_bitmap_size;
601 m_bitmap_padded_size.IncBy(
602 m_art->GetMetric(wxRIBBON_ART_GALLERY_BITMAP_PADDING_LEFT_SIZE) +
603 m_art->GetMetric(wxRIBBON_ART_GALLERY_BITMAP_PADDING_RIGHT_SIZE),
604 m_art->GetMetric(wxRIBBON_ART_GALLERY_BITMAP_PADDING_TOP_SIZE) +
605 m_art->GetMetric(wxRIBBON_ART_GALLERY_BITMAP_PADDING_BOTTOM_SIZE));
606
607 wxMemoryDC dc;
608 SetMinSize(m_art->GetGallerySize(dc, this, m_bitmap_padded_size));
609
610 // The best size is displaying several items
611 m_best_size = m_bitmap_padded_size;
612 m_best_size.x *= 3;
613 m_best_size = m_art->GetGallerySize(dc, this, m_best_size);
614 }
615}
616
617bool wxRibbonGallery::Realize()
618{
619 CalculateMinSize();
620 return Layout();
621}
622
623bool wxRibbonGallery::Layout()
624{
625 if(m_art == NULL)
626 return false;
627
628 wxMemoryDC dc;
629 wxPoint origin;
630 wxSize client_size = m_art->GetGalleryClientSize(dc, this, GetSize(),
631 &origin, &m_scroll_up_button_rect, &m_scroll_down_button_rect,
632 &m_extension_button_rect);
633 m_client_rect = wxRect(origin, client_size);
634
635 int x_cursor = 0;
636 int y_cursor = 0;
637
638 size_t item_count = m_items.Count();
639 size_t item_i;
640 long art_flags = m_art->GetFlags();
641 for(item_i = 0; item_i < item_count; ++item_i)
642 {
643 wxRibbonGalleryItem *item = m_items.Item(item_i);
644 item->SetIsVisible(true);
645 if(art_flags & wxRIBBON_BAR_FLOW_VERTICAL)
646 {
647 if(y_cursor + m_bitmap_padded_size.y > client_size.GetHeight())
648 {
649 if(y_cursor == 0)
650 break;
651 y_cursor = 0;
652 x_cursor += m_bitmap_padded_size.x;
653 }
654 item->SetPosition(origin.x + x_cursor, origin.y + y_cursor,
655 m_bitmap_padded_size);
656 y_cursor += m_bitmap_padded_size.y;
657 }
658 else
659 {
660 if(x_cursor + m_bitmap_padded_size.x > client_size.GetWidth())
661 {
662 if(x_cursor == 0)
663 break;
664 x_cursor = 0;
665 y_cursor += m_bitmap_padded_size.y;
666 }
667 item->SetPosition(origin.x + x_cursor, origin.y + y_cursor,
668 m_bitmap_padded_size);
669 x_cursor += m_bitmap_padded_size.x;
670 }
671 }
672 for(; item_i < item_count; ++item_i)
673 {
674 wxRibbonGalleryItem *item = m_items.Item(item_i);
675 item->SetIsVisible(false);
676 }
677 if(art_flags & wxRIBBON_BAR_FLOW_VERTICAL)
678 m_scroll_limit = x_cursor;
679 else
680 m_scroll_limit = y_cursor;
681 if(m_scroll_amount >= m_scroll_limit)
682 {
683 m_scroll_amount = m_scroll_limit;
684 m_down_button_state = wxRIBBON_GALLERY_BUTTON_DISABLED;
685 }
686 else if(m_down_button_state == wxRIBBON_GALLERY_BUTTON_DISABLED)
687 m_down_button_state = wxRIBBON_GALLERY_BUTTON_NORMAL;
688
689 if(m_scroll_amount <= 0)
690 {
691 m_scroll_amount = 0;
692 m_up_button_state = wxRIBBON_GALLERY_BUTTON_DISABLED;
693 }
694 else if(m_up_button_state == wxRIBBON_GALLERY_BUTTON_DISABLED)
695 m_up_button_state = wxRIBBON_GALLERY_BUTTON_NORMAL;
696
697 return true;
698}
699
700wxSize wxRibbonGallery::DoGetBestSize() const
701{
702 return m_best_size;
703}
704
705wxSize wxRibbonGallery::DoGetNextSmallerSize(wxOrientation direction,
706 wxSize relative_to) const
707{
708 if(m_art == NULL)
709 return relative_to;
710
711 wxMemoryDC dc;
712
713 wxSize client = m_art->GetGalleryClientSize(dc, this, relative_to, NULL,
714 NULL, NULL, NULL);
715 switch(direction)
716 {
717 case wxHORIZONTAL:
718 client.DecBy(1, 0);
719 break;
720 case wxVERTICAL:
721 client.DecBy(0, 1);
722 break;
723 case wxBOTH:
724 client.DecBy(1, 1);
725 break;
726 }
727 if(client.GetWidth() < 0 || client.GetHeight() < 0)
728 return relative_to;
729
730 client.x = (client.x / m_bitmap_padded_size.x) * m_bitmap_padded_size.x;
731 client.y = (client.y / m_bitmap_padded_size.y) * m_bitmap_padded_size.y;
732
733 wxSize size = m_art->GetGallerySize(dc, this, client);
734 wxSize minimum = GetMinSize();
735
736 if(size.GetWidth() < minimum.GetWidth() ||
737 size.GetHeight() < minimum.GetHeight())
738 {
739 return relative_to;
740 }
741
742 switch(direction)
743 {
744 case wxHORIZONTAL:
745 size.SetHeight(relative_to.GetHeight());
746 break;
747 case wxVERTICAL:
748 size.SetWidth(relative_to.GetWidth());
749 break;
750 default:
751 break;
752 }
753
754 return size;
755}
756
757wxSize wxRibbonGallery::DoGetNextLargerSize(wxOrientation direction,
758 wxSize relative_to) const
759{
760 if(m_art == NULL)
761 return relative_to;
762
763 wxMemoryDC dc;
764
765 wxSize client = m_art->GetGalleryClientSize(dc, this, relative_to, NULL,
766 NULL, NULL, NULL);
767
768 // No need to grow if the given size can already display every item
769 int nitems = (client.GetWidth() / m_bitmap_padded_size.x) *
770 (client.GetHeight() / m_bitmap_padded_size.y);
771 if(nitems >= (int)m_items.GetCount())
772 return relative_to;
773
774 switch(direction)
775 {
776 case wxHORIZONTAL:
777 client.IncBy(m_bitmap_padded_size.x, 0);
778 break;
779 case wxVERTICAL:
780 client.IncBy(0, m_bitmap_padded_size.y);
781 break;
782 case wxBOTH:
783 client.IncBy(m_bitmap_padded_size);
784 break;
785 }
786
787 client.x = (client.x / m_bitmap_padded_size.x) * m_bitmap_padded_size.x;
788 client.y = (client.y / m_bitmap_padded_size.y) * m_bitmap_padded_size.y;
789
790 wxSize size = m_art->GetGallerySize(dc, this, client);
791 wxSize minimum = GetMinSize();
792
793 if(size.GetWidth() < minimum.GetWidth() ||
794 size.GetHeight() < minimum.GetHeight())
795 {
796 return relative_to;
797 }
798
799 switch(direction)
800 {
801 case wxHORIZONTAL:
802 size.SetHeight(relative_to.GetHeight());
803 break;
804 case wxVERTICAL:
805 size.SetWidth(relative_to.GetWidth());
806 break;
807 default:
808 break;
809 }
810
811 return size;
812}
813
814bool wxRibbonGallery::IsEmpty() const
815{
816 return m_items.IsEmpty();
817}
818
819unsigned int wxRibbonGallery::GetCount() const
820{
821 return (unsigned int)m_items.GetCount();
822}
823
824wxRibbonGalleryItem* wxRibbonGallery::GetItem(unsigned int n)
825{
826 if(n >= GetCount())
827 return NULL;
828 return m_items.Item(n);
829}
830
831void wxRibbonGallery::SetSelection(wxRibbonGalleryItem* item)
832{
833 if(item != m_selected_item)
834 {
835 m_selected_item = item;
836 Refresh(false);
837 }
838}
839
840wxRibbonGalleryItem* wxRibbonGallery::GetSelection() const
841{
842 return m_selected_item;
843}
844
845wxRibbonGalleryItem* wxRibbonGallery::GetHoveredItem() const
846{
847 return m_hovered_item;
848}
849
850wxRibbonGalleryItem* wxRibbonGallery::GetActiveItem() const
851{
852 return m_active_item;
853}
854
855wxRibbonGalleryButtonState wxRibbonGallery::GetUpButtonState() const
856{
857 return m_up_button_state;
858}
859
860wxRibbonGalleryButtonState wxRibbonGallery::GetDownButtonState() const
861{
862 return m_down_button_state;
863}
864
865wxRibbonGalleryButtonState wxRibbonGallery::GetExtensionButtonState() const
866{
867 return m_extension_button_state;
868}
869
870#endif // wxUSE_RIBBON