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