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