1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/ribbon/art_msw.cpp
3 // Purpose:     MSW style art provider for ribbon interface
4 // Author:      Peter Cawley
5 // Modified by:
6 // Created:     2009-05-25
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 
17 #if wxUSE_RIBBON
18 
19 #include "wx/ribbon/art.h"
20 #include "wx/ribbon/art_internal.h"
21 #include "wx/ribbon/buttonbar.h"
22 #include "wx/ribbon/gallery.h"
23 #include "wx/ribbon/toolbar.h"
24 
25 #ifndef WX_PRECOMP
26 #include "wx/dcmemory.h"
27 #endif
28 
29 #ifdef __WXMSW__
30 #include "wx/msw/private.h"
31 #endif
32 
33 static const char* const gallery_up_xpm[] = {
34   "5 5 2 1",
35   "  c None",
36   "x c #FF00FF",
37   "     ",
38   "  x  ",
39   " xxx ",
40   "xxxxx",
41   "     "};
42 
43 static const char* const gallery_down_xpm[] = {
44   "5 5 2 1",
45   "  c None",
46   "x c #FF00FF",
47   "     ",
48   "xxxxx",
49   " xxx ",
50   "  x  ",
51   "     "};
52 
53 static const char* const gallery_left_xpm[] = {
54   "5 5 2 1",
55   "  c None",
56   "x c #FF00FF",
57   "   x ",
58   "  xx ",
59   " xxx ",
60   "  xx ",
61   "   x "};
62 
63 static const char* const gallery_right_xpm[] = {
64   "5 5 2 1",
65   "  c None",
66   "x c #FF00FF",
67   " x   ",
68   " xx  ",
69   " xxx ",
70   " xx  ",
71   " x   "};
72 
73 static const char* const gallery_extension_xpm[] = {
74   "5 5 2 1",
75   "  c None",
76   "x c #FF00FF",
77   "xxxxx",
78   "     ",
79   "xxxxx",
80   " xxx ",
81   "  x  "};
82 
83 static const char* const panel_extension_xpm[] = {
84   "7 7 2 1",
85   "  c None",
86   "x c #FF00FF",
87   "xxxxxx ",
88   "x      ",
89   "x      ",
90   "x  x  x",
91   "x   xxx",
92   "x   xxx",
93   "   xxxx"};
94 
95 static const char* const panel_toggle_down_xpm[] = {
96   "7 9 2 1",
97   "  c None",
98   "x c #FF00FF",
99   "       ",
100   "x     x",
101   "xx   xx",
102   " xx xx ",
103   "x xxx x",
104   "xx x xx",
105   " xx xx ",
106   "  xxx  ",
107   "   x   ",};
108 
109 static const char* const panel_toggle_up_xpm[] = {
110   "7 9 2 1",
111   "  c None",
112   "x c #FF00FF",
113   "   x   ",
114   "  xxx  ",
115   " xx xx ",
116   "xx x xx",
117   "x xxx x",
118   " xx xx ",
119   "xx   xx",
120   "x     x",
121   "       ",};
122 
123 static const char* const ribbon_toggle_pin_xpm[] = {
124   "12 9 3 1",
125   "  c None",
126   "x c #FF00FF",
127   ". c #FF00FF",
128   "   xx       ",
129   "   x.x   xxx",
130   "   x..xxx..x",
131   "xxxx.......x",
132   "x..........x",
133   "xxxx.......x",
134   "   x..xxx..x",
135   "   x.x   xxx",
136   "   xx       "
137 };
138 
139 static const char * const ribbon_help_button_xpm[] = {
140 "12 12 112 2",
141 "   c #163B95",
142 ".  c none",
143 "X  c #1B3F98",
144 "o  c #1B4097",
145 "O  c #1D4198",
146 "+  c #1E4298",
147 "@  c #1E439B",
148 "#  c #1A419F",
149 "$  c #1E439D",
150 "%  c #204398",
151 "&  c #204399",
152 "*  c #25479B",
153 "=  c #25489A",
154 "-  c #284A9D",
155 ";  c #2A4C9D",
156 ":  c #30519E",
157 ">  c #3B589A",
158 ",  c #3D599B",
159 "<  c #1840A2",
160 "1  c #1E45A1",
161 "2  c #1E4AB4",
162 "3  c #2D4FA0",
163 "4  c #224AAC",
164 "5  c #254DAC",
165 "6  c #294FA9",
166 "7  c #2B52AE",
167 "8  c #3051A0",
168 "9  c #3354A0",
169 "0  c #3354A2",
170 "q  c #3454A3",
171 "w  c #3456A4",
172 "e  c #3556A4",
173 "r  c #3C5BA3",
174 "t  c #395AA6",
175 "y  c #3E5CA6",
176 "u  c #3E5DA7",
177 "i  c #3F5EA6",
178 "p  c #2A51B0",
179 "a  c #2E55B5",
180 "s  c #2752BA",
181 "d  c #3058B8",
182 "f  c #3F61B2",
183 "g  c #415FA7",
184 "h  c #4562A7",
185 "j  c #4864A7",
186 "k  c #4D67A5",
187 "l  c #4361A8",
188 "z  c #4361A9",
189 "x  c #4663A8",
190 "c  c #4563AA",
191 "v  c #4764AA",
192 "b  c #4B68AE",
193 "n  c #506AA8",
194 "m  c #516DAD",
195 "M  c #546EAC",
196 "N  c #5F75AB",
197 "B  c #5A72AC",
198 "V  c #5C77B6",
199 "C  c #6C7DA7",
200 "Z  c #6077AD",
201 "A  c #687DAF",
202 "S  c #637BB4",
203 "D  c #687FB7",
204 "F  c #2D59C1",
205 "G  c #2E5AC2",
206 "H  c #2F5ECE",
207 "J  c #3763CC",
208 "K  c #4169CB",
209 "L  c #7787AC",
210 "P  c #7E8CAE",
211 "I  c #7A8BB5",
212 "U  c #7B8CB4",
213 "Y  c #7C8FBD",
214 "T  c #758FCA",
215 "R  c #808CA8",
216 "E  c #969DAF",
217 "W  c #8291B4",
218 "Q  c #8A95B0",
219 "!  c #8B96B1",
220 "~  c #8F9AB3",
221 "^  c #8D98B5",
222 "/  c #8E9AB7",
223 "(  c #8997B8",
224 ")  c #949EB9",
225 "_  c #99A1B4",
226 "`  c #ADAFB7",
227 "'  c #A5ABB8",
228 "]  c #A6ABB8",
229 "[  c #AAAFBE",
230 "{  c #AFB2BE",
231 "}  c #B0B1B6",
232 "|  c #BAB8B6",
233 " . c #B4B5BC",
234 ".. c #B6B9BF",
235 "X. c #BBB9B8",
236 "o. c #8C9DC3",
237 "O. c #8EA3D4",
238 "+. c #97AAD4",
239 "@. c #ACB5C9",
240 "#. c #B3B7C0",
241 "$. c #A1B1D5",
242 "%. c #BAC3D7",
243 "&. c #BEC6D6",
244 "*. c #D7D2C7",
245 "=. c #C2C8D6",
246 "-. c #D2D6DF",
247 ";. c #E8E4DA",
248 ":. c #CED5E4",
249 ">. c #FFF9EC",
250 ",. c #F3F4F5",
251 "<. c #F6F8FB",
252 "1. c None",
253 /* pixels */
254 "1.1.1.1.#./ W ~ } 1.1.1.",
255 "1.1.1.U r c b t h Q 1.1.",
256 "1.1.A 3 $.<.,.&.m w ^ 1.",
257 "1.( 0 z :.%.=.;.) e x ` ",
258 "1.n u v M * B *.R O @ P ",
259 "' i z l - 9 { | > $ # Z ",
260 "_ y l ; & [ X., 1 6 4 D ",
261 "] g 8 o :  .C < 7 a s o.",
262 "1.k X % = I S 5 d G K ..",
263 "1.! .   j >.-.p F H +.1.",
264 "1.1.L X + Y V 2 J O.1.1.",
265 "1.1.1.E N q f T @.1.1.1."
266 };
267 
wxRibbonMSWArtProvider(bool set_colour_scheme)268 wxRibbonMSWArtProvider::wxRibbonMSWArtProvider(bool set_colour_scheme)
269 {
270     m_flags = 0;
271 #if defined( __WXMAC__ )
272     m_tab_label_font = *wxSMALL_FONT;
273 #else
274     m_tab_label_font = *wxNORMAL_FONT;
275 #endif
276     m_button_bar_label_font = m_tab_label_font;
277     m_panel_label_font = m_tab_label_font;
278 
279     if(set_colour_scheme)
280     {
281         SetColourScheme(
282             wxColour(194, 216, 241),
283             wxColour(255, 223, 114),
284             wxColour(  0,   0,   0));
285     }
286 
287     m_cached_tab_separator_visibility = -10.0; // valid visibilities are in range [0, 1]
288     m_tab_separation_size = 3;
289     m_page_border_left = 2;
290     m_page_border_top = 1;
291     m_page_border_right = 2;
292     m_page_border_bottom = 3;
293     m_panel_x_separation_size = 1;
294     m_panel_y_separation_size = 1;
295     m_tool_group_separation_size = 3;
296     m_gallery_bitmap_padding_left_size = 4;
297     m_gallery_bitmap_padding_right_size = 4;
298     m_gallery_bitmap_padding_top_size = 4;
299     m_gallery_bitmap_padding_bottom_size = 4;
300     m_toggle_button_offset = 22;
301     m_help_button_offset = 22;
302 }
303 
~wxRibbonMSWArtProvider()304 wxRibbonMSWArtProvider::~wxRibbonMSWArtProvider()
305 {
306 }
307 
GetColourScheme(wxColour * primary,wxColour * secondary,wxColour * tertiary) const308 void wxRibbonMSWArtProvider::GetColourScheme(
309                          wxColour* primary,
310                          wxColour* secondary,
311                          wxColour* tertiary) const
312 {
313     if(primary != NULL)
314         *primary = m_primary_scheme_colour;
315     if(secondary != NULL)
316         *secondary = m_secondary_scheme_colour;
317     if(tertiary != NULL)
318         *tertiary = m_tertiary_scheme_colour;
319 }
320 
SetColourScheme(const wxColour & primary,const wxColour & secondary,const wxColour & tertiary)321 void wxRibbonMSWArtProvider::SetColourScheme(
322                          const wxColour& primary,
323                          const wxColour& secondary,
324                          const wxColour& tertiary)
325 {
326     m_primary_scheme_colour = primary;
327     m_secondary_scheme_colour = secondary;
328     m_tertiary_scheme_colour = tertiary;
329 
330     wxRibbonHSLColour primary_hsl(primary);
331     wxRibbonHSLColour secondary_hsl(secondary);
332     // tertiary not used for anything
333 
334     // Map primary saturation from [0, 1] to [.25, .75]
335     bool primary_is_gray = false;
336     static const double gray_saturation_threshold = 0.01;
337     if(primary_hsl.saturation <= gray_saturation_threshold)
338         primary_is_gray = true;
339     else
340     {
341         primary_hsl.saturation = cos(primary_hsl.saturation * M_PI)
342             * -0.25 + 0.5;
343     }
344 
345     // Map primary luminance from [0, 1] to [.23, .83]
346     primary_hsl.luminance = cos(primary_hsl.luminance * M_PI) * -0.3 + 0.53;
347 
348     // Map secondary saturation from [0, 1] to [0.16, 0.84]
349     bool secondary_is_gray = false;
350     if(secondary_hsl.saturation <= gray_saturation_threshold)
351         secondary_is_gray = true;
352     else
353     {
354         secondary_hsl.saturation = cos(secondary_hsl.saturation * M_PI)
355             * -0.34 + 0.5;
356     }
357 
358     // Map secondary luminance from [0, 1] to [0.1, 0.9]
359     secondary_hsl.luminance = cos(secondary_hsl.luminance * M_PI) * -0.4 + 0.5;
360 
361 #define LikePrimary(h, s, l) \
362     primary_hsl.ShiftHue(h ## f).Saturated(primary_is_gray ? 0 : s ## f) \
363     .Lighter(l ## f).ToRGB()
364 #define LikeSecondary(h, s, l) \
365     secondary_hsl.ShiftHue(h ## f).Saturated(secondary_is_gray ? 0 : s ## f) \
366     .Lighter(l ## f).ToRGB()
367 
368     m_page_border_pen = LikePrimary(1.4, 0.00, -0.08);
369 
370     m_page_background_top_colour = LikePrimary(-0.1, -0.03, 0.12);
371     m_page_hover_background_top_colour = LikePrimary(-2.8, 0.27, 0.17);
372     m_page_background_top_gradient_colour = LikePrimary(0.1, -0.10, 0.08);
373     m_page_hover_background_top_gradient_colour = LikePrimary(3.2, 0.16, 0.13);
374     m_page_background_colour = LikePrimary(0.4, -0.09, 0.05);
375     m_page_hover_background_colour = LikePrimary(0.1, 0.19, 0.10);
376     m_page_background_gradient_colour = LikePrimary(-3.2, 0.27, 0.10);
377     m_page_hover_background_gradient_colour = LikePrimary(1.8, 0.01, 0.15);
378 
379     m_tab_active_background_colour = LikePrimary(-0.1, -0.31, 0.16);
380     m_tab_active_background_gradient_colour = LikePrimary(-0.1, -0.03, 0.12);
381     m_tab_separator_colour = LikePrimary(0.9, 0.24, 0.05);
382     m_tab_ctrl_background_brush = LikePrimary(1.0, 0.39, 0.07);
383     m_tab_hover_background_colour = LikePrimary(1.3, 0.15, 0.10);
384     m_tab_hover_background_top_colour = LikePrimary(1.4, 0.36, 0.08);
385     m_tab_border_pen = LikePrimary(1.4, 0.03, -0.05);
386     m_tab_separator_gradient_colour = LikePrimary(1.7, -0.15, -0.18);
387     m_tab_hover_background_top_gradient_colour = LikePrimary(1.8, 0.34, 0.13);
388     m_tab_label_colour = LikePrimary(4.3, 0.13, -0.49);
389     m_tab_hover_background_gradient_colour = LikeSecondary(-1.5, -0.34, 0.01);
390 
391     m_panel_minimised_border_gradient_pen = LikePrimary(-6.9, -0.17, -0.09);
392     m_panel_minimised_border_pen = LikePrimary(-5.3, -0.24, -0.06);
393     m_panel_border_gradient_pen = LikePrimary(-5.2, -0.15, -0.06);
394     m_panel_border_pen = LikePrimary(-2.8, -0.32, 0.02);
395     m_panel_label_background_brush = LikePrimary(-1.5, 0.03, 0.05);
396     m_panel_active_background_gradient_colour = LikePrimary(0.5, 0.34, 0.05);
397     m_panel_hover_label_background_brush = LikePrimary(1.0, 0.30, 0.09);
398     m_panel_active_background_top_gradient_colour = LikePrimary(1.4, -0.17, -0.13);
399     m_panel_active_background_colour = LikePrimary(1.6, -0.18, -0.18);
400     m_panel_active_background_top_colour = LikePrimary(1.7, -0.20, -0.03);
401     m_panel_label_colour = LikePrimary(2.8, -0.14, -0.35);
402     m_panel_hover_label_colour = m_panel_label_colour;
403     m_panel_minimised_label_colour = m_tab_label_colour;
404     m_panel_hover_button_background_brush = LikeSecondary(-0.9, 0.16, -0.07);
405     m_panel_hover_button_border_pen = LikeSecondary(-3.9, -0.16, -0.14);
406     SetColour(wxRIBBON_ART_PANEL_BUTTON_FACE_COLOUR, LikePrimary(1.4, -0.21, -0.23));
407     SetColour(wxRIBBON_ART_PANEL_BUTTON_HOVER_FACE_COLOUR, LikePrimary(1.5, -0.24, -0.29));
408 
409     m_ribbon_toggle_brush = LikeSecondary(-0.9, 0.16, -0.07);
410     m_ribbon_toggle_pen = LikeSecondary(-3.9, -0.16, -0.14);
411     SetColour(wxRIBBON_ART_PAGE_TOGGLE_FACE_COLOUR, LikePrimary(1.7, -0.20, -0.15));
412     SetColour(wxRIBBON_ART_PAGE_TOGGLE_HOVER_FACE_COLOUR, LikePrimary(1.8, -0.23, -0.21));
413 
414     m_gallery_button_disabled_background_colour = LikePrimary(-2.8, -0.46, 0.09);
415     m_gallery_button_disabled_background_top_brush = LikePrimary(-2.8, -0.36, 0.15);
416     m_gallery_hover_background_brush = LikePrimary(-0.8, 0.05, 0.15);
417     m_gallery_border_pen = LikePrimary(0.7, -0.02, 0.03);
418     m_gallery_button_background_top_brush = LikePrimary(0.8, 0.34, 0.13);
419     m_gallery_button_background_colour = LikePrimary(1.3, 0.10, 0.08);
420     // SetColour used so that the relevant bitmaps are generated
421     SetColour(wxRIBBON_ART_GALLERY_BUTTON_FACE_COLOUR, LikePrimary(1.4, -0.21, -0.23));
422     SetColour(wxRIBBON_ART_GALLERY_BUTTON_HOVER_FACE_COLOUR, LikePrimary(1.5, -0.24, -0.29));
423     SetColour(wxRIBBON_ART_GALLERY_BUTTON_ACTIVE_FACE_COLOUR, LikePrimary(1.5, -0.24, -0.29));
424     SetColour(wxRIBBON_ART_GALLERY_BUTTON_DISABLED_FACE_COLOUR, LikePrimary(0.0, -1.0, 0.0));
425     m_gallery_button_disabled_background_gradient_colour = LikePrimary(1.5, -0.43, 0.12);
426     m_gallery_button_background_gradient_colour = LikePrimary(1.7, 0.11, 0.09);
427     m_gallery_item_border_pen = LikeSecondary(-3.9, -0.16, -0.14);
428     m_gallery_button_hover_background_colour = LikeSecondary(-0.9, 0.16, -0.07);
429     m_gallery_button_hover_background_gradient_colour = LikeSecondary(0.1, 0.12, 0.03);
430     m_gallery_button_hover_background_top_brush = LikeSecondary(4.3, 0.16, 0.17);
431 
432     m_gallery_button_active_background_colour = LikeSecondary(-9.9, 0.03, -0.22);
433     m_gallery_button_active_background_gradient_colour = LikeSecondary(-9.5, 0.14, -0.11);
434     m_gallery_button_active_background_top_brush = LikeSecondary(-9.0, 0.15, -0.08);
435 
436     m_button_bar_label_colour = m_tab_label_colour;
437     m_button_bar_label_disabled_colour = m_tab_label_colour;
438 
439     m_button_bar_hover_border_pen = LikeSecondary(-6.2, -0.47, -0.14);
440     m_button_bar_hover_background_gradient_colour = LikeSecondary(-0.6, 0.16, 0.04);
441     m_button_bar_hover_background_colour = LikeSecondary(-0.2, 0.16, -0.10);
442     m_button_bar_hover_background_top_gradient_colour = LikeSecondary(0.2, 0.16, 0.03);
443     m_button_bar_hover_background_top_colour = LikeSecondary(8.8, 0.16, 0.17);
444     m_button_bar_active_border_pen = LikeSecondary(-6.2, -0.47, -0.25);
445     m_button_bar_active_background_top_colour = LikeSecondary(-8.4, 0.08, 0.06);
446     m_button_bar_active_background_top_gradient_colour = LikeSecondary(-9.7, 0.13, -0.07);
447     m_button_bar_active_background_colour = LikeSecondary(-9.9, 0.14, -0.14);
448     m_button_bar_active_background_gradient_colour = LikeSecondary(-8.7, 0.17, -0.03);
449 
450     m_toolbar_border_pen = LikePrimary(1.4, -0.21, -0.16);
451     SetColour(wxRIBBON_ART_TOOLBAR_FACE_COLOUR, LikePrimary(1.4, -0.17, -0.22));
452     m_tool_background_top_colour = LikePrimary(-1.9, -0.07, 0.06);
453     m_tool_background_top_gradient_colour = LikePrimary(1.4, 0.12, 0.08);
454     m_tool_background_colour = LikePrimary(1.4, -0.09, 0.03);
455     m_tool_background_gradient_colour = LikePrimary(1.9, 0.11, 0.09);
456     m_tool_hover_background_top_colour = LikeSecondary(3.4, 0.11, 0.16);
457     m_tool_hover_background_top_gradient_colour = LikeSecondary(-1.4, 0.04, 0.08);
458     m_tool_hover_background_colour = LikeSecondary(-1.8, 0.16, -0.12);
459     m_tool_hover_background_gradient_colour = LikeSecondary(-2.6, 0.16, 0.05);
460     m_tool_active_background_top_colour = LikeSecondary(-9.9, -0.12, -0.09);
461     m_tool_active_background_top_gradient_colour = LikeSecondary(-8.5, 0.16, -0.12);
462     m_tool_active_background_colour = LikeSecondary(-7.9, 0.16, -0.20);
463     m_tool_active_background_gradient_colour = LikeSecondary(-6.6, 0.16, -0.10);
464 
465 #undef LikePrimary
466 #undef LikeSecondary
467 
468     // Invalidate cached tab separator
469     m_cached_tab_separator_visibility = -1.0;
470 }
471 
Clone() const472 wxRibbonArtProvider* wxRibbonMSWArtProvider::Clone() const
473 {
474     wxRibbonMSWArtProvider *copy = new wxRibbonMSWArtProvider;
475     CloneTo(copy);
476     return copy;
477 }
478 
CloneTo(wxRibbonMSWArtProvider * copy) const479 void wxRibbonMSWArtProvider::CloneTo(wxRibbonMSWArtProvider* copy) const
480 {
481     int i;
482     for(i = 0; i < 4; ++i)
483     {
484         copy->m_gallery_up_bitmap[i] = m_gallery_up_bitmap[i];
485         copy->m_gallery_down_bitmap[i] = m_gallery_down_bitmap[i];
486         copy->m_gallery_extension_bitmap[i] = m_gallery_extension_bitmap[i];
487     }
488     for(i = 0; i < 2; ++i)
489     {
490         copy->m_panel_extension_bitmap[i] = m_panel_extension_bitmap[i];
491         copy->m_ribbon_toggle_up_bitmap[i] = m_ribbon_toggle_up_bitmap[i];
492         copy->m_ribbon_toggle_down_bitmap[i] = m_ribbon_toggle_down_bitmap[i];
493         copy->m_ribbon_toggle_pin_bitmap[i] = m_ribbon_toggle_pin_bitmap[i];
494         copy->m_ribbon_bar_help_button_bitmap[i] = m_ribbon_bar_help_button_bitmap[i];
495     }
496     copy->m_toolbar_drop_bitmap = m_toolbar_drop_bitmap;
497 
498     copy->m_primary_scheme_colour = m_primary_scheme_colour;
499     copy->m_secondary_scheme_colour = m_secondary_scheme_colour;
500     copy->m_tertiary_scheme_colour = m_tertiary_scheme_colour;
501 
502     copy->m_page_toggle_face_colour = m_page_toggle_face_colour;
503     copy->m_page_toggle_hover_face_colour = m_page_toggle_hover_face_colour;
504 
505     copy->m_button_bar_label_colour = m_button_bar_label_colour;
506     copy->m_button_bar_label_disabled_colour = m_button_bar_label_disabled_colour;
507     copy->m_tab_label_colour = m_tab_label_colour;
508     copy->m_tab_separator_colour = m_tab_separator_colour;
509     copy->m_tab_separator_gradient_colour = m_tab_separator_gradient_colour;
510     copy->m_tab_active_background_colour = m_tab_hover_background_colour;
511     copy->m_tab_active_background_gradient_colour = m_tab_hover_background_gradient_colour;
512     copy->m_tab_hover_background_colour = m_tab_hover_background_colour;
513     copy->m_tab_hover_background_gradient_colour = m_tab_hover_background_gradient_colour;
514     copy->m_tab_hover_background_top_colour = m_tab_hover_background_top_colour;
515     copy->m_tab_hover_background_top_gradient_colour = m_tab_hover_background_top_gradient_colour;
516     copy->m_panel_label_colour = m_panel_label_colour;
517     copy->m_panel_hover_label_colour = m_panel_hover_label_colour;
518     copy->m_panel_minimised_label_colour = m_panel_minimised_label_colour;
519     copy->m_panel_button_face_colour = m_panel_button_face_colour;
520     copy->m_panel_button_hover_face_colour = m_panel_button_hover_face_colour;
521     copy->m_panel_active_background_colour = m_panel_active_background_colour;
522     copy->m_panel_active_background_gradient_colour = m_panel_active_background_gradient_colour;
523     copy->m_panel_active_background_top_colour = m_panel_active_background_top_colour;
524     copy->m_panel_active_background_top_gradient_colour = m_panel_active_background_top_gradient_colour;
525     copy->m_page_background_colour = m_page_background_colour;
526     copy->m_page_background_gradient_colour = m_page_background_gradient_colour;
527     copy->m_page_background_top_colour = m_page_background_top_colour;
528     copy->m_page_background_top_gradient_colour = m_page_background_top_gradient_colour;
529     copy->m_page_hover_background_colour = m_page_hover_background_colour;
530     copy->m_page_hover_background_gradient_colour = m_page_hover_background_gradient_colour;
531     copy->m_page_hover_background_top_colour = m_page_hover_background_top_colour;
532     copy->m_page_hover_background_top_gradient_colour = m_page_hover_background_top_gradient_colour;
533     copy->m_button_bar_hover_background_colour = m_button_bar_hover_background_colour;
534     copy->m_button_bar_hover_background_gradient_colour = m_button_bar_hover_background_gradient_colour;
535     copy->m_button_bar_hover_background_top_colour = m_button_bar_hover_background_top_colour;
536     copy->m_button_bar_hover_background_top_gradient_colour = m_button_bar_hover_background_top_gradient_colour;
537     copy->m_button_bar_active_background_colour = m_button_bar_active_background_colour;
538     copy->m_button_bar_active_background_gradient_colour = m_button_bar_active_background_gradient_colour;
539     copy->m_button_bar_active_background_top_colour = m_button_bar_active_background_top_colour;
540     copy->m_button_bar_active_background_top_gradient_colour = m_button_bar_active_background_top_gradient_colour;
541     copy->m_gallery_button_background_colour = m_gallery_button_background_colour;
542     copy->m_gallery_button_background_gradient_colour = m_gallery_button_background_gradient_colour;
543     copy->m_gallery_button_hover_background_colour = m_gallery_button_hover_background_colour;
544     copy->m_gallery_button_hover_background_gradient_colour = m_gallery_button_hover_background_gradient_colour;
545     copy->m_gallery_button_active_background_colour = m_gallery_button_active_background_colour;
546     copy->m_gallery_button_active_background_gradient_colour = m_gallery_button_active_background_gradient_colour;
547     copy->m_gallery_button_disabled_background_colour = m_gallery_button_disabled_background_colour;
548     copy->m_gallery_button_disabled_background_gradient_colour = m_gallery_button_disabled_background_gradient_colour;
549     copy->m_gallery_button_face_colour = m_gallery_button_face_colour;
550     copy->m_gallery_button_hover_face_colour = m_gallery_button_hover_face_colour;
551     copy->m_gallery_button_active_face_colour = m_gallery_button_active_face_colour;
552     copy->m_gallery_button_disabled_face_colour = m_gallery_button_disabled_face_colour;
553 
554     copy->m_tab_ctrl_background_brush = m_tab_ctrl_background_brush;
555     copy->m_panel_label_background_brush = m_panel_label_background_brush;
556     copy->m_panel_hover_label_background_brush = m_panel_hover_label_background_brush;
557     copy->m_panel_hover_button_background_brush = m_panel_hover_button_background_brush;
558     copy->m_gallery_hover_background_brush = m_gallery_hover_background_brush;
559     copy->m_gallery_button_background_top_brush = m_gallery_button_background_top_brush;
560     copy->m_gallery_button_hover_background_top_brush = m_gallery_button_hover_background_top_brush;
561     copy->m_gallery_button_active_background_top_brush = m_gallery_button_active_background_top_brush;
562     copy->m_gallery_button_disabled_background_top_brush = m_gallery_button_disabled_background_top_brush;
563     copy->m_ribbon_toggle_brush = m_ribbon_toggle_brush;
564 
565     copy->m_tab_label_font = m_tab_label_font;
566     copy->m_button_bar_label_font = m_button_bar_label_font;
567     copy->m_panel_label_font = m_panel_label_font;
568 
569     copy->m_page_border_pen = m_page_border_pen;
570     copy->m_panel_border_pen = m_panel_border_pen;
571     copy->m_panel_border_gradient_pen = m_panel_border_gradient_pen;
572     copy->m_panel_minimised_border_pen = m_panel_minimised_border_pen;
573     copy->m_panel_minimised_border_gradient_pen = m_panel_minimised_border_gradient_pen;
574     copy->m_panel_hover_button_border_pen = m_panel_hover_button_border_pen;
575     copy->m_tab_border_pen = m_tab_border_pen;
576     copy->m_gallery_border_pen = m_gallery_border_pen;
577     copy->m_button_bar_hover_border_pen = m_button_bar_hover_border_pen;
578     copy->m_button_bar_active_border_pen = m_button_bar_active_border_pen;
579     copy->m_gallery_item_border_pen = m_gallery_item_border_pen;
580     copy->m_toolbar_border_pen = m_toolbar_border_pen;
581     copy->m_ribbon_toggle_pen = m_ribbon_toggle_pen;
582 
583     copy->m_flags = m_flags;
584     copy->m_tab_separation_size = m_tab_separation_size;
585     copy->m_page_border_left = m_page_border_left;
586     copy->m_page_border_top = m_page_border_top;
587     copy->m_page_border_right = m_page_border_right;
588     copy->m_page_border_bottom = m_page_border_bottom;
589     copy->m_panel_x_separation_size = m_panel_x_separation_size;
590     copy->m_panel_y_separation_size = m_panel_y_separation_size;
591     copy->m_gallery_bitmap_padding_left_size = m_gallery_bitmap_padding_left_size;
592     copy->m_gallery_bitmap_padding_right_size = m_gallery_bitmap_padding_right_size;
593     copy->m_gallery_bitmap_padding_top_size = m_gallery_bitmap_padding_top_size;
594     copy->m_gallery_bitmap_padding_bottom_size = m_gallery_bitmap_padding_bottom_size;
595 }
596 
GetFlags() const597 long wxRibbonMSWArtProvider::GetFlags() const
598 {
599     return m_flags;
600 }
601 
SetFlags(long flags)602 void wxRibbonMSWArtProvider::SetFlags(long flags)
603 {
604     if((flags ^ m_flags) & wxRIBBON_BAR_FLOW_VERTICAL)
605     {
606         if(flags & wxRIBBON_BAR_FLOW_VERTICAL)
607         {
608             m_page_border_left++;
609             m_page_border_right++;
610             m_page_border_top--;
611             m_page_border_bottom--;
612         }
613         else
614         {
615             m_page_border_left--;
616             m_page_border_right--;
617             m_page_border_top++;
618             m_page_border_bottom++;
619         }
620     }
621     m_flags = flags;
622 
623     // Need to reload some bitmaps when flags change
624 #define Reload(setting) SetColour(setting, GetColour(setting))
625     Reload(wxRIBBON_ART_GALLERY_BUTTON_FACE_COLOUR);
626     Reload(wxRIBBON_ART_GALLERY_BUTTON_HOVER_FACE_COLOUR);
627     Reload(wxRIBBON_ART_GALLERY_BUTTON_ACTIVE_FACE_COLOUR);
628     Reload(wxRIBBON_ART_GALLERY_BUTTON_DISABLED_FACE_COLOUR);
629     Reload(wxRIBBON_ART_PANEL_BUTTON_FACE_COLOUR);
630     Reload(wxRIBBON_ART_PANEL_BUTTON_HOVER_FACE_COLOUR);
631 #undef Reload
632 }
633 
GetMetric(int id) const634 int wxRibbonMSWArtProvider::GetMetric(int id) const
635 {
636     switch(id)
637     {
638         case wxRIBBON_ART_TAB_SEPARATION_SIZE:
639             return m_tab_separation_size;
640         case wxRIBBON_ART_PAGE_BORDER_LEFT_SIZE:
641             return m_page_border_left;
642         case wxRIBBON_ART_PAGE_BORDER_TOP_SIZE:
643             return m_page_border_top;
644         case wxRIBBON_ART_PAGE_BORDER_RIGHT_SIZE:
645             return m_page_border_right;
646         case wxRIBBON_ART_PAGE_BORDER_BOTTOM_SIZE:
647             return m_page_border_bottom;
648         case wxRIBBON_ART_PANEL_X_SEPARATION_SIZE:
649             return m_panel_x_separation_size;
650         case wxRIBBON_ART_PANEL_Y_SEPARATION_SIZE:
651             return m_panel_y_separation_size;
652         case wxRIBBON_ART_TOOL_GROUP_SEPARATION_SIZE:
653             return m_tool_group_separation_size;
654         case wxRIBBON_ART_GALLERY_BITMAP_PADDING_LEFT_SIZE:
655             return m_gallery_bitmap_padding_left_size;
656         case wxRIBBON_ART_GALLERY_BITMAP_PADDING_RIGHT_SIZE:
657             return m_gallery_bitmap_padding_right_size;
658         case wxRIBBON_ART_GALLERY_BITMAP_PADDING_TOP_SIZE:
659             return m_gallery_bitmap_padding_top_size;
660         case wxRIBBON_ART_GALLERY_BITMAP_PADDING_BOTTOM_SIZE:
661             return m_gallery_bitmap_padding_bottom_size;
662         default:
663             wxFAIL_MSG(wxT("Invalid Metric Ordinal"));
664             break;
665     }
666 
667     return 0;
668 }
669 
SetMetric(int id,int new_val)670 void wxRibbonMSWArtProvider::SetMetric(int id, int new_val)
671 {
672     switch(id)
673     {
674         case wxRIBBON_ART_TAB_SEPARATION_SIZE:
675             m_tab_separation_size = new_val;
676             break;
677         case wxRIBBON_ART_PAGE_BORDER_LEFT_SIZE:
678             m_page_border_left = new_val;
679             break;
680         case wxRIBBON_ART_PAGE_BORDER_TOP_SIZE:
681             m_page_border_top = new_val;
682             break;
683         case wxRIBBON_ART_PAGE_BORDER_RIGHT_SIZE:
684             m_page_border_right = new_val;
685             break;
686         case wxRIBBON_ART_PAGE_BORDER_BOTTOM_SIZE:
687             m_page_border_bottom = new_val;
688             break;
689         case wxRIBBON_ART_PANEL_X_SEPARATION_SIZE:
690             m_panel_x_separation_size = new_val;
691             break;
692         case wxRIBBON_ART_PANEL_Y_SEPARATION_SIZE:
693             m_panel_y_separation_size = new_val;
694             break;
695         case wxRIBBON_ART_TOOL_GROUP_SEPARATION_SIZE:
696             m_tool_group_separation_size = new_val;
697             break;
698         case wxRIBBON_ART_GALLERY_BITMAP_PADDING_LEFT_SIZE:
699             m_gallery_bitmap_padding_left_size = new_val;
700             break;
701         case wxRIBBON_ART_GALLERY_BITMAP_PADDING_RIGHT_SIZE:
702             m_gallery_bitmap_padding_right_size = new_val;
703             break;
704         case wxRIBBON_ART_GALLERY_BITMAP_PADDING_TOP_SIZE:
705             m_gallery_bitmap_padding_top_size = new_val;
706             break;
707         case wxRIBBON_ART_GALLERY_BITMAP_PADDING_BOTTOM_SIZE:
708             m_gallery_bitmap_padding_bottom_size = new_val;
709             break;
710         default:
711             wxFAIL_MSG(wxT("Invalid Metric Ordinal"));
712             break;
713     }
714 }
715 
SetFont(int id,const wxFont & font)716 void wxRibbonMSWArtProvider::SetFont(int id, const wxFont& font)
717 {
718     switch(id)
719     {
720         case wxRIBBON_ART_TAB_LABEL_FONT:
721             m_tab_label_font = font;
722             break;
723         case wxRIBBON_ART_BUTTON_BAR_LABEL_FONT:
724             m_button_bar_label_font = font;
725             break;
726         case wxRIBBON_ART_PANEL_LABEL_FONT:
727             m_panel_label_font = font;
728             break;
729         default:
730             wxFAIL_MSG(wxT("Invalid Metric Ordinal"));
731             break;
732     }
733 }
734 
GetFont(int id) const735 wxFont wxRibbonMSWArtProvider::GetFont(int id) const
736 {
737     switch(id)
738     {
739         case wxRIBBON_ART_TAB_LABEL_FONT:
740             return m_tab_label_font;
741         case wxRIBBON_ART_BUTTON_BAR_LABEL_FONT:
742             return m_button_bar_label_font;
743         case wxRIBBON_ART_PANEL_LABEL_FONT:
744             return m_panel_label_font;
745         default:
746             wxFAIL_MSG(wxT("Invalid Metric Ordinal"));
747             break;
748     }
749 
750     return wxNullFont;
751 }
752 
GetColour(int id) const753 wxColour wxRibbonMSWArtProvider::GetColour(int id) const
754 {
755     switch(id)
756     {
757         case wxRIBBON_ART_BUTTON_BAR_LABEL_COLOUR:
758             return m_button_bar_label_colour;
759         case wxRIBBON_ART_BUTTON_BAR_LABEL_DISABLED_COLOUR:
760             return m_button_bar_label_disabled_colour;
761         case wxRIBBON_ART_BUTTON_BAR_HOVER_BORDER_COLOUR:
762             return m_button_bar_hover_border_pen.GetColour();
763         case wxRIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_TOP_COLOUR:
764             return m_button_bar_hover_background_top_colour;
765         case wxRIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR:
766             return m_button_bar_hover_background_top_gradient_colour;
767         case wxRIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_COLOUR:
768             return m_button_bar_hover_background_colour;
769         case wxRIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_GRADIENT_COLOUR:
770             return m_button_bar_hover_background_gradient_colour;
771         case wxRIBBON_ART_BUTTON_BAR_ACTIVE_BORDER_COLOUR:
772             return m_button_bar_active_border_pen.GetColour();
773         case wxRIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_TOP_COLOUR:
774             return m_button_bar_active_background_top_colour;
775         case wxRIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR:
776             return m_button_bar_active_background_top_gradient_colour;
777         case wxRIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_COLOUR:
778             return m_button_bar_active_background_colour;
779         case wxRIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_GRADIENT_COLOUR:
780             return m_button_bar_active_background_gradient_colour;
781         case wxRIBBON_ART_GALLERY_BORDER_COLOUR:
782             return m_gallery_border_pen.GetColour();
783         case wxRIBBON_ART_GALLERY_HOVER_BACKGROUND_COLOUR:
784             return m_gallery_hover_background_brush.GetColour();
785         case wxRIBBON_ART_GALLERY_BUTTON_BACKGROUND_COLOUR:
786             return m_gallery_button_background_colour;
787         case wxRIBBON_ART_GALLERY_BUTTON_BACKGROUND_GRADIENT_COLOUR:
788             return m_gallery_button_background_gradient_colour;
789         case wxRIBBON_ART_GALLERY_BUTTON_BACKGROUND_TOP_COLOUR:
790             return m_gallery_button_background_top_brush.GetColour();
791         case wxRIBBON_ART_GALLERY_BUTTON_FACE_COLOUR:
792             return m_gallery_button_face_colour;
793         case wxRIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_COLOUR:
794             return m_gallery_button_hover_background_colour;
795         case wxRIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_GRADIENT_COLOUR:
796             return m_gallery_button_hover_background_gradient_colour;
797         case wxRIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_TOP_COLOUR:
798             return m_gallery_button_hover_background_top_brush.GetColour();
799         case wxRIBBON_ART_GALLERY_BUTTON_HOVER_FACE_COLOUR:
800             return m_gallery_button_face_colour;
801         case wxRIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_COLOUR:
802             return m_gallery_button_active_background_colour;
803         case wxRIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_GRADIENT_COLOUR:
804             return m_gallery_button_active_background_gradient_colour;
805         case wxRIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_TOP_COLOUR:
806             return m_gallery_button_background_top_brush.GetColour();
807         case wxRIBBON_ART_GALLERY_BUTTON_ACTIVE_FACE_COLOUR:
808             return m_gallery_button_active_face_colour;
809         case wxRIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_COLOUR:
810             return m_gallery_button_disabled_background_colour;
811         case wxRIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_GRADIENT_COLOUR:
812             return m_gallery_button_disabled_background_gradient_colour;
813         case wxRIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_TOP_COLOUR:
814             return m_gallery_button_disabled_background_top_brush.GetColour();
815         case wxRIBBON_ART_GALLERY_BUTTON_DISABLED_FACE_COLOUR:
816             return m_gallery_button_disabled_face_colour;
817         case wxRIBBON_ART_GALLERY_ITEM_BORDER_COLOUR:
818             return m_gallery_item_border_pen.GetColour();
819         case wxRIBBON_ART_TAB_CTRL_BACKGROUND_COLOUR:
820         case wxRIBBON_ART_TAB_CTRL_BACKGROUND_GRADIENT_COLOUR:
821             return m_tab_ctrl_background_brush.GetColour();
822         case wxRIBBON_ART_TAB_LABEL_COLOUR:
823             return m_tab_label_colour;
824         case wxRIBBON_ART_TAB_SEPARATOR_COLOUR:
825             return m_tab_separator_colour;
826         case wxRIBBON_ART_TAB_SEPARATOR_GRADIENT_COLOUR:
827             return m_tab_separator_gradient_colour;
828         case wxRIBBON_ART_TAB_ACTIVE_BACKGROUND_TOP_COLOUR:
829         case wxRIBBON_ART_TAB_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR:
830             return wxColour(0, 0, 0);
831         case wxRIBBON_ART_TAB_ACTIVE_BACKGROUND_COLOUR:
832             return m_tab_active_background_colour;
833         case wxRIBBON_ART_TAB_ACTIVE_BACKGROUND_GRADIENT_COLOUR:
834             return m_tab_active_background_gradient_colour;
835         case wxRIBBON_ART_TAB_HOVER_BACKGROUND_TOP_COLOUR:
836             return m_tab_hover_background_top_colour;
837         case wxRIBBON_ART_TAB_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR:
838             return m_tab_hover_background_top_gradient_colour;
839         case wxRIBBON_ART_TAB_HOVER_BACKGROUND_COLOUR:
840             return m_tab_hover_background_colour;
841         case wxRIBBON_ART_TAB_HOVER_BACKGROUND_GRADIENT_COLOUR:
842             return m_tab_hover_background_gradient_colour;
843         case wxRIBBON_ART_TAB_BORDER_COLOUR:
844             return m_tab_border_pen.GetColour();
845         case wxRIBBON_ART_PANEL_BORDER_COLOUR:
846             return m_panel_border_pen.GetColour();
847         case wxRIBBON_ART_PANEL_BORDER_GRADIENT_COLOUR:
848             return m_panel_border_gradient_pen.GetColour();
849         case wxRIBBON_ART_PANEL_MINIMISED_BORDER_COLOUR:
850             return m_panel_minimised_border_pen.GetColour();
851         case wxRIBBON_ART_PANEL_MINIMISED_BORDER_GRADIENT_COLOUR:
852             return m_panel_minimised_border_gradient_pen.GetColour();
853         case wxRIBBON_ART_PANEL_LABEL_BACKGROUND_COLOUR:
854         case wxRIBBON_ART_PANEL_LABEL_BACKGROUND_GRADIENT_COLOUR:
855             return m_panel_label_background_brush.GetColour();
856         case wxRIBBON_ART_PANEL_LABEL_COLOUR:
857             return m_panel_label_colour;
858         case wxRIBBON_ART_PANEL_MINIMISED_LABEL_COLOUR:
859             return m_panel_minimised_label_colour;
860         case wxRIBBON_ART_PANEL_HOVER_LABEL_BACKGROUND_COLOUR:
861         case wxRIBBON_ART_PANEL_HOVER_LABEL_BACKGROUND_GRADIENT_COLOUR:
862             return m_panel_hover_label_background_brush.GetColour();
863         case wxRIBBON_ART_PANEL_HOVER_LABEL_COLOUR:
864             return m_panel_hover_label_colour;
865         case wxRIBBON_ART_PANEL_ACTIVE_BACKGROUND_TOP_COLOUR:
866             return m_panel_active_background_top_colour;
867         case wxRIBBON_ART_PANEL_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR:
868             return m_panel_active_background_top_gradient_colour;
869         case wxRIBBON_ART_PANEL_ACTIVE_BACKGROUND_COLOUR:
870             return m_panel_active_background_colour;
871         case wxRIBBON_ART_PANEL_ACTIVE_BACKGROUND_GRADIENT_COLOUR:
872             return m_panel_active_background_gradient_colour;
873         case wxRIBBON_ART_PANEL_BUTTON_FACE_COLOUR:
874             return m_panel_button_face_colour;
875         case wxRIBBON_ART_PANEL_BUTTON_HOVER_FACE_COLOUR:
876             return m_panel_button_hover_face_colour;
877         case wxRIBBON_ART_PAGE_BORDER_COLOUR:
878             return m_page_border_pen.GetColour();
879         case wxRIBBON_ART_PAGE_BACKGROUND_TOP_COLOUR:
880             return m_page_background_top_colour;
881         case wxRIBBON_ART_PAGE_BACKGROUND_TOP_GRADIENT_COLOUR:
882             return m_page_background_top_gradient_colour;
883         case wxRIBBON_ART_PAGE_BACKGROUND_COLOUR:
884             return m_page_background_colour;
885         case wxRIBBON_ART_PAGE_BACKGROUND_GRADIENT_COLOUR:
886             return m_page_background_gradient_colour;
887         case wxRIBBON_ART_PAGE_HOVER_BACKGROUND_TOP_COLOUR:
888             return m_page_hover_background_top_colour;
889         case wxRIBBON_ART_PAGE_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR:
890             return m_page_hover_background_top_gradient_colour;
891         case wxRIBBON_ART_PAGE_HOVER_BACKGROUND_COLOUR:
892             return m_page_hover_background_colour;
893         case wxRIBBON_ART_PAGE_HOVER_BACKGROUND_GRADIENT_COLOUR:
894             return m_page_hover_background_gradient_colour;
895         case wxRIBBON_ART_TOOLBAR_BORDER_COLOUR:
896         case wxRIBBON_ART_TOOLBAR_HOVER_BORDER_COLOUR:
897             return m_toolbar_border_pen.GetColour();
898         case wxRIBBON_ART_TOOLBAR_FACE_COLOUR:
899             return m_tool_face_colour;
900         case wxRIBBON_ART_PAGE_TOGGLE_FACE_COLOUR:
901             return m_page_toggle_face_colour;
902         case wxRIBBON_ART_PAGE_TOGGLE_HOVER_FACE_COLOUR:
903             return m_page_toggle_hover_face_colour;
904         default:
905             wxFAIL_MSG(wxT("Invalid Metric Ordinal"));
906             break;
907     }
908 
909     return wxColour();
910 }
911 
SetColour(int id,const wxColor & colour)912 void wxRibbonMSWArtProvider::SetColour(int id, const wxColor& colour)
913 {
914     switch(id)
915     {
916         case wxRIBBON_ART_BUTTON_BAR_LABEL_COLOUR:
917             m_button_bar_label_colour = colour;
918             break;
919         case wxRIBBON_ART_BUTTON_BAR_LABEL_DISABLED_COLOUR:
920             m_button_bar_label_disabled_colour = colour;
921             break;
922         case wxRIBBON_ART_BUTTON_BAR_HOVER_BORDER_COLOUR:
923             m_button_bar_hover_border_pen.SetColour(colour);
924             break;
925         case wxRIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_TOP_COLOUR:
926             m_button_bar_hover_background_top_colour = colour;
927             break;
928         case wxRIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR:
929             m_button_bar_hover_background_top_gradient_colour = colour;
930             break;
931         case wxRIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_COLOUR:
932             m_button_bar_hover_background_colour = colour;
933             break;
934         case wxRIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_GRADIENT_COLOUR:
935             m_button_bar_hover_background_gradient_colour = colour;
936             break;
937         case wxRIBBON_ART_BUTTON_BAR_ACTIVE_BORDER_COLOUR:
938             m_button_bar_active_border_pen.SetColour(colour);
939             break;
940         case wxRIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_TOP_COLOUR:
941             m_button_bar_active_background_top_colour = colour;
942             break;
943         case wxRIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR:
944             m_button_bar_active_background_top_gradient_colour = colour;
945             break;
946         case wxRIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_COLOUR:
947             m_button_bar_active_background_colour = colour;
948             break;
949         case wxRIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_GRADIENT_COLOUR:
950             m_button_bar_active_background_gradient_colour = colour;
951             break;
952         case wxRIBBON_ART_GALLERY_BORDER_COLOUR:
953             m_gallery_border_pen.SetColour(colour);
954             break;
955         case wxRIBBON_ART_GALLERY_HOVER_BACKGROUND_COLOUR:
956             m_gallery_hover_background_brush.SetColour(colour);
957             break;
958         case wxRIBBON_ART_GALLERY_BUTTON_BACKGROUND_COLOUR:
959             m_gallery_button_background_colour = colour;
960             break;
961         case wxRIBBON_ART_GALLERY_BUTTON_BACKGROUND_GRADIENT_COLOUR:
962             m_gallery_button_background_gradient_colour = colour;
963             break;
964         case wxRIBBON_ART_GALLERY_BUTTON_BACKGROUND_TOP_COLOUR:
965             m_gallery_button_background_top_brush.SetColour(colour);
966             break;
967         case wxRIBBON_ART_GALLERY_BUTTON_FACE_COLOUR:
968             m_gallery_button_face_colour = colour;
969             if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
970             {
971                 m_gallery_up_bitmap[0] = wxRibbonLoadPixmap(gallery_left_xpm, colour);
972                 m_gallery_down_bitmap[0] = wxRibbonLoadPixmap(gallery_right_xpm, colour);
973             }
974             else
975             {
976                 m_gallery_up_bitmap[0] = wxRibbonLoadPixmap(gallery_up_xpm, colour);
977                 m_gallery_down_bitmap[0] = wxRibbonLoadPixmap(gallery_down_xpm, colour);
978             }
979             m_gallery_extension_bitmap[0] = wxRibbonLoadPixmap(gallery_extension_xpm, colour);
980             break;
981         case wxRIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_COLOUR:
982             m_gallery_button_hover_background_colour = colour;
983             break;
984         case wxRIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_GRADIENT_COLOUR:
985             m_gallery_button_hover_background_gradient_colour = colour;
986             break;
987         case wxRIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_TOP_COLOUR:
988             m_gallery_button_hover_background_top_brush.SetColour(colour);
989             break;
990         case wxRIBBON_ART_GALLERY_BUTTON_HOVER_FACE_COLOUR:
991             m_gallery_button_hover_face_colour = colour;
992             if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
993             {
994                 m_gallery_up_bitmap[1] = wxRibbonLoadPixmap(gallery_left_xpm, colour);
995                 m_gallery_down_bitmap[1] = wxRibbonLoadPixmap(gallery_right_xpm, colour);
996             }
997             else
998             {
999                 m_gallery_up_bitmap[1] = wxRibbonLoadPixmap(gallery_up_xpm, colour);
1000                 m_gallery_down_bitmap[1] = wxRibbonLoadPixmap(gallery_down_xpm, colour);
1001             }
1002             m_gallery_extension_bitmap[1] = wxRibbonLoadPixmap(gallery_extension_xpm, colour);
1003             break;
1004         case wxRIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_COLOUR:
1005             m_gallery_button_active_background_colour = colour;
1006             break;
1007         case wxRIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_GRADIENT_COLOUR:
1008             m_gallery_button_active_background_gradient_colour = colour;
1009             break;
1010         case wxRIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_TOP_COLOUR:
1011             m_gallery_button_background_top_brush.SetColour(colour);
1012             break;
1013         case wxRIBBON_ART_GALLERY_BUTTON_ACTIVE_FACE_COLOUR:
1014             m_gallery_button_active_face_colour = colour;
1015             if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
1016             {
1017                 m_gallery_up_bitmap[2] = wxRibbonLoadPixmap(gallery_left_xpm, colour);
1018                 m_gallery_down_bitmap[2] = wxRibbonLoadPixmap(gallery_right_xpm, colour);
1019             }
1020             else
1021             {
1022                 m_gallery_up_bitmap[2] = wxRibbonLoadPixmap(gallery_up_xpm, colour);
1023                 m_gallery_down_bitmap[2] = wxRibbonLoadPixmap(gallery_down_xpm, colour);
1024             }
1025             m_gallery_extension_bitmap[2] = wxRibbonLoadPixmap(gallery_extension_xpm, colour);
1026             break;
1027         case wxRIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_COLOUR:
1028             m_gallery_button_disabled_background_colour = colour;
1029             break;
1030         case wxRIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_GRADIENT_COLOUR:
1031             m_gallery_button_disabled_background_gradient_colour = colour;
1032             break;
1033         case wxRIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_TOP_COLOUR:
1034             m_gallery_button_disabled_background_top_brush.SetColour(colour);
1035             break;
1036         case wxRIBBON_ART_GALLERY_BUTTON_DISABLED_FACE_COLOUR:
1037             m_gallery_button_disabled_face_colour = colour;
1038             if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
1039             {
1040                 m_gallery_up_bitmap[3] = wxRibbonLoadPixmap(gallery_left_xpm, colour);
1041                 m_gallery_down_bitmap[3] = wxRibbonLoadPixmap(gallery_right_xpm, colour);
1042             }
1043             else
1044             {
1045                 m_gallery_up_bitmap[3] = wxRibbonLoadPixmap(gallery_up_xpm, colour);
1046                 m_gallery_down_bitmap[3] = wxRibbonLoadPixmap(gallery_down_xpm, colour);
1047             }
1048             m_gallery_extension_bitmap[3] = wxRibbonLoadPixmap(gallery_extension_xpm, colour);
1049             break;
1050         case wxRIBBON_ART_GALLERY_ITEM_BORDER_COLOUR:
1051             m_gallery_item_border_pen.SetColour(colour);
1052             break;
1053         case wxRIBBON_ART_TAB_CTRL_BACKGROUND_COLOUR:
1054         case wxRIBBON_ART_TAB_CTRL_BACKGROUND_GRADIENT_COLOUR:
1055             m_tab_ctrl_background_brush.SetColour(colour);
1056             m_cached_tab_separator_visibility = -1.0;
1057             break;
1058         case wxRIBBON_ART_TAB_LABEL_COLOUR:
1059             m_tab_label_colour = colour;
1060             break;
1061         case wxRIBBON_ART_TAB_SEPARATOR_COLOUR:
1062             m_tab_separator_colour = colour;
1063             m_cached_tab_separator_visibility = -1.0;
1064             break;
1065         case wxRIBBON_ART_TAB_SEPARATOR_GRADIENT_COLOUR:
1066             m_tab_separator_gradient_colour = colour;
1067             m_cached_tab_separator_visibility = -1.0;
1068             break;
1069         case wxRIBBON_ART_TAB_ACTIVE_BACKGROUND_TOP_COLOUR:
1070         case wxRIBBON_ART_TAB_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR:
1071             break;
1072         case wxRIBBON_ART_TAB_ACTIVE_BACKGROUND_COLOUR:
1073             m_tab_active_background_colour = colour;
1074             break;
1075         case wxRIBBON_ART_TAB_ACTIVE_BACKGROUND_GRADIENT_COLOUR:
1076             m_tab_active_background_gradient_colour = colour;
1077             break;
1078         case wxRIBBON_ART_TAB_HOVER_BACKGROUND_TOP_COLOUR:
1079             m_tab_hover_background_top_colour = colour;
1080             break;
1081         case wxRIBBON_ART_TAB_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR:
1082             m_tab_hover_background_top_gradient_colour = colour;
1083             break;
1084         case wxRIBBON_ART_TAB_HOVER_BACKGROUND_COLOUR:
1085             m_tab_hover_background_colour = colour;
1086             break;
1087         case wxRIBBON_ART_TAB_HOVER_BACKGROUND_GRADIENT_COLOUR:
1088             m_tab_hover_background_gradient_colour = colour;
1089             break;
1090         case wxRIBBON_ART_TAB_BORDER_COLOUR:
1091             m_tab_border_pen.SetColour(colour);
1092             break;
1093         case wxRIBBON_ART_PANEL_BORDER_COLOUR:
1094             m_panel_border_pen.SetColour(colour);
1095             break;
1096         case wxRIBBON_ART_PANEL_BORDER_GRADIENT_COLOUR:
1097             m_panel_border_gradient_pen.SetColour(colour);
1098             break;
1099         case wxRIBBON_ART_PANEL_MINIMISED_BORDER_COLOUR:
1100             m_panel_minimised_border_pen.SetColour(colour);
1101             break;
1102         case wxRIBBON_ART_PANEL_MINIMISED_BORDER_GRADIENT_COLOUR:
1103             m_panel_minimised_border_gradient_pen.SetColour(colour);
1104             break;
1105         case wxRIBBON_ART_PANEL_LABEL_BACKGROUND_COLOUR:
1106         case wxRIBBON_ART_PANEL_LABEL_BACKGROUND_GRADIENT_COLOUR:
1107             m_panel_label_background_brush.SetColour(colour);
1108             break;
1109         case wxRIBBON_ART_PANEL_LABEL_COLOUR:
1110             m_panel_label_colour = colour;
1111             break;
1112         case wxRIBBON_ART_PANEL_HOVER_LABEL_BACKGROUND_COLOUR:
1113         case wxRIBBON_ART_PANEL_HOVER_LABEL_BACKGROUND_GRADIENT_COLOUR:
1114             m_panel_hover_label_background_brush.SetColour(colour);
1115             break;
1116         case wxRIBBON_ART_PANEL_HOVER_LABEL_COLOUR:
1117             m_panel_hover_label_colour = colour;
1118             break;
1119         case wxRIBBON_ART_PANEL_MINIMISED_LABEL_COLOUR:
1120             m_panel_minimised_label_colour = colour;
1121             break;
1122         case wxRIBBON_ART_PANEL_ACTIVE_BACKGROUND_TOP_COLOUR:
1123             m_panel_active_background_top_colour = colour;
1124             break;
1125         case wxRIBBON_ART_PANEL_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR:
1126             m_panel_active_background_top_gradient_colour = colour;
1127             break;
1128         case wxRIBBON_ART_PANEL_ACTIVE_BACKGROUND_COLOUR:
1129             m_panel_active_background_colour = colour;
1130             break;
1131         case wxRIBBON_ART_PANEL_ACTIVE_BACKGROUND_GRADIENT_COLOUR:
1132             m_panel_active_background_gradient_colour = colour;
1133             break;
1134         case wxRIBBON_ART_PANEL_BUTTON_FACE_COLOUR:
1135             m_panel_button_face_colour = colour;
1136             m_panel_extension_bitmap[0] = wxRibbonLoadPixmap(panel_extension_xpm, colour);
1137             break;
1138         case wxRIBBON_ART_PANEL_BUTTON_HOVER_FACE_COLOUR:
1139             m_panel_button_hover_face_colour = colour;
1140             m_panel_extension_bitmap[1] = wxRibbonLoadPixmap(panel_extension_xpm, colour);
1141             break;
1142         case wxRIBBON_ART_PAGE_BORDER_COLOUR:
1143             m_page_border_pen.SetColour(colour);
1144             break;
1145         case wxRIBBON_ART_PAGE_BACKGROUND_TOP_COLOUR:
1146             m_page_background_top_colour = colour;
1147             break;
1148         case wxRIBBON_ART_PAGE_BACKGROUND_TOP_GRADIENT_COLOUR:
1149             m_page_background_top_gradient_colour = colour;
1150             break;
1151         case wxRIBBON_ART_PAGE_BACKGROUND_COLOUR:
1152             m_page_background_colour = colour;
1153             break;
1154         case wxRIBBON_ART_PAGE_BACKGROUND_GRADIENT_COLOUR:
1155             m_page_background_gradient_colour = colour;
1156             break;
1157         case wxRIBBON_ART_PAGE_HOVER_BACKGROUND_TOP_COLOUR:
1158             m_page_hover_background_top_colour = colour;
1159             break;
1160         case wxRIBBON_ART_PAGE_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR:
1161             m_page_hover_background_top_gradient_colour = colour;
1162             break;
1163         case wxRIBBON_ART_PAGE_HOVER_BACKGROUND_COLOUR:
1164             m_page_hover_background_colour = colour;
1165             break;
1166         case wxRIBBON_ART_PAGE_HOVER_BACKGROUND_GRADIENT_COLOUR:
1167             m_page_hover_background_gradient_colour = colour;
1168             break;
1169         case wxRIBBON_ART_TOOLBAR_BORDER_COLOUR:
1170         case wxRIBBON_ART_TOOLBAR_HOVER_BORDER_COLOUR:
1171             m_toolbar_border_pen.SetColour(colour);
1172             break;
1173         case wxRIBBON_ART_TOOLBAR_FACE_COLOUR:
1174             m_tool_face_colour = colour;
1175             m_toolbar_drop_bitmap = wxRibbonLoadPixmap(gallery_down_xpm, colour);
1176             break;
1177         case wxRIBBON_ART_PAGE_TOGGLE_FACE_COLOUR:
1178             m_page_toggle_face_colour = colour;
1179             m_ribbon_toggle_down_bitmap[0] = wxRibbonLoadPixmap(panel_toggle_down_xpm, colour);
1180             m_ribbon_toggle_up_bitmap[0] = wxRibbonLoadPixmap(panel_toggle_up_xpm, colour);
1181             m_ribbon_toggle_pin_bitmap[0] = wxRibbonLoadPixmap(ribbon_toggle_pin_xpm, colour);
1182             m_ribbon_bar_help_button_bitmap[0] = wxRibbonLoadPixmap(ribbon_help_button_xpm, colour);
1183             break;
1184         case wxRIBBON_ART_PAGE_TOGGLE_HOVER_FACE_COLOUR:
1185             m_page_toggle_hover_face_colour = colour;
1186             m_ribbon_toggle_down_bitmap[1] = wxRibbonLoadPixmap(panel_toggle_down_xpm, colour);
1187             m_ribbon_toggle_up_bitmap[1] = wxRibbonLoadPixmap(panel_toggle_up_xpm, colour);
1188             m_ribbon_toggle_pin_bitmap[1] = wxRibbonLoadPixmap(ribbon_toggle_pin_xpm, colour);
1189             m_ribbon_bar_help_button_bitmap[1] = wxRibbonLoadPixmap(ribbon_help_button_xpm, colour);
1190             break;
1191         default:
1192             wxFAIL_MSG(wxT("Invalid Metric Ordinal"));
1193             break;
1194     }
1195 }
1196 
DrawTabCtrlBackground(wxDC & dc,wxWindow * WXUNUSED (wnd),const wxRect & rect)1197 void wxRibbonMSWArtProvider::DrawTabCtrlBackground(
1198                         wxDC& dc,
1199                         wxWindow* WXUNUSED(wnd),
1200                         const wxRect& rect)
1201 {
1202     dc.SetPen(*wxTRANSPARENT_PEN);
1203     dc.SetBrush(m_tab_ctrl_background_brush);
1204     dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
1205 
1206     dc.SetPen(m_page_border_pen);
1207     if(rect.width > 6)
1208     {
1209         dc.DrawLine(rect.x + 3, rect.y + rect.height - 1, rect.x + rect.width - 3, rect.y + rect.height - 1);
1210     }
1211     else
1212     {
1213         dc.DrawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width, rect.y + rect.height - 1);
1214     }
1215 }
1216 
DrawTab(wxDC & dc,wxWindow * WXUNUSED (wnd),const wxRibbonPageTabInfo & tab)1217 void wxRibbonMSWArtProvider::DrawTab(
1218                  wxDC& dc,
1219                  wxWindow* WXUNUSED(wnd),
1220                  const wxRibbonPageTabInfo& tab)
1221 {
1222     if(tab.rect.height <= 2)
1223         return;
1224 
1225     if(tab.active || tab.hovered || tab.highlight)
1226     {
1227         if(tab.active)
1228         {
1229             wxRect background(tab.rect);
1230 
1231             background.x += 2;
1232             background.y += 2;
1233             background.width -= 4;
1234             background.height -= 2;
1235 
1236             dc.GradientFillLinear(background, m_tab_active_background_colour,
1237                 m_tab_active_background_gradient_colour, wxSOUTH);
1238 
1239             // TODO: active and hovered
1240         }
1241         else if(tab.hovered)
1242         {
1243             wxRect background(tab.rect);
1244 
1245             background.x += 2;
1246             background.y += 2;
1247             background.width -= 4;
1248             background.height -= 3;
1249             int h = background.height;
1250             background.height /= 2;
1251             dc.GradientFillLinear(background,
1252                 m_tab_hover_background_top_colour,
1253                 m_tab_hover_background_top_gradient_colour, wxSOUTH);
1254 
1255             background.y += background.height;
1256             background.height = h - background.height;
1257             dc.GradientFillLinear(background, m_tab_hover_background_colour,
1258                 m_tab_hover_background_gradient_colour, wxSOUTH);
1259         }
1260         else if(tab.highlight)
1261         {
1262             wxRect background(tab.rect);
1263 
1264             background.x += 2;
1265             background.y += 2;
1266             background.width -= 4;
1267             background.height -= 3;
1268             int h = background.height;
1269             background.height /= 2;
1270 
1271             //For highlight pages we show a colour between the active page and for a hovered page:
1272             wxColour top_colour1((m_tab_active_background_colour.Red()   + m_tab_hover_background_top_colour.Red())/2,
1273                                  (m_tab_active_background_colour.Green() + m_tab_hover_background_top_colour.Green())/2,
1274                                  (m_tab_active_background_colour.Blue()  + m_tab_hover_background_top_colour.Blue())/2);
1275 
1276             wxColour bottom_colour1((m_tab_active_background_gradient_colour.Red()   + m_tab_hover_background_top_gradient_colour.Red())/2,
1277                                     (m_tab_active_background_gradient_colour.Green() + m_tab_hover_background_top_gradient_colour.Green())/2,
1278                                     (m_tab_active_background_gradient_colour.Blue()  + m_tab_hover_background_top_gradient_colour.Blue())/2);
1279 
1280             dc.GradientFillLinear(background, top_colour1, bottom_colour1, wxSOUTH);
1281 
1282             background.y += background.height;
1283             background.height = h - background.height;
1284 
1285             wxColour top_colour2((m_tab_active_background_colour.Red()   + m_tab_hover_background_colour.Red())/2,
1286                                  (m_tab_active_background_colour.Green() + m_tab_hover_background_colour.Green())/2,
1287                                  (m_tab_active_background_colour.Blue()  + m_tab_hover_background_colour.Blue())/2);
1288 
1289             wxColour bottom_colour2((m_tab_active_background_gradient_colour.Red()   + m_tab_hover_background_gradient_colour.Red())/2,
1290                                     (m_tab_active_background_gradient_colour.Green() + m_tab_hover_background_gradient_colour.Green())/2,
1291                                     (m_tab_active_background_gradient_colour.Blue()  + m_tab_hover_background_gradient_colour.Blue())/2);
1292 
1293             dc.GradientFillLinear(background, top_colour2, bottom_colour2, wxSOUTH);
1294         }
1295 
1296         wxPoint border_points[6];
1297         border_points[0] = wxPoint(1, tab.rect.height - 2);
1298         border_points[1] = wxPoint(1, 3);
1299         border_points[2] = wxPoint(3, 1);
1300         border_points[3] = wxPoint(tab.rect.width - 4, 1);
1301         border_points[4] = wxPoint(tab.rect.width - 2, 3);
1302         border_points[5] = wxPoint(tab.rect.width - 2, tab.rect.height - 1);
1303 
1304         dc.SetPen(m_tab_border_pen);
1305         dc.DrawLines(sizeof(border_points)/sizeof(wxPoint), border_points, tab.rect.x, tab.rect.y);
1306 
1307         if(tab.active)
1308         {
1309             // Give the tab a curved outward border at the bottom
1310             dc.DrawPoint(tab.rect.x, tab.rect.y + tab.rect.height - 2);
1311             dc.DrawPoint(tab.rect.x + tab.rect.width - 1, tab.rect.y + tab.rect.height - 2);
1312 
1313             wxPen p(m_tab_active_background_gradient_colour);
1314             dc.SetPen(p);
1315 
1316             // Technically the first two points are the wrong colour, but they're near enough
1317             dc.DrawPoint(tab.rect.x + 1, tab.rect.y + tab.rect.height - 2);
1318             dc.DrawPoint(tab.rect.x + tab.rect.width - 2, tab.rect.y + tab.rect.height - 2);
1319             dc.DrawPoint(tab.rect.x + 1, tab.rect.y + tab.rect.height - 1);
1320             dc.DrawPoint(tab.rect.x, tab.rect.y + tab.rect.height - 1);
1321             dc.DrawPoint(tab.rect.x + tab.rect.width - 2, tab.rect.y + tab.rect.height - 1);
1322             dc.DrawPoint(tab.rect.x + tab.rect.width - 1, tab.rect.y + tab.rect.height - 1);
1323         }
1324     }
1325 
1326     if(m_flags & wxRIBBON_BAR_SHOW_PAGE_ICONS)
1327     {
1328         wxBitmap icon = tab.page->GetIcon();
1329         if(icon.IsOk())
1330         {
1331         int x = tab.rect.x + 4;
1332         if((m_flags & wxRIBBON_BAR_SHOW_PAGE_LABELS) == 0)
1333             x = tab.rect.x + (tab.rect.width - icon.GetWidth()) / 2;
1334         dc.DrawBitmap(icon, x, tab.rect.y + 1 + (tab.rect.height - 1 -
1335             icon.GetHeight()) / 2, true);
1336         }
1337     }
1338     if(m_flags & wxRIBBON_BAR_SHOW_PAGE_LABELS)
1339     {
1340         wxString label = tab.page->GetLabel();
1341         if(!label.IsEmpty())
1342         {
1343             dc.SetFont(m_tab_label_font);
1344             dc.SetTextForeground(m_tab_label_colour);
1345             dc.SetBackgroundMode(wxTRANSPARENT);
1346 
1347             int text_height;
1348             int text_width;
1349             dc.GetTextExtent(label, &text_width, &text_height);
1350             int width = tab.rect.width - 5;
1351             int x = tab.rect.x + 3;
1352             if(m_flags & wxRIBBON_BAR_SHOW_PAGE_ICONS)
1353             {
1354                 x += 3 + tab.page->GetIcon().GetWidth();
1355                 width -= 3 + tab.page->GetIcon().GetWidth();
1356             }
1357             int y = tab.rect.y + (tab.rect.height - text_height) / 2;
1358 
1359             if(width <= text_width)
1360             {
1361                 dc.SetClippingRegion(x, tab.rect.y, width, tab.rect.height);
1362                 dc.DrawText(label, x, y);
1363             }
1364             else
1365             {
1366                 dc.DrawText(label, x + (width - text_width) / 2 + 1, y);
1367             }
1368         }
1369     }
1370 }
1371 
DrawTabSeparator(wxDC & dc,wxWindow * wnd,const wxRect & rect,double visibility)1372 void wxRibbonMSWArtProvider::DrawTabSeparator(
1373                         wxDC& dc,
1374                         wxWindow* wnd,
1375                         const wxRect& rect,
1376                         double visibility)
1377 {
1378     if(visibility <= 0.0)
1379     {
1380         return;
1381     }
1382     if(visibility > 1.0)
1383     {
1384         visibility = 1.0;
1385     }
1386 
1387     // The tab separator is relatively expensive to draw (for its size), and is
1388     // usually drawn multiple times sequentially (in different positions), so it
1389     // makes sense to draw it once and cache it.
1390     if(!m_cached_tab_separator.IsOk() || m_cached_tab_separator.GetSize() != rect.GetSize() || visibility != m_cached_tab_separator_visibility)
1391     {
1392         wxRect size(rect.GetSize());
1393         ReallyDrawTabSeparator(wnd, size, visibility);
1394     }
1395     dc.DrawBitmap(m_cached_tab_separator, rect.x, rect.y, false);
1396 }
1397 
ReallyDrawTabSeparator(wxWindow * wnd,const wxRect & rect,double visibility)1398 void wxRibbonMSWArtProvider::ReallyDrawTabSeparator(wxWindow* wnd, const wxRect& rect, double visibility)
1399 {
1400     if(!m_cached_tab_separator.IsOk() || m_cached_tab_separator.GetSize() != rect.GetSize())
1401     {
1402         m_cached_tab_separator = wxBitmap(rect.GetSize());
1403     }
1404 
1405     wxMemoryDC dc(m_cached_tab_separator);
1406     DrawTabCtrlBackground(dc, wnd, rect);
1407 
1408     wxCoord x = rect.x + rect.width / 2;
1409     double h = (double)(rect.height - 1);
1410 
1411     double r1 = m_tab_ctrl_background_brush.GetColour().Red() * (1.0 - visibility) + 0.5;
1412     double g1 = m_tab_ctrl_background_brush.GetColour().Green() * (1.0 - visibility) + 0.5;
1413     double b1 = m_tab_ctrl_background_brush.GetColour().Blue() * (1.0 - visibility) + 0.5;
1414     double r2 = m_tab_separator_colour.Red();
1415     double g2 = m_tab_separator_colour.Green();
1416     double b2 = m_tab_separator_colour.Blue();
1417     double r3 = m_tab_separator_gradient_colour.Red();
1418     double g3 = m_tab_separator_gradient_colour.Green();
1419     double b3 = m_tab_separator_gradient_colour.Blue();
1420 
1421     for(int i = 0; i < rect.height - 1; ++i)
1422     {
1423         double p = ((double)i)/h;
1424 
1425         double r = (p * r3 + (1.0 - p) * r2) * visibility + r1;
1426         double g = (p * g3 + (1.0 - p) * g2) * visibility + g1;
1427         double b = (p * b3 + (1.0 - p) * b2) * visibility + b1;
1428 
1429         wxPen P(wxColour((unsigned char)r, (unsigned char)g, (unsigned char)b));
1430         dc.SetPen(P);
1431         dc.DrawPoint(x, rect.y + i);
1432     }
1433 
1434     m_cached_tab_separator_visibility = visibility;
1435 }
1436 
DrawPartialPageBackground(wxDC & dc,wxWindow * wnd,const wxRect & r,wxRibbonPage * page,wxPoint offset,bool hovered)1437 void wxRibbonMSWArtProvider::DrawPartialPageBackground(wxDC& dc,
1438         wxWindow* wnd, const wxRect& r, wxRibbonPage* page,
1439         wxPoint offset, bool hovered)
1440 {
1441     wxRect background;
1442     // Expanded panels need a background - the expanded panel at
1443     // best size may have a greater Y dimension higher than when
1444     // on the bar if it has a sizer. AUI art provider does not need this
1445     // because it paints the panel without reference to its parent's size.
1446     // Expanded panels use a wxFrame as parent (not a wxRibbonPage).
1447 
1448     if(wnd->GetSizer() && wnd->GetParent() != page)
1449     {
1450         background = wnd->GetParent()->GetSize();
1451         offset = wxPoint(0,0);
1452     }
1453     else
1454     {
1455         background = page->GetSize();
1456         page->AdjustRectToIncludeScrollButtons(&background);
1457         background.height -= 2;
1458     }
1459     // Page background isn't dependent upon the width of the page
1460     // (at least not the part of it intended to be painted by this
1461     // function). Set to wider than the page itself for when externally
1462     // expanded panels need a background - the expanded panel can be wider
1463     // than the bar.
1464     background.x = 0;
1465     background.width = INT_MAX;
1466 
1467     // upper_rect, lower_rect, paint_rect are all in page co-ordinates
1468     wxRect upper_rect(background);
1469     upper_rect.height /= 5;
1470 
1471     wxRect lower_rect(background);
1472     lower_rect.y += upper_rect.height;
1473     lower_rect.height -= upper_rect.height;
1474 
1475     wxRect paint_rect(r);
1476     paint_rect.x += offset.x;
1477     paint_rect.y += offset.y;
1478 
1479     wxColour bg_top, bg_top_grad, bg_btm, bg_btm_grad;
1480     if(hovered)
1481     {
1482         bg_top = m_page_hover_background_top_colour;
1483         bg_top_grad = m_page_hover_background_top_gradient_colour;
1484         bg_btm = m_page_hover_background_colour;
1485         bg_btm_grad = m_page_hover_background_gradient_colour;
1486     }
1487     else
1488     {
1489         bg_top = m_page_background_top_colour;
1490         bg_top_grad = m_page_background_top_gradient_colour;
1491         bg_btm = m_page_background_colour;
1492         bg_btm_grad = m_page_background_gradient_colour;
1493     }
1494 
1495     if(paint_rect.Intersects(upper_rect))
1496     {
1497         wxRect rect(upper_rect);
1498         rect.Intersect(paint_rect);
1499         rect.x -= offset.x;
1500         rect.y -= offset.y;
1501         wxColour starting_colour(wxRibbonInterpolateColour(bg_top, bg_top_grad,
1502             paint_rect.y, upper_rect.y, upper_rect.y + upper_rect.height));
1503         wxColour ending_colour(wxRibbonInterpolateColour(bg_top, bg_top_grad,
1504             paint_rect.y + paint_rect.height, upper_rect.y,
1505             upper_rect.y + upper_rect.height));
1506         dc.GradientFillLinear(rect, starting_colour, ending_colour, wxSOUTH);
1507     }
1508 
1509     if(paint_rect.Intersects(lower_rect))
1510     {
1511         wxRect rect(lower_rect);
1512         rect.Intersect(paint_rect);
1513         rect.x -= offset.x;
1514         rect.y -= offset.y;
1515         wxColour starting_colour(wxRibbonInterpolateColour(bg_btm, bg_btm_grad,
1516             paint_rect.y, lower_rect.y, lower_rect.y + lower_rect.height));
1517         wxColour ending_colour(wxRibbonInterpolateColour(bg_btm, bg_btm_grad,
1518             paint_rect.y + paint_rect.height,
1519             lower_rect.y, lower_rect.y + lower_rect.height));
1520         dc.GradientFillLinear(rect, starting_colour, ending_colour, wxSOUTH);
1521     }
1522 }
1523 
DrawPageBackground(wxDC & dc,wxWindow * WXUNUSED (wnd),const wxRect & rect)1524 void wxRibbonMSWArtProvider::DrawPageBackground(
1525                         wxDC& dc,
1526                         wxWindow* WXUNUSED(wnd),
1527                         const wxRect& rect)
1528 {
1529     dc.SetPen(*wxTRANSPARENT_PEN);
1530     dc.SetBrush(m_tab_ctrl_background_brush);
1531 
1532     {
1533         wxRect edge(rect);
1534 
1535         edge.width = 2;
1536         dc.DrawRectangle(edge.x, edge.y, edge.width, edge.height);
1537 
1538         edge.x += rect.width - 2;
1539         dc.DrawRectangle(edge.x, edge.y, edge.width, edge.height);
1540 
1541         edge = rect;
1542         edge.height = 2;
1543         edge.y += (rect.height - edge.height);
1544         dc.DrawRectangle(edge.x, edge.y, edge.width, edge.height);
1545     }
1546 
1547     {
1548         wxRect background(rect);
1549         background.x += 2;
1550         background.width -= 4;
1551         background.height -= 2;
1552 
1553         background.height /= 5;
1554         dc.GradientFillLinear(background, m_page_background_top_colour,
1555             m_page_background_top_gradient_colour, wxSOUTH);
1556 
1557         background.y += background.height;
1558         background.height = rect.height - 2 - background.height;
1559         dc.GradientFillLinear(background, m_page_background_colour,
1560             m_page_background_gradient_colour, wxSOUTH);
1561     }
1562 
1563     {
1564         wxPoint border_points[8];
1565         border_points[0] = wxPoint(2, 0);
1566         border_points[1] = wxPoint(1, 1);
1567         border_points[2] = wxPoint(1, rect.height - 4);
1568         border_points[3] = wxPoint(3, rect.height - 2);
1569         border_points[4] = wxPoint(rect.width - 4, rect.height - 2);
1570         border_points[5] = wxPoint(rect.width - 2, rect.height - 4);
1571         border_points[6] = wxPoint(rect.width - 2, 1);
1572         border_points[7] = wxPoint(rect.width - 4, -1);
1573 
1574         dc.SetPen(m_page_border_pen);
1575         dc.DrawLines(sizeof(border_points)/sizeof(wxPoint), border_points, rect.x, rect.y);
1576     }
1577 }
1578 
DrawScrollButton(wxDC & dc,wxWindow * WXUNUSED (wnd),const wxRect & rect_,long style)1579 void wxRibbonMSWArtProvider::DrawScrollButton(
1580                         wxDC& dc,
1581                         wxWindow* WXUNUSED(wnd),
1582                         const wxRect& rect_,
1583                         long style)
1584 {
1585     wxRect rect(rect_);
1586 
1587     if((style & wxRIBBON_SCROLL_BTN_FOR_MASK) == wxRIBBON_SCROLL_BTN_FOR_PAGE)
1588     {
1589         // Page scroll buttons do not have the luxury of rendering on top of anything
1590         // else, and their size includes some padding, hence the background painting
1591         // and size adjustment.
1592         dc.SetPen(*wxTRANSPARENT_PEN);
1593         dc.SetBrush(m_tab_ctrl_background_brush);
1594         dc.DrawRectangle(rect);
1595         dc.SetClippingRegion(rect);
1596         switch(style & wxRIBBON_SCROLL_BTN_DIRECTION_MASK)
1597         {
1598         case wxRIBBON_SCROLL_BTN_LEFT:
1599             rect.x++;
1600         case wxRIBBON_SCROLL_BTN_RIGHT:
1601             rect.y--;
1602             rect.width--;
1603             break;
1604         case wxRIBBON_SCROLL_BTN_UP:
1605             rect.x++;
1606             rect.y--;
1607             rect.width -= 2;
1608             rect.height++;
1609             break;
1610         case wxRIBBON_SCROLL_BTN_DOWN:
1611             rect.x++;
1612             rect.width -= 2;
1613             rect.height--;
1614             break;
1615         }
1616     }
1617 
1618     {
1619         wxRect background(rect);
1620         background.x++;
1621         background.y++;
1622         background.width -= 2;
1623         background.height -= 2;
1624 
1625         if(style & wxRIBBON_SCROLL_BTN_UP)
1626             background.height /= 2;
1627         else
1628             background.height /= 5;
1629         dc.GradientFillLinear(background, m_page_background_top_colour,
1630             m_page_background_top_gradient_colour, wxSOUTH);
1631 
1632         background.y += background.height;
1633         background.height = rect.height - 2 - background.height;
1634         dc.GradientFillLinear(background, m_page_background_colour,
1635             m_page_background_gradient_colour, wxSOUTH);
1636     }
1637 
1638     {
1639         wxPoint border_points[7];
1640         switch(style & wxRIBBON_SCROLL_BTN_DIRECTION_MASK)
1641         {
1642         case wxRIBBON_SCROLL_BTN_LEFT:
1643             border_points[0] = wxPoint(2, 0);
1644             border_points[1] = wxPoint(rect.width - 1, 0);
1645             border_points[2] = wxPoint(rect.width - 1, rect.height - 1);
1646             border_points[3] = wxPoint(2, rect.height - 1);
1647             border_points[4] = wxPoint(0, rect.height - 3);
1648             border_points[5] = wxPoint(0, 2);
1649             break;
1650         case wxRIBBON_SCROLL_BTN_RIGHT:
1651             border_points[0] = wxPoint(0, 0);
1652             border_points[1] = wxPoint(rect.width - 3, 0);
1653             border_points[2] = wxPoint(rect.width - 1, 2);
1654             border_points[3] = wxPoint(rect.width - 1, rect.height - 3);
1655             border_points[4] = wxPoint(rect.width - 3, rect.height - 1);
1656             border_points[5] = wxPoint(0, rect.height - 1);
1657             break;
1658         case wxRIBBON_SCROLL_BTN_UP:
1659             border_points[0] = wxPoint(2, 0);
1660             border_points[1] = wxPoint(rect.width - 3, 0);
1661             border_points[2] = wxPoint(rect.width - 1, 2);
1662             border_points[3] = wxPoint(rect.width - 1, rect.height - 1);
1663             border_points[4] = wxPoint(0, rect.height - 1);
1664             border_points[5] = wxPoint(0, 2);
1665             break;
1666         case wxRIBBON_SCROLL_BTN_DOWN:
1667             border_points[0] = wxPoint(0, 0);
1668             border_points[1] = wxPoint(rect.width - 1, 0);
1669             border_points[2] = wxPoint(rect.width - 1, rect.height - 3);
1670             border_points[3] = wxPoint(rect.width - 3, rect.height - 1);
1671             border_points[4] = wxPoint(2, rect.height - 1);
1672             border_points[5] = wxPoint(0, rect.height - 3);
1673             break;
1674         }
1675         border_points[6] = border_points[0];
1676 
1677         dc.SetPen(m_page_border_pen);
1678         dc.DrawLines(sizeof(border_points)/sizeof(wxPoint), border_points, rect.x, rect.y);
1679     }
1680 
1681     {
1682         // NB: Code for handling hovered/active state is temporary
1683         wxPoint arrow_points[3];
1684         switch(style & wxRIBBON_SCROLL_BTN_DIRECTION_MASK)
1685         {
1686         case wxRIBBON_SCROLL_BTN_LEFT:
1687             arrow_points[0] = wxPoint(rect.width / 2 - 2, rect.height / 2);
1688             if(style & wxRIBBON_SCROLL_BTN_ACTIVE)
1689                 arrow_points[0].y += 1;
1690             arrow_points[1] = arrow_points[0] + wxPoint(3, -3);
1691             arrow_points[2] = arrow_points[0] + wxPoint(3,  3);
1692             break;
1693         case wxRIBBON_SCROLL_BTN_RIGHT:
1694             arrow_points[0] = wxPoint(rect.width / 2 + 2, rect.height / 2);
1695             if(style & wxRIBBON_SCROLL_BTN_ACTIVE)
1696                 arrow_points[0].y += 1;
1697             arrow_points[1] = arrow_points[0] - wxPoint(3,  3);
1698             arrow_points[2] = arrow_points[0] - wxPoint(3, -3);
1699             break;
1700         case wxRIBBON_SCROLL_BTN_UP:
1701             arrow_points[0] = wxPoint(rect.width / 2, rect.height / 2 - 2);
1702             if(style & wxRIBBON_SCROLL_BTN_ACTIVE)
1703                 arrow_points[0].y += 1;
1704             arrow_points[1] = arrow_points[0] + wxPoint( 3, 3);
1705             arrow_points[2] = arrow_points[0] + wxPoint(-3, 3);
1706             break;
1707         case wxRIBBON_SCROLL_BTN_DOWN:
1708             arrow_points[0] = wxPoint(rect.width / 2, rect.height / 2 + 2);
1709             if(style & wxRIBBON_SCROLL_BTN_ACTIVE)
1710                 arrow_points[0].y += 1;
1711             arrow_points[1] = arrow_points[0] - wxPoint( 3, 3);
1712             arrow_points[2] = arrow_points[0] - wxPoint(-3, 3);
1713             break;
1714         }
1715 
1716         dc.SetPen(*wxTRANSPARENT_PEN);
1717         wxBrush B(style & wxRIBBON_SCROLL_BTN_HOVERED ? m_tab_active_background_colour : m_tab_label_colour);
1718         dc.SetBrush(B);
1719         dc.DrawPolygon(sizeof(arrow_points)/sizeof(wxPoint), arrow_points, rect.x, rect.y);
1720     }
1721 }
1722 
DrawDropdownArrow(wxDC & dc,int x,int y,const wxColour & colour)1723 void wxRibbonMSWArtProvider::DrawDropdownArrow(wxDC& dc, int x, int y, const wxColour& colour)
1724 {
1725     wxPoint arrow_points[3];
1726     wxBrush brush(colour);
1727     arrow_points[0] = wxPoint(1, 2);
1728     arrow_points[1] = arrow_points[0] + wxPoint(-3, -3);
1729     arrow_points[2] = arrow_points[0] + wxPoint( 3, -3);
1730     dc.SetPen(*wxTRANSPARENT_PEN);
1731     dc.SetBrush(brush);
1732     dc.DrawPolygon(sizeof(arrow_points)/sizeof(wxPoint), arrow_points, x, y);
1733 }
1734 
RemovePanelPadding(wxRect * rect)1735 void wxRibbonMSWArtProvider::RemovePanelPadding(wxRect* rect)
1736 {
1737     if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
1738     {
1739         rect->y += 1;
1740         rect->height -= 2;
1741     }
1742     else
1743     {
1744         rect->x += 1;
1745         rect->width -= 2;
1746     }
1747 }
1748 
DrawPanelBackground(wxDC & dc,wxRibbonPanel * wnd,const wxRect & rect)1749 void wxRibbonMSWArtProvider::DrawPanelBackground(
1750                         wxDC& dc,
1751                         wxRibbonPanel* wnd,
1752                         const wxRect& rect)
1753 {
1754     DrawPartialPageBackground(dc, wnd, rect, false);
1755 
1756     wxRect true_rect(rect);
1757     RemovePanelPadding(&true_rect);
1758     bool has_ext_button = wnd->HasExtButton();
1759 
1760     int label_height;
1761     {
1762         dc.SetFont(m_panel_label_font);
1763         dc.SetPen(*wxTRANSPARENT_PEN);
1764         if(wnd->IsHovered())
1765         {
1766             dc.SetBrush(m_panel_hover_label_background_brush);
1767             dc.SetTextForeground(m_panel_hover_label_colour);
1768         }
1769         else
1770         {
1771             dc.SetBrush(m_panel_label_background_brush);
1772             dc.SetTextForeground(m_panel_label_colour);
1773         }
1774 
1775         wxRect label_rect(true_rect);
1776         wxString label = wnd->GetLabel();
1777         bool clip_label = false;
1778         wxSize label_size(dc.GetTextExtent(label));
1779 
1780         label_rect.SetX(label_rect.GetX() + 1);
1781         label_rect.SetWidth(label_rect.GetWidth() - 2);
1782         label_rect.SetHeight(label_size.GetHeight() + 2);
1783         label_rect.SetY(true_rect.GetBottom() - label_rect.GetHeight());
1784         label_height = label_rect.GetHeight();
1785 
1786         wxRect label_bg_rect = label_rect;
1787 
1788         if(has_ext_button)
1789             label_rect.SetWidth(label_rect.GetWidth() - 13);
1790 
1791         if(label_size.GetWidth() > label_rect.GetWidth())
1792         {
1793             // Test if there is enough length for 3 letters and ...
1794             wxString new_label = label.Mid(0, 3) + wxT("...");
1795             label_size = dc.GetTextExtent(new_label);
1796             if(label_size.GetWidth() > label_rect.GetWidth())
1797             {
1798                 // Not enough room for three characters and ...
1799                 // Display the entire label and just crop it
1800                 clip_label = true;
1801             }
1802             else
1803             {
1804                 // Room for some characters and ...
1805                 // Display as many characters as possible and append ...
1806                 for(size_t len = label.Len() - 1; len >= 3; --len)
1807                 {
1808                     new_label = label.Mid(0, len) + wxT("...");
1809                     label_size = dc.GetTextExtent(new_label);
1810                     if(label_size.GetWidth() <= label_rect.GetWidth())
1811                     {
1812                         label = new_label;
1813                         break;
1814                     }
1815                 }
1816             }
1817         }
1818 
1819         dc.DrawRectangle(label_bg_rect);
1820         if(clip_label)
1821         {
1822             wxDCClipper clip(dc, label_rect);
1823             dc.DrawText(label, label_rect.x, label_rect.y +
1824                 (label_rect.GetHeight() - label_size.GetHeight()) / 2);
1825         }
1826         else
1827         {
1828             dc.DrawText(label, label_rect.x +
1829                 (label_rect.GetWidth() - label_size.GetWidth()) / 2,
1830                 label_rect.y +
1831                 (label_rect.GetHeight() - label_size.GetHeight()) / 2);
1832         }
1833 
1834         if(has_ext_button)
1835         {
1836             if(wnd->IsExtButtonHovered())
1837             {
1838                 dc.SetPen(m_panel_hover_button_border_pen);
1839                 dc.SetBrush(m_panel_hover_button_background_brush);
1840                 dc.DrawRoundedRectangle(label_rect.GetRight(), label_rect.GetBottom() - 13, 13, 13, 1.0);
1841                 dc.DrawBitmap(m_panel_extension_bitmap[1], label_rect.GetRight() + 3, label_rect.GetBottom() - 10, true);
1842             }
1843             else
1844                 dc.DrawBitmap(m_panel_extension_bitmap[0], label_rect.GetRight() + 3, label_rect.GetBottom() - 10, true);
1845         }
1846     }
1847 
1848     if(wnd->IsHovered())
1849     {
1850         wxRect client_rect(true_rect);
1851         client_rect.x++;
1852         client_rect.width -= 2;
1853         client_rect.y++;
1854         client_rect.height -= 2 + label_height;
1855         DrawPartialPageBackground(dc, wnd, client_rect, true);
1856     }
1857 
1858     DrawPanelBorder(dc, true_rect, m_panel_border_pen, m_panel_border_gradient_pen);
1859 }
1860 
GetPanelExtButtonArea(wxDC & WXUNUSED (dc),const wxRibbonPanel * WXUNUSED (wnd),wxRect rect)1861 wxRect wxRibbonMSWArtProvider::GetPanelExtButtonArea(wxDC& WXUNUSED(dc),
1862                         const wxRibbonPanel* WXUNUSED(wnd),
1863                         wxRect rect)
1864 {
1865     RemovePanelPadding(&rect);
1866     rect = wxRect(rect.GetRight()-13, rect.GetBottom()-13, 13, 13);
1867     return rect;
1868 }
1869 
DrawGalleryBackground(wxDC & dc,wxRibbonGallery * wnd,const wxRect & rect)1870 void wxRibbonMSWArtProvider::DrawGalleryBackground(
1871                         wxDC& dc,
1872                         wxRibbonGallery* wnd,
1873                         const wxRect& rect)
1874 {
1875     DrawPartialPageBackground(dc, wnd, rect);
1876 
1877     if(wnd->IsHovered())
1878     {
1879         dc.SetPen(*wxTRANSPARENT_PEN);
1880         dc.SetBrush(m_gallery_hover_background_brush);
1881         if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
1882         {
1883             dc.DrawRectangle(rect.x + 1, rect.y + 1, rect.width - 2,
1884                 rect.height - 16);
1885         }
1886         else
1887         {
1888             dc.DrawRectangle(rect.x + 1, rect.y + 1, rect.width - 16,
1889                 rect.height - 2);
1890         }
1891     }
1892 
1893     dc.SetPen(m_gallery_border_pen);
1894     // Outline
1895     dc.DrawLine(rect.x + 1, rect.y, rect.x + rect.width - 1, rect.y);
1896     dc.DrawLine(rect.x, rect.y + 1, rect.x, rect.y + rect.height - 1);
1897     dc.DrawLine(rect.x + 1, rect.y + rect.height - 1, rect.x + rect.width - 1,
1898         rect.y + rect.height - 1);
1899     dc.DrawLine(rect.x + rect.width - 1, rect.y + 1, rect.x + rect.width - 1,
1900         rect.y + rect.height - 1);
1901 
1902     DrawGalleryBackgroundCommon(dc, wnd, rect);
1903 }
1904 
DrawGalleryBackgroundCommon(wxDC & dc,wxRibbonGallery * wnd,const wxRect & rect)1905 void wxRibbonMSWArtProvider::DrawGalleryBackgroundCommon(wxDC& dc,
1906                         wxRibbonGallery* wnd,
1907                         const wxRect& rect)
1908 {
1909     wxRect up_btn, down_btn, ext_btn;
1910 
1911     if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
1912     {
1913         // Divider between items and buttons
1914         dc.DrawLine(rect.x, rect.y + rect.height - 15, rect.x + rect.width,
1915             rect.y + rect.height - 15);
1916 
1917         up_btn = wxRect(rect.x, rect.y + rect.height - 15, rect.width / 3, 15);
1918 
1919         down_btn = wxRect(up_btn.GetRight() + 1, up_btn.GetTop(),
1920             up_btn.GetWidth(), up_btn.GetHeight());
1921         dc.DrawLine(down_btn.GetLeft(), down_btn.GetTop(), down_btn.GetLeft(),
1922             down_btn.GetBottom());
1923 
1924         ext_btn = wxRect(down_btn.GetRight() + 1, up_btn.GetTop(), rect.width -
1925             up_btn.GetWidth() - down_btn.GetWidth() - 1, up_btn.GetHeight());
1926         dc.DrawLine(ext_btn.GetLeft(), ext_btn.GetTop(), ext_btn.GetLeft(),
1927             ext_btn.GetBottom());
1928     }
1929     else
1930     {
1931         // Divider between items and buttons
1932         dc.DrawLine(rect.x + rect.width - 15, rect.y, rect.x + rect.width - 15,
1933             rect.y + rect.height);
1934 
1935         up_btn = wxRect(rect.x + rect.width - 15, rect.y, 15, rect.height / 3);
1936 
1937         down_btn = wxRect(up_btn.GetLeft(), up_btn.GetBottom() + 1,
1938             up_btn.GetWidth(), up_btn.GetHeight());
1939         dc.DrawLine(down_btn.GetLeft(), down_btn.GetTop(), down_btn.GetRight(),
1940             down_btn.GetTop());
1941 
1942         ext_btn = wxRect(up_btn.GetLeft(), down_btn.GetBottom() + 1, up_btn.GetWidth(),
1943             rect.height - up_btn.GetHeight() - down_btn.GetHeight() - 1);
1944         dc.DrawLine(ext_btn.GetLeft(), ext_btn.GetTop(), ext_btn.GetRight(),
1945             ext_btn.GetTop());
1946     }
1947 
1948     DrawGalleryButton(dc, up_btn, wnd->GetUpButtonState(),
1949         m_gallery_up_bitmap);
1950     DrawGalleryButton(dc, down_btn, wnd->GetDownButtonState(),
1951         m_gallery_down_bitmap);
1952     DrawGalleryButton(dc, ext_btn, wnd->GetExtensionButtonState(),
1953         m_gallery_extension_bitmap);
1954 }
1955 
DrawGalleryButton(wxDC & dc,wxRect rect,wxRibbonGalleryButtonState state,wxBitmap * bitmaps)1956 void wxRibbonMSWArtProvider::DrawGalleryButton(wxDC& dc,
1957                                             wxRect rect,
1958                                             wxRibbonGalleryButtonState state,
1959                                             wxBitmap* bitmaps)
1960 {
1961     wxBitmap btn_bitmap;
1962     wxBrush btn_top_brush;
1963     wxColour btn_colour;
1964     wxColour btn_grad_colour;
1965     switch(state)
1966     {
1967     case wxRIBBON_GALLERY_BUTTON_NORMAL:
1968         btn_top_brush = m_gallery_button_background_top_brush;
1969         btn_colour = m_gallery_button_background_colour;
1970         btn_grad_colour = m_gallery_button_background_gradient_colour;
1971         btn_bitmap = bitmaps[0];
1972         break;
1973     case wxRIBBON_GALLERY_BUTTON_HOVERED:
1974         btn_top_brush = m_gallery_button_hover_background_top_brush;
1975         btn_colour = m_gallery_button_hover_background_colour;
1976         btn_grad_colour = m_gallery_button_hover_background_gradient_colour;
1977         btn_bitmap = bitmaps[1];
1978         break;
1979     case wxRIBBON_GALLERY_BUTTON_ACTIVE:
1980         btn_top_brush = m_gallery_button_active_background_top_brush;
1981         btn_colour = m_gallery_button_active_background_colour;
1982         btn_grad_colour = m_gallery_button_active_background_gradient_colour;
1983         btn_bitmap = bitmaps[2];
1984         break;
1985     case wxRIBBON_GALLERY_BUTTON_DISABLED:
1986         btn_top_brush = m_gallery_button_disabled_background_top_brush;
1987         btn_colour = m_gallery_button_disabled_background_colour;
1988         btn_grad_colour = m_gallery_button_disabled_background_gradient_colour;
1989         btn_bitmap = bitmaps[3];
1990         break;
1991     }
1992 
1993     rect.x++;
1994     rect.y++;
1995     if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
1996     {
1997         rect.width--;;
1998         rect.height -= 2;
1999     }
2000     else
2001     {
2002         rect.width -= 2;
2003         rect.height--;
2004     }
2005 
2006     dc.SetPen(*wxTRANSPARENT_PEN);
2007     dc.SetBrush(btn_top_brush);
2008     dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height / 2);
2009 
2010     wxRect lower(rect);
2011     lower.height = (lower.height + 1) / 2;
2012     lower.y += rect.height - lower.height;
2013     dc.GradientFillLinear(lower, btn_colour, btn_grad_colour, wxSOUTH);
2014 
2015     dc.DrawBitmap(btn_bitmap, rect.x + rect.width / 2 - 2, lower.y - 2, true);
2016 }
2017 
DrawGalleryItemBackground(wxDC & dc,wxRibbonGallery * wnd,const wxRect & rect,wxRibbonGalleryItem * item)2018 void wxRibbonMSWArtProvider::DrawGalleryItemBackground(
2019                         wxDC& dc,
2020                         wxRibbonGallery* wnd,
2021                         const wxRect& rect,
2022                         wxRibbonGalleryItem* item)
2023 {
2024     if(wnd->GetHoveredItem() != item && wnd->GetActiveItem() != item &&
2025         wnd->GetSelection() != item)
2026         return;
2027 
2028     dc.SetPen(m_gallery_item_border_pen);
2029     dc.DrawLine(rect.x + 1, rect.y, rect.x + rect.width - 1, rect.y);
2030     dc.DrawLine(rect.x, rect.y + 1, rect.x, rect.y + rect.height - 1);
2031     dc.DrawLine(rect.x + 1, rect.y + rect.height - 1, rect.x + rect.width - 1,
2032         rect.y + rect.height - 1);
2033     dc.DrawLine(rect.x + rect.width - 1, rect.y + 1, rect.x + rect.width - 1,
2034         rect.y + rect.height - 1);
2035 
2036     wxBrush top_brush;
2037     wxColour bg_colour;
2038     wxColour bg_gradient_colour;
2039 
2040     if(wnd->GetActiveItem() == item || wnd->GetSelection() == item)
2041     {
2042         top_brush = m_gallery_button_active_background_top_brush;
2043         bg_colour = m_gallery_button_active_background_colour;
2044         bg_gradient_colour = m_gallery_button_active_background_gradient_colour;
2045     }
2046     else
2047     {
2048         top_brush = m_gallery_button_hover_background_top_brush;
2049         bg_colour = m_gallery_button_hover_background_colour;
2050         bg_gradient_colour = m_gallery_button_hover_background_gradient_colour;
2051     }
2052 
2053     wxRect upper(rect);
2054     upper.x += 1;
2055     upper.width -= 2;
2056     upper.y += 1;
2057     upper.height /= 3;
2058     dc.SetPen(*wxTRANSPARENT_PEN);
2059     dc.SetBrush(top_brush);
2060     dc.DrawRectangle(upper.x, upper.y, upper.width, upper.height);
2061 
2062     wxRect lower(upper);
2063     lower.y += lower.height;
2064     lower.height = rect.height - 2 - lower.height;
2065     dc.GradientFillLinear(lower, bg_colour, bg_gradient_colour, wxSOUTH);
2066 }
2067 
DrawPanelBorder(wxDC & dc,const wxRect & rect,wxPen & primary_colour,wxPen & secondary_colour)2068 void wxRibbonMSWArtProvider::DrawPanelBorder(wxDC& dc, const wxRect& rect,
2069                                              wxPen& primary_colour,
2070                                              wxPen& secondary_colour)
2071 {
2072     wxPoint border_points[9];
2073     border_points[0] = wxPoint(2, 0);
2074     border_points[1] = wxPoint(rect.width - 3, 0);
2075     border_points[2] = wxPoint(rect.width - 1, 2);
2076     border_points[3] = wxPoint(rect.width - 1, rect.height - 3);
2077     border_points[4] = wxPoint(rect.width - 3, rect.height - 1);
2078     border_points[5] = wxPoint(2, rect.height - 1);
2079     border_points[6] = wxPoint(0, rect.height - 3);
2080     border_points[7] = wxPoint(0, 2);
2081 
2082     if(primary_colour.GetColour() == secondary_colour.GetColour())
2083     {
2084         border_points[8] = border_points[0];
2085         dc.SetPen(primary_colour);
2086         dc.DrawLines(sizeof(border_points)/sizeof(wxPoint), border_points, rect.x, rect.y);
2087     }
2088     else
2089     {
2090         dc.SetPen(primary_colour);
2091         dc.DrawLines(3, border_points, rect.x, rect.y);
2092 
2093 #define SingleLine(start, finish) \
2094         dc.DrawLine(start.x + rect.x, start.y + rect.y, finish.x + rect.x, finish.y + rect.y)
2095 
2096         SingleLine(border_points[0], border_points[7]);
2097         dc.SetPen(secondary_colour);
2098         dc.DrawLines(3, border_points + 4, rect.x, rect.y);
2099         SingleLine(border_points[4], border_points[3]);
2100 
2101 #undef SingleLine
2102 
2103         border_points[6] = border_points[2];
2104         wxRibbonDrawParallelGradientLines(dc, 2, border_points + 6, 0, 1,
2105             border_points[3].y - border_points[2].y + 1, rect.x, rect.y,
2106             primary_colour.GetColour(), secondary_colour.GetColour());
2107     }
2108 }
2109 
DrawMinimisedPanel(wxDC & dc,wxRibbonPanel * wnd,const wxRect & rect,wxBitmap & bitmap)2110 void wxRibbonMSWArtProvider::DrawMinimisedPanel(
2111                         wxDC& dc,
2112                         wxRibbonPanel* wnd,
2113                         const wxRect& rect,
2114                         wxBitmap& bitmap)
2115 {
2116     DrawPartialPageBackground(dc, wnd, rect, false);
2117 
2118     wxRect true_rect(rect);
2119     RemovePanelPadding(&true_rect);
2120 
2121     if(wnd->GetExpandedPanel() != NULL)
2122     {
2123         wxRect client_rect(true_rect);
2124         client_rect.x++;
2125         client_rect.width -= 2;
2126         client_rect.y++;
2127         client_rect.height = (rect.y + rect.height / 5) - client_rect.x;
2128         dc.GradientFillLinear(client_rect,
2129             m_panel_active_background_top_colour,
2130             m_panel_active_background_top_gradient_colour, wxSOUTH);
2131 
2132         client_rect.y += client_rect.height;
2133         client_rect.height = (true_rect.y + true_rect.height) - client_rect.y;
2134         dc.GradientFillLinear(client_rect,
2135             m_panel_active_background_colour,
2136             m_panel_active_background_gradient_colour, wxSOUTH);
2137     }
2138     else if(wnd->IsHovered())
2139     {
2140         wxRect client_rect(true_rect);
2141         client_rect.x++;
2142         client_rect.width -= 2;
2143         client_rect.y++;
2144         client_rect.height -= 2;
2145         DrawPartialPageBackground(dc, wnd, client_rect, true);
2146     }
2147 
2148     wxRect preview;
2149     DrawMinimisedPanelCommon(dc, wnd, true_rect, &preview);
2150 
2151     dc.SetBrush(m_panel_hover_label_background_brush);
2152     dc.SetPen(*wxTRANSPARENT_PEN);
2153     dc.DrawRectangle(preview.x + 1, preview.y + preview.height - 8,
2154         preview.width - 2, 7);
2155 
2156     int mid_pos = rect.y + rect.height / 5 - preview.y;
2157     if(mid_pos < 0 || mid_pos >= preview.height)
2158     {
2159         wxRect full_rect(preview);
2160         full_rect.x += 1;
2161         full_rect.y += 1;
2162         full_rect.width -= 2;
2163         full_rect.height -= 9;
2164         if(mid_pos < 0)
2165         {
2166             dc.GradientFillLinear(full_rect,
2167                 m_page_hover_background_colour,
2168                 m_page_hover_background_gradient_colour, wxSOUTH);
2169         }
2170         else
2171         {
2172             dc.GradientFillLinear(full_rect,
2173                 m_page_hover_background_top_colour,
2174                 m_page_hover_background_top_gradient_colour, wxSOUTH);
2175         }
2176     }
2177     else
2178     {
2179         wxRect top_rect(preview);
2180         top_rect.x += 1;
2181         top_rect.y += 1;
2182         top_rect.width -= 2;
2183         top_rect.height = mid_pos;
2184         dc.GradientFillLinear(top_rect,
2185             m_page_hover_background_top_colour,
2186             m_page_hover_background_top_gradient_colour, wxSOUTH);
2187 
2188         wxRect btm_rect(top_rect);
2189         btm_rect.y = preview.y + mid_pos;
2190         btm_rect.height = preview.y + preview.height - 7 - btm_rect.y;
2191         dc.GradientFillLinear(btm_rect,
2192             m_page_hover_background_colour,
2193             m_page_hover_background_gradient_colour, wxSOUTH);
2194     }
2195 
2196     if(bitmap.IsOk())
2197     {
2198         dc.DrawBitmap(bitmap, preview.x + (preview.width - bitmap.GetWidth()) / 2,
2199             preview.y + (preview.height - 7 - bitmap.GetHeight()) / 2, true);
2200     }
2201 
2202     DrawPanelBorder(dc, preview, m_panel_border_pen, m_panel_border_gradient_pen);
2203 
2204     DrawPanelBorder(dc, true_rect, m_panel_minimised_border_pen,
2205         m_panel_minimised_border_gradient_pen);
2206 }
2207 
DrawMinimisedPanelCommon(wxDC & dc,wxRibbonPanel * wnd,const wxRect & true_rect,wxRect * preview_rect)2208 void wxRibbonMSWArtProvider::DrawMinimisedPanelCommon(
2209                         wxDC& dc,
2210                         wxRibbonPanel* wnd,
2211                         const wxRect& true_rect,
2212                         wxRect* preview_rect)
2213 {
2214     wxRect preview(0, 0, 32, 32);
2215     if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
2216     {
2217         preview.x = true_rect.x + 4;
2218         preview.y = true_rect.y + (true_rect.height - preview.height) / 2;
2219     }
2220     else
2221     {
2222         preview.x = true_rect.x + (true_rect.width - preview.width) / 2;
2223         preview.y = true_rect.y + 4;
2224     }
2225     if(preview_rect)
2226         *preview_rect = preview;
2227 
2228     wxCoord label_width, label_height;
2229     dc.SetFont(m_panel_label_font);
2230     dc.GetTextExtent(wnd->GetLabel(), &label_width, &label_height);
2231 
2232     int xpos = true_rect.x + (true_rect.width - label_width + 1) / 2;
2233     int ypos = preview.y + preview.height + 5;
2234 
2235     if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
2236     {
2237         xpos = preview.x + preview.width + 5;
2238         ypos = true_rect.y + (true_rect.height - label_height) / 2;
2239     }
2240 
2241     dc.SetTextForeground(m_panel_minimised_label_colour);
2242     dc.DrawText(wnd->GetLabel(), xpos, ypos);
2243 
2244 
2245     wxPoint arrow_points[3];
2246     if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
2247     {
2248         xpos += label_width;
2249         arrow_points[0] = wxPoint(xpos + 5, ypos + label_height / 2);
2250         arrow_points[1] = arrow_points[0] + wxPoint(-3,  3);
2251         arrow_points[2] = arrow_points[0] + wxPoint(-3, -3);
2252     }
2253     else
2254     {
2255         ypos += label_height;
2256         arrow_points[0] = wxPoint(true_rect.width / 2, ypos + 5);
2257         arrow_points[1] = arrow_points[0] + wxPoint(-3, -3);
2258         arrow_points[2] = arrow_points[0] + wxPoint( 3, -3);
2259     }
2260 
2261     dc.SetPen(*wxTRANSPARENT_PEN);
2262     wxBrush B(m_panel_minimised_label_colour);
2263     dc.SetBrush(B);
2264     dc.DrawPolygon(sizeof(arrow_points)/sizeof(wxPoint), arrow_points,
2265         true_rect.x, true_rect.y);
2266 }
2267 
DrawButtonBarBackground(wxDC & dc,wxWindow * wnd,const wxRect & rect)2268 void wxRibbonMSWArtProvider::DrawButtonBarBackground(
2269                         wxDC& dc,
2270                         wxWindow* wnd,
2271                         const wxRect& rect)
2272 {
2273     DrawPartialPageBackground(dc, wnd, rect, true);
2274 }
2275 
DrawPartialPageBackground(wxDC & dc,wxWindow * wnd,const wxRect & rect,bool allow_hovered)2276 void wxRibbonMSWArtProvider::DrawPartialPageBackground(
2277                         wxDC& dc,
2278                         wxWindow* wnd,
2279                         const wxRect& rect,
2280                         bool allow_hovered)
2281 {
2282     // Assume the window is a child of a ribbon page, and also check for a
2283     // hovered panel somewhere between the window and the page, as it causes
2284     // the background to change.
2285     wxPoint offset(wnd->GetPosition());
2286     wxRibbonPage* page = NULL;
2287     wxWindow* parent = wnd->GetParent();
2288     wxRibbonPanel* panel = wxDynamicCast(wnd, wxRibbonPanel);
2289     bool hovered = false;
2290 
2291     if(panel != NULL)
2292     {
2293         hovered = allow_hovered && panel->IsHovered();
2294         if(panel->GetExpandedDummy() != NULL)
2295         {
2296             offset = panel->GetExpandedDummy()->GetPosition();
2297             parent = panel->GetExpandedDummy()->GetParent();
2298         }
2299     }
2300     for(; parent; parent = parent->GetParent())
2301     {
2302         if(panel == NULL)
2303         {
2304             panel = wxDynamicCast(parent, wxRibbonPanel);
2305             if(panel != NULL)
2306             {
2307                 hovered = allow_hovered && panel->IsHovered();
2308                 if(panel->GetExpandedDummy() != NULL)
2309                 {
2310                     parent = panel->GetExpandedDummy();
2311                 }
2312             }
2313         }
2314         page = wxDynamicCast(parent, wxRibbonPage);
2315         if(page != NULL)
2316         {
2317             break;
2318         }
2319         offset += parent->GetPosition();
2320     }
2321     if(page != NULL)
2322     {
2323         DrawPartialPageBackground(dc, wnd, rect, page, offset, hovered);
2324         return;
2325     }
2326 
2327     // No page found - fallback to painting with a stock brush
2328     dc.SetBrush(*wxWHITE_BRUSH);
2329     dc.SetPen(*wxTRANSPARENT_PEN);
2330     dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
2331 }
2332 
DrawButtonBarButton(wxDC & dc,wxWindow * WXUNUSED (wnd),const wxRect & rect,wxRibbonButtonKind kind,long state,const wxString & label,const wxBitmap & bitmap_large,const wxBitmap & bitmap_small)2333 void wxRibbonMSWArtProvider::DrawButtonBarButton(
2334                         wxDC& dc,
2335                         wxWindow* WXUNUSED(wnd),
2336                         const wxRect& rect,
2337                         wxRibbonButtonKind kind,
2338                         long state,
2339                         const wxString& label,
2340                         const wxBitmap& bitmap_large,
2341                         const wxBitmap& bitmap_small)
2342 {
2343     if(kind == wxRIBBON_BUTTON_TOGGLE)
2344     {
2345         kind = wxRIBBON_BUTTON_NORMAL;
2346         if(state & wxRIBBON_BUTTONBAR_BUTTON_TOGGLED)
2347             state ^= wxRIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK;
2348     }
2349 
2350     if(state & (wxRIBBON_BUTTONBAR_BUTTON_HOVER_MASK |
2351         wxRIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK))
2352     {
2353         if(state & wxRIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK)
2354             dc.SetPen(m_button_bar_active_border_pen);
2355         else
2356             dc.SetPen(m_button_bar_hover_border_pen);
2357 
2358         wxRect bg_rect(rect);
2359         bg_rect.x++;
2360         bg_rect.y++;
2361         bg_rect.width -= 2;
2362         bg_rect.height -= 2;
2363 
2364         wxRect bg_rect_top(bg_rect);
2365         bg_rect_top.height /= 3;
2366         bg_rect.y += bg_rect_top.height;
2367         bg_rect.height -= bg_rect_top.height;
2368 
2369         if(kind == wxRIBBON_BUTTON_HYBRID)
2370         {
2371             switch(state & wxRIBBON_BUTTONBAR_BUTTON_SIZE_MASK)
2372             {
2373             case wxRIBBON_BUTTONBAR_BUTTON_LARGE:
2374                 {
2375                     int iYBorder = rect.y + bitmap_large.GetHeight() + 4;
2376                     wxRect partial_bg(rect);
2377                     if(state & wxRIBBON_BUTTONBAR_BUTTON_NORMAL_HOVERED)
2378                     {
2379                         partial_bg.SetBottom(iYBorder - 1);
2380                     }
2381                     else
2382                     {
2383                         partial_bg.height -= (iYBorder - partial_bg.y + 1);
2384                         partial_bg.y = iYBorder + 1;
2385                     }
2386                     dc.DrawLine(rect.x, iYBorder, rect.x + rect.width, iYBorder);
2387                     bg_rect.Intersect(partial_bg);
2388                     bg_rect_top.Intersect(partial_bg);
2389                 }
2390                 break;
2391             case wxRIBBON_BUTTONBAR_BUTTON_MEDIUM:
2392                 {
2393                     int iArrowWidth = 9;
2394                     if(state & wxRIBBON_BUTTONBAR_BUTTON_NORMAL_HOVERED)
2395                     {
2396                         bg_rect.width -= iArrowWidth;
2397                         bg_rect_top.width -= iArrowWidth;
2398                         dc.DrawLine(bg_rect_top.x + bg_rect_top.width,
2399                             rect.y, bg_rect_top.x + bg_rect_top.width,
2400                             rect.y + rect.height);
2401                     }
2402                     else
2403                     {
2404                         --iArrowWidth;
2405                         bg_rect.x += bg_rect.width - iArrowWidth;
2406                         bg_rect_top.x += bg_rect_top.width - iArrowWidth;
2407                         bg_rect.width = iArrowWidth;
2408                         bg_rect_top.width = iArrowWidth;
2409                         dc.DrawLine(bg_rect_top.x - 1, rect.y,
2410                             bg_rect_top.x - 1, rect.y + rect.height);
2411                     }
2412                 }
2413                 break;
2414             case wxRIBBON_BUTTONBAR_BUTTON_SMALL:
2415                 break;
2416             }
2417         }
2418 
2419         if(state & wxRIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK)
2420         {
2421             dc.GradientFillLinear(bg_rect_top,
2422                 m_button_bar_active_background_top_colour,
2423                 m_button_bar_active_background_top_gradient_colour, wxSOUTH);
2424             dc.GradientFillLinear(bg_rect,
2425                 m_button_bar_active_background_colour,
2426                 m_button_bar_active_background_gradient_colour, wxSOUTH);
2427         }
2428         else
2429         {
2430             dc.GradientFillLinear(bg_rect_top,
2431                 m_button_bar_hover_background_top_colour,
2432                 m_button_bar_hover_background_top_gradient_colour, wxSOUTH);
2433             dc.GradientFillLinear(bg_rect,
2434                 m_button_bar_hover_background_colour,
2435                 m_button_bar_hover_background_gradient_colour, wxSOUTH);
2436         }
2437 
2438         wxPoint border_points[9];
2439         border_points[0] = wxPoint(2, 0);
2440         border_points[1] = wxPoint(rect.width - 3, 0);
2441         border_points[2] = wxPoint(rect.width - 1, 2);
2442         border_points[3] = wxPoint(rect.width - 1, rect.height - 3);
2443         border_points[4] = wxPoint(rect.width - 3, rect.height - 1);
2444         border_points[5] = wxPoint(2, rect.height - 1);
2445         border_points[6] = wxPoint(0, rect.height - 3);
2446         border_points[7] = wxPoint(0, 2);
2447         border_points[8] = border_points[0];
2448 
2449         dc.DrawLines(sizeof(border_points)/sizeof(wxPoint), border_points,
2450             rect.x, rect.y);
2451     }
2452 
2453     dc.SetFont(m_button_bar_label_font);
2454     dc.SetTextForeground(state & wxRIBBON_BUTTONBAR_BUTTON_DISABLED
2455                             ? m_button_bar_label_disabled_colour
2456                             : m_button_bar_label_colour);
2457     DrawButtonBarButtonForeground(dc, rect, kind, state, label, bitmap_large,
2458         bitmap_small);
2459 }
2460 
DrawButtonBarButtonForeground(wxDC & dc,const wxRect & rect,wxRibbonButtonKind kind,long state,const wxString & label,const wxBitmap & bitmap_large,const wxBitmap & bitmap_small)2461 void wxRibbonMSWArtProvider::DrawButtonBarButtonForeground(
2462                         wxDC& dc,
2463                         const wxRect& rect,
2464                         wxRibbonButtonKind kind,
2465                         long state,
2466                         const wxString& label,
2467                         const wxBitmap& bitmap_large,
2468                         const wxBitmap& bitmap_small)
2469 {
2470     const wxColour
2471         arrowColour(state & wxRIBBON_BUTTONBAR_BUTTON_DISABLED
2472                         ? m_button_bar_label_disabled_colour
2473                         : m_button_bar_label_colour);
2474 
2475     switch(state & wxRIBBON_BUTTONBAR_BUTTON_SIZE_MASK)
2476     {
2477     case wxRIBBON_BUTTONBAR_BUTTON_LARGE:
2478         {
2479             const int padding = 2;
2480             dc.DrawBitmap(bitmap_large,
2481                 rect.x + (rect.width - bitmap_large.GetWidth()) / 2,
2482                 rect.y + padding, true);
2483             int ypos = rect.y + padding + bitmap_large.GetHeight() + padding;
2484             int arrow_width = kind == wxRIBBON_BUTTON_NORMAL ? 0 : 8;
2485             wxCoord label_w, label_h;
2486             dc.GetTextExtent(label, &label_w, &label_h);
2487             if(label_w + 2 * padding <= rect.width)
2488             {
2489                 dc.DrawText(label, rect.x + (rect.width - label_w) / 2, ypos);
2490                 if(arrow_width != 0)
2491                 {
2492                     DrawDropdownArrow(dc, rect.x + rect.width / 2,
2493                         ypos + (label_h * 3) / 2,
2494                         arrowColour);
2495                 }
2496             }
2497             else
2498             {
2499                 size_t breaki = label.Len();
2500                 do
2501                 {
2502                     --breaki;
2503                     if(wxRibbonCanLabelBreakAtPosition(label, breaki))
2504                     {
2505                         wxString label_top = label.Mid(0, breaki);
2506                         dc.GetTextExtent(label_top, &label_w, &label_h);
2507                         if(label_w + 2 * padding <= rect.width)
2508                         {
2509                             dc.DrawText(label_top,
2510                                 rect.x + (rect.width - label_w) / 2, ypos);
2511                             ypos += label_h;
2512                             wxString label_bottom = label.Mid(breaki + 1);
2513                             dc.GetTextExtent(label_bottom, &label_w, &label_h);
2514                             label_w += arrow_width;
2515                             int iX = rect.x + (rect.width - label_w) / 2;
2516                             dc.DrawText(label_bottom, iX, ypos);
2517                             if(arrow_width != 0)
2518                             {
2519                                 DrawDropdownArrow(dc,
2520                                     iX + 2 +label_w - arrow_width,
2521                                     ypos + label_h / 2 + 1,
2522                                     arrowColour);
2523                             }
2524                             break;
2525                         }
2526                     }
2527                 } while(breaki > 0);
2528             }
2529         }
2530         break;
2531     case wxRIBBON_BUTTONBAR_BUTTON_MEDIUM:
2532         {
2533             int x_cursor = rect.x + 2;
2534             dc.DrawBitmap(bitmap_small, x_cursor,
2535                     rect.y + (rect.height - bitmap_small.GetHeight())/2, true);
2536             x_cursor += bitmap_small.GetWidth() + 2;
2537             wxCoord label_w, label_h;
2538             dc.GetTextExtent(label, &label_w, &label_h);
2539             dc.DrawText(label, x_cursor,
2540                 rect.y + (rect.height - label_h) / 2);
2541             x_cursor += label_w + 3;
2542             if(kind != wxRIBBON_BUTTON_NORMAL)
2543             {
2544                 DrawDropdownArrow(dc, x_cursor, rect.y + rect.height / 2, arrowColour);
2545             }
2546             break;
2547         }
2548     default:
2549         // TODO
2550         break;
2551     }
2552 }
2553 
DrawToolBarBackground(wxDC & dc,wxWindow * wnd,const wxRect & rect)2554 void wxRibbonMSWArtProvider::DrawToolBarBackground(
2555                         wxDC& dc,
2556                         wxWindow* wnd,
2557                         const wxRect& rect)
2558 {
2559     DrawPartialPageBackground(dc, wnd, rect);
2560 }
2561 
DrawToolGroupBackground(wxDC & dc,wxWindow * WXUNUSED (wnd),const wxRect & rect)2562 void wxRibbonMSWArtProvider::DrawToolGroupBackground(
2563                         wxDC& dc,
2564                         wxWindow* WXUNUSED(wnd),
2565                         const wxRect& rect)
2566 {
2567     dc.SetPen(m_toolbar_border_pen);
2568     wxPoint outline[9];
2569     outline[0] = wxPoint(2, 0);
2570     outline[1] = wxPoint(rect.width - 3, 0);
2571     outline[2] = wxPoint(rect.width - 1, 2);
2572     outline[3] = wxPoint(rect.width - 1, rect.height - 3);
2573     outline[4] = wxPoint(rect.width - 3, rect.height - 1);
2574     outline[5] = wxPoint(2, rect.height - 1);
2575     outline[6] = wxPoint(0, rect.height - 3);
2576     outline[7] = wxPoint(0, 2);
2577     outline[8] = outline[0];
2578 
2579     dc.DrawLines(sizeof(outline)/sizeof(wxPoint), outline, rect.x, rect.y);
2580 }
2581 
DrawTool(wxDC & dc,wxWindow * WXUNUSED (wnd),const wxRect & rect,const wxBitmap & bitmap,wxRibbonButtonKind kind,long state)2582 void wxRibbonMSWArtProvider::DrawTool(
2583                 wxDC& dc,
2584                 wxWindow* WXUNUSED(wnd),
2585                 const wxRect& rect,
2586                 const wxBitmap& bitmap,
2587                 wxRibbonButtonKind kind,
2588                 long state)
2589 {
2590     if(kind == wxRIBBON_BUTTON_TOGGLE)
2591     {
2592         if(state & wxRIBBON_TOOLBAR_TOOL_TOGGLED)
2593             state ^= wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK;
2594     }
2595 
2596     wxRect bg_rect(rect);
2597     bg_rect.Deflate(1);
2598     if((state & wxRIBBON_TOOLBAR_TOOL_LAST) == 0)
2599         bg_rect.width++;
2600     bool is_split_hybrid = (kind == wxRIBBON_BUTTON_HYBRID && (state &
2601         (wxRIBBON_TOOLBAR_TOOL_HOVER_MASK | wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK)));
2602 
2603     // Background
2604     wxRect bg_rect_top(bg_rect);
2605     bg_rect_top.height = (bg_rect_top.height * 2) / 5;
2606     wxRect bg_rect_btm(bg_rect);
2607     bg_rect_btm.y += bg_rect_top.height;
2608     bg_rect_btm.height -= bg_rect_top.height;
2609     wxColour bg_top_colour = m_tool_background_top_colour;
2610     wxColour bg_top_grad_colour = m_tool_background_top_gradient_colour;
2611     wxColour bg_colour = m_tool_background_colour;
2612     wxColour bg_grad_colour = m_tool_background_gradient_colour;
2613     if(state & wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK)
2614     {
2615         bg_top_colour = m_tool_active_background_top_colour;
2616         bg_top_grad_colour = m_tool_active_background_top_gradient_colour;
2617         bg_colour = m_tool_active_background_colour;
2618         bg_grad_colour = m_tool_active_background_gradient_colour;
2619     }
2620     else if(state & wxRIBBON_TOOLBAR_TOOL_HOVER_MASK)
2621     {
2622         bg_top_colour = m_tool_hover_background_top_colour;
2623         bg_top_grad_colour = m_tool_hover_background_top_gradient_colour;
2624         bg_colour = m_tool_hover_background_colour;
2625         bg_grad_colour = m_tool_hover_background_gradient_colour;
2626     }
2627     dc.GradientFillLinear(bg_rect_top, bg_top_colour, bg_top_grad_colour, wxSOUTH);
2628     dc.GradientFillLinear(bg_rect_btm, bg_colour, bg_grad_colour, wxSOUTH);
2629     if(is_split_hybrid)
2630     {
2631         wxRect nonrect(bg_rect);
2632         if(state & (wxRIBBON_TOOLBAR_TOOL_DROPDOWN_HOVERED |
2633             wxRIBBON_TOOLBAR_TOOL_DROPDOWN_ACTIVE))
2634         {
2635             nonrect.width -= 8;
2636         }
2637         else
2638         {
2639             nonrect.x += nonrect.width - 8;
2640             nonrect.width = 8;
2641         }
2642         wxBrush B(m_tool_hover_background_top_colour);
2643         dc.SetPen(*wxTRANSPARENT_PEN);
2644         dc.SetBrush(B);
2645         dc.DrawRectangle(nonrect.x, nonrect.y, nonrect.width, nonrect.height);
2646     }
2647 
2648     // Border
2649     dc.SetPen(m_toolbar_border_pen);
2650     if(state & wxRIBBON_TOOLBAR_TOOL_FIRST)
2651     {
2652         dc.DrawPoint(rect.x + 1, rect.y + 1);
2653         dc.DrawPoint(rect.x + 1, rect.y + rect.height - 2);
2654     }
2655     else
2656         dc.DrawLine(rect.x, rect.y + 1, rect.x, rect.y + rect.height - 1);
2657 
2658     if(state & wxRIBBON_TOOLBAR_TOOL_LAST)
2659     {
2660         dc.DrawPoint(rect.x + rect.width - 2, rect.y + 1);
2661         dc.DrawPoint(rect.x + rect.width - 2, rect.y + rect.height - 2);
2662     }
2663 
2664     // Foreground
2665     int avail_width = bg_rect.GetWidth();
2666     if(kind & wxRIBBON_BUTTON_DROPDOWN)
2667     {
2668         avail_width -= 8;
2669         if(is_split_hybrid)
2670         {
2671             dc.DrawLine(rect.x + avail_width + 1, rect.y,
2672                 rect.x + avail_width + 1, rect.y + rect.height);
2673         }
2674         dc.DrawBitmap(m_toolbar_drop_bitmap, bg_rect.x + avail_width + 2,
2675             bg_rect.y + (bg_rect.height / 2) - 2, true);
2676     }
2677     dc.DrawBitmap(bitmap, bg_rect.x + (avail_width - bitmap.GetWidth()) / 2,
2678         bg_rect.y + (bg_rect.height - bitmap.GetHeight()) / 2, true);
2679 }
2680 
2681 void
DrawToggleButton(wxDC & dc,wxRibbonBar * wnd,const wxRect & rect,wxRibbonDisplayMode mode)2682 wxRibbonMSWArtProvider::DrawToggleButton(wxDC& dc,
2683                                          wxRibbonBar* wnd,
2684                                          const wxRect& rect,
2685                                          wxRibbonDisplayMode mode)
2686 {
2687     int bindex = 0;
2688     DrawPartialPageBackground(dc, wnd, rect, false);
2689 
2690     dc.DestroyClippingRegion();
2691     dc.SetClippingRegion(rect);
2692 
2693     if(wnd->IsToggleButtonHovered())
2694     {
2695         dc.SetPen(m_ribbon_toggle_pen);
2696         dc.SetBrush(m_ribbon_toggle_brush);
2697         dc.DrawRoundedRectangle(rect.GetX(), rect.GetY(), 20, 20, 1.0);
2698         bindex = 1;
2699     }
2700     switch(mode)
2701     {
2702         case wxRIBBON_BAR_PINNED:
2703             dc.DrawBitmap(m_ribbon_toggle_up_bitmap[bindex], rect.GetX()+7, rect.GetY()+6, true);
2704             break;
2705         case wxRIBBON_BAR_MINIMIZED:
2706             dc.DrawBitmap(m_ribbon_toggle_down_bitmap[bindex], rect.GetX()+7, rect.GetY()+6, true);
2707             break;
2708         case wxRIBBON_BAR_EXPANDED:
2709             dc.DrawBitmap(m_ribbon_toggle_pin_bitmap[bindex], rect.GetX ()+4, rect.GetY ()+5, true);
2710             break;
2711     }
2712 }
2713 
DrawHelpButton(wxDC & dc,wxRibbonBar * wnd,const wxRect & rect)2714 void wxRibbonMSWArtProvider::DrawHelpButton(wxDC& dc,
2715                                        wxRibbonBar* wnd,
2716                                        const wxRect& rect)
2717 {
2718     DrawPartialPageBackground(dc, wnd, rect, false);
2719 
2720     dc.DestroyClippingRegion();
2721     dc.SetClippingRegion(rect);
2722 
2723     if ( wnd->IsHelpButtonHovered() )
2724     {
2725         dc.SetPen(m_ribbon_toggle_pen);
2726         dc.SetBrush(m_ribbon_toggle_brush);
2727         dc.DrawRoundedRectangle(rect.GetX(), rect.GetY(), 20, 20, 1.0);
2728         dc.DrawBitmap(m_ribbon_bar_help_button_bitmap[1], rect.GetX ()+4, rect.GetY()+5, true);
2729     }
2730     else
2731     {
2732         dc.DrawBitmap(m_ribbon_bar_help_button_bitmap[0], rect.GetX ()+4, rect.GetY()+5, true);
2733     }
2734 
2735 }
2736 
GetBarTabWidth(wxDC & dc,wxWindow * WXUNUSED (wnd),const wxString & label,const wxBitmap & bitmap,int * ideal,int * small_begin_need_separator,int * small_must_have_separator,int * minimum)2737 void wxRibbonMSWArtProvider::GetBarTabWidth(
2738                         wxDC& dc,
2739                         wxWindow* WXUNUSED(wnd),
2740                         const wxString& label,
2741                         const wxBitmap& bitmap,
2742                         int* ideal,
2743                         int* small_begin_need_separator,
2744                         int* small_must_have_separator,
2745                         int* minimum)
2746 {
2747     int width = 0;
2748     int min = 0;
2749     if((m_flags & wxRIBBON_BAR_SHOW_PAGE_LABELS) && !label.IsEmpty())
2750     {
2751         dc.SetFont(m_tab_label_font);
2752         width += dc.GetTextExtent(label).GetWidth();
2753         min += wxMin(25, width); // enough for a few chars
2754         if(bitmap.IsOk())
2755         {
2756             // gap between label and bitmap
2757             width += 4;
2758             min += 2;
2759         }
2760     }
2761     if((m_flags & wxRIBBON_BAR_SHOW_PAGE_ICONS) && bitmap.IsOk())
2762     {
2763         width += bitmap.GetWidth();
2764         min += bitmap.GetWidth();
2765     }
2766 
2767     if(ideal != NULL)
2768     {
2769         *ideal = width + 30;
2770     }
2771     if(small_begin_need_separator != NULL)
2772     {
2773         *small_begin_need_separator = width + 20;
2774     }
2775     if(small_must_have_separator != NULL)
2776     {
2777         *small_must_have_separator = width + 10;
2778     }
2779     if(minimum != NULL)
2780     {
2781         *minimum = min;
2782     }
2783 }
2784 
GetTabCtrlHeight(wxDC & dc,wxWindow * WXUNUSED (wnd),const wxRibbonPageTabInfoArray & pages)2785 int wxRibbonMSWArtProvider::GetTabCtrlHeight(
2786                         wxDC& dc,
2787                         wxWindow* WXUNUSED(wnd),
2788                         const wxRibbonPageTabInfoArray& pages)
2789 {
2790     int text_height = 0;
2791     int icon_height = 0;
2792 
2793     if(pages.GetCount() <= 1 && (m_flags & wxRIBBON_BAR_ALWAYS_SHOW_TABS) == 0)
2794     {
2795         // To preserve space, a single tab need not be displayed. We still need
2796         // two pixels of border / padding though.
2797         return 2;
2798     }
2799 
2800     if(m_flags & wxRIBBON_BAR_SHOW_PAGE_LABELS)
2801     {
2802         dc.SetFont(m_tab_label_font);
2803         text_height = dc.GetTextExtent(wxT("ABCDEFXj")).GetHeight() + 10;
2804     }
2805     if(m_flags & wxRIBBON_BAR_SHOW_PAGE_ICONS)
2806     {
2807         size_t numpages = pages.GetCount();
2808         for(size_t i = 0; i < numpages; ++i)
2809         {
2810             const wxRibbonPageTabInfo& info = pages.Item(i);
2811             if(info.page->GetIcon().IsOk())
2812             {
2813                 icon_height = wxMax(icon_height, info.page->GetIcon().GetHeight() + 4);
2814             }
2815         }
2816     }
2817 
2818     return wxMax(text_height, icon_height);
2819 }
2820 
GetScrollButtonMinimumSize(wxDC & WXUNUSED (dc),wxWindow * WXUNUSED (wnd),long WXUNUSED (style))2821 wxSize wxRibbonMSWArtProvider::GetScrollButtonMinimumSize(
2822                         wxDC& WXUNUSED(dc),
2823                         wxWindow* WXUNUSED(wnd),
2824                         long WXUNUSED(style))
2825 {
2826     return wxSize(12, 12);
2827 }
2828 
GetPanelSize(wxDC & dc,const wxRibbonPanel * wnd,wxSize client_size,wxPoint * client_offset)2829 wxSize wxRibbonMSWArtProvider::GetPanelSize(
2830                         wxDC& dc,
2831                         const wxRibbonPanel* wnd,
2832                         wxSize client_size,
2833                         wxPoint* client_offset)
2834 {
2835     dc.SetFont(m_panel_label_font);
2836     wxSize label_size = dc.GetTextExtent(wnd->GetLabel());
2837 
2838     client_size.IncBy(0, label_size.GetHeight());
2839     if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
2840         client_size.IncBy(4, 8);
2841     else
2842         client_size.IncBy(6, 6);
2843 
2844     if(client_offset != NULL)
2845     {
2846         if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
2847             *client_offset = wxPoint(2, 3);
2848         else
2849             *client_offset = wxPoint(3, 2);
2850     }
2851 
2852     return client_size;
2853 }
2854 
GetPanelClientSize(wxDC & dc,const wxRibbonPanel * wnd,wxSize size,wxPoint * client_offset)2855 wxSize wxRibbonMSWArtProvider::GetPanelClientSize(
2856                         wxDC& dc,
2857                         const wxRibbonPanel* wnd,
2858                         wxSize size,
2859                         wxPoint* client_offset)
2860 {
2861     dc.SetFont(m_panel_label_font);
2862     wxSize label_size = dc.GetTextExtent(wnd->GetLabel());
2863 
2864     size.DecBy(0, label_size.GetHeight());
2865     if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
2866         size.DecBy(4, 8);
2867     else
2868         size.DecBy(6, 6);
2869 
2870     if(client_offset != NULL)
2871     {
2872         if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
2873             *client_offset = wxPoint(2, 3);
2874         else
2875             *client_offset = wxPoint(3, 2);
2876     }
2877     if (size.x < 0) size.x = 0;
2878     if (size.y < 0) size.y = 0;
2879 
2880     return size;
2881 }
2882 
GetGallerySize(wxDC & WXUNUSED (dc),const wxRibbonGallery * WXUNUSED (wnd),wxSize client_size)2883 wxSize wxRibbonMSWArtProvider::GetGallerySize(
2884                         wxDC& WXUNUSED(dc),
2885                         const wxRibbonGallery* WXUNUSED(wnd),
2886                         wxSize client_size)
2887 {
2888     client_size.IncBy( 2, 1); // Left / top padding
2889     if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
2890         client_size.IncBy(1, 16); // Right / bottom padding
2891     else
2892         client_size.IncBy(16, 1); // Right / bottom padding
2893     return client_size;
2894 }
2895 
GetGalleryClientSize(wxDC & WXUNUSED (dc),const wxRibbonGallery * WXUNUSED (wnd),wxSize size,wxPoint * client_offset,wxRect * scroll_up_button,wxRect * scroll_down_button,wxRect * extension_button)2896 wxSize wxRibbonMSWArtProvider::GetGalleryClientSize(
2897                         wxDC& WXUNUSED(dc),
2898                         const wxRibbonGallery* WXUNUSED(wnd),
2899                         wxSize size,
2900                         wxPoint* client_offset,
2901                         wxRect* scroll_up_button,
2902                         wxRect* scroll_down_button,
2903                         wxRect* extension_button)
2904 {
2905     wxRect scroll_up;
2906     wxRect scroll_down;
2907     wxRect extension;
2908     if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
2909     {
2910         // Flow is vertical - put buttons on bottom
2911         scroll_up.y = size.GetHeight() - 15;
2912         scroll_up.height = 15;
2913         scroll_up.x = 0;
2914         scroll_up.width = (size.GetWidth() + 2) / 3;
2915         scroll_down.y = scroll_up.y;
2916         scroll_down.height = scroll_up.height;
2917         scroll_down.x = scroll_up.x + scroll_up.width;
2918         scroll_down.width = scroll_up.width;
2919         extension.y = scroll_down.y;
2920         extension.height = scroll_down.height;
2921         extension.x = scroll_down.x + scroll_down.width;
2922         extension.width = size.GetWidth() - scroll_up.width - scroll_down.width;
2923         size.DecBy(1, 16);
2924         size.DecBy( 2, 1);
2925     }
2926     else
2927     {
2928         // Flow is horizontal - put buttons on right
2929         scroll_up.x = size.GetWidth() - 15;
2930         scroll_up.width = 15;
2931         scroll_up.y = 0;
2932         scroll_up.height = (size.GetHeight() + 2) / 3;
2933         scroll_down.x = scroll_up.x;
2934         scroll_down.width = scroll_up.width;
2935         scroll_down.y = scroll_up.y + scroll_up.height;
2936         scroll_down.height = scroll_up.height;
2937         extension.x = scroll_down.x;
2938         extension.width = scroll_down.width;
2939         extension.y = scroll_down.y + scroll_down.height;
2940         extension.height = size.GetHeight() - scroll_up.height - scroll_down.height;
2941         size.DecBy(16, 1);
2942         size.DecBy( 2, 1);
2943     }
2944 
2945     if(client_offset != NULL)
2946         *client_offset = wxPoint(2, 1);
2947     if(scroll_up_button != NULL)
2948         *scroll_up_button = scroll_up;
2949     if(scroll_down_button != NULL)
2950         *scroll_down_button = scroll_down;
2951     if(extension_button != NULL)
2952         *extension_button = extension;
2953 
2954     return size;
2955 }
2956 
GetPageBackgroundRedrawArea(wxDC & WXUNUSED (dc),const wxRibbonPage * WXUNUSED (wnd),wxSize page_old_size,wxSize page_new_size)2957 wxRect wxRibbonMSWArtProvider::GetPageBackgroundRedrawArea(
2958                         wxDC& WXUNUSED(dc),
2959                         const wxRibbonPage* WXUNUSED(wnd),
2960                         wxSize page_old_size,
2961                         wxSize page_new_size)
2962 {
2963     wxRect new_rect, old_rect;
2964 
2965     if(page_new_size.GetWidth() != page_old_size.GetWidth())
2966     {
2967         if(page_new_size.GetHeight() != page_old_size.GetHeight())
2968         {
2969             // Width and height both changed - redraw everything
2970             return wxRect(page_new_size);
2971         }
2972         else
2973         {
2974             // Only width changed - redraw right hand side
2975             const int right_edge_width = 4;
2976 
2977             new_rect = wxRect(page_new_size.GetWidth() - right_edge_width, 0, right_edge_width, page_new_size.GetHeight());
2978             old_rect = wxRect(page_old_size.GetWidth() - right_edge_width, 0, right_edge_width, page_old_size.GetHeight());
2979         }
2980     }
2981     else
2982     {
2983         if(page_new_size.GetHeight() == page_old_size.GetHeight())
2984         {
2985             // Nothing changed (should never happen) - redraw nothing
2986             return wxRect(0, 0, 0, 0);
2987         }
2988         else
2989         {
2990             // Height changed - need to redraw everything (as the background
2991             // gradient is done vertically).
2992             return page_new_size;
2993         }
2994     }
2995 
2996     new_rect.Union(old_rect);
2997     new_rect.Intersect(wxRect(page_new_size));
2998     return new_rect;
2999 }
3000 
GetButtonBarButtonSize(wxDC & dc,wxWindow * wnd,wxRibbonButtonKind kind,wxRibbonButtonBarButtonState size,const wxString & label,wxSize bitmap_size_large,wxSize bitmap_size_small,wxSize * button_size,wxRect * normal_region,wxRect * dropdown_region)3001 bool wxRibbonMSWArtProvider::GetButtonBarButtonSize(
3002                         wxDC& dc,
3003                         wxWindow* wnd,
3004                         wxRibbonButtonKind kind,
3005                         wxRibbonButtonBarButtonState size,
3006                         const wxString& label,
3007                         wxSize bitmap_size_large,
3008                         wxSize bitmap_size_small,
3009                         wxSize* button_size,
3010                         wxRect* normal_region,
3011                         wxRect* dropdown_region)
3012 {
3013     const int drop_button_width = 8;
3014 
3015     dc.SetFont(m_button_bar_label_font);
3016     switch(size & wxRIBBON_BUTTONBAR_BUTTON_SIZE_MASK)
3017     {
3018     case wxRIBBON_BUTTONBAR_BUTTON_SMALL:
3019         // Small bitmap, no label
3020         *button_size = bitmap_size_small + wxSize(6, 4);
3021         switch(kind)
3022         {
3023         case wxRIBBON_BUTTON_NORMAL:
3024         case wxRIBBON_BUTTON_TOGGLE:
3025             *normal_region = wxRect(*button_size);
3026             *dropdown_region = wxRect(0, 0, 0, 0);
3027             break;
3028         case wxRIBBON_BUTTON_DROPDOWN:
3029             *button_size += wxSize(drop_button_width, 0);
3030             *dropdown_region = wxRect(*button_size);
3031             *normal_region = wxRect(0, 0, 0, 0);
3032             break;
3033         case wxRIBBON_BUTTON_HYBRID:
3034             *normal_region = wxRect(*button_size);
3035             *dropdown_region = wxRect(button_size->GetWidth(), 0,
3036                 drop_button_width, button_size->GetHeight());
3037             *button_size += wxSize(drop_button_width, 0);
3038             break;
3039         }
3040         break;
3041     case wxRIBBON_BUTTONBAR_BUTTON_MEDIUM:
3042         // Small bitmap, with label to the right
3043         {
3044             GetButtonBarButtonSize(dc, wnd, kind, wxRIBBON_BUTTONBAR_BUTTON_SMALL,
3045                 label, bitmap_size_large, bitmap_size_small, button_size,
3046                 normal_region, dropdown_region);
3047             int text_size = dc.GetTextExtent(label).GetWidth();
3048             button_size->SetWidth(button_size->GetWidth() + text_size);
3049             switch(kind)
3050             {
3051             case wxRIBBON_BUTTON_DROPDOWN:
3052                 dropdown_region->SetWidth(dropdown_region->GetWidth() + text_size);
3053                 break;
3054             case wxRIBBON_BUTTON_HYBRID:
3055                 dropdown_region->SetX(dropdown_region->GetX() + text_size);
3056                 // no break
3057             case wxRIBBON_BUTTON_NORMAL:
3058             case wxRIBBON_BUTTON_TOGGLE:
3059                 normal_region->SetWidth(normal_region->GetWidth() + text_size);
3060                 break;
3061             }
3062             break;
3063         }
3064     case wxRIBBON_BUTTONBAR_BUTTON_LARGE:
3065         // Large bitmap, with label below (possibly split over 2 lines)
3066         {
3067             wxSize icon_size(bitmap_size_large);
3068             icon_size += wxSize(4, 4);
3069             wxCoord label_height;
3070             wxCoord best_width;
3071             dc.GetTextExtent(label, &best_width, &label_height);
3072             int last_line_extra_width = 0;
3073             if(kind != wxRIBBON_BUTTON_NORMAL && kind != wxRIBBON_BUTTON_TOGGLE)
3074             {
3075                 last_line_extra_width += 8;
3076             }
3077             size_t i;
3078             for(i = 0; i < label.Len(); ++i)
3079             {
3080                 if(wxRibbonCanLabelBreakAtPosition(label, i))
3081                 {
3082                     int width = wxMax(
3083                         dc.GetTextExtent(label.Left(i)).GetWidth(),
3084                         dc.GetTextExtent(label.Mid(i + 1)).GetWidth() + last_line_extra_width);
3085                     if(width < best_width)
3086                     {
3087                         best_width = width;
3088                     }
3089                 }
3090             }
3091             label_height *= 2; // Assume two lines even when only one is used
3092                                // (to give all buttons a consistent height)
3093             icon_size.SetWidth(wxMax(icon_size.GetWidth(), best_width) + 6);
3094             icon_size.SetHeight(icon_size.GetHeight() + label_height);
3095             *button_size = icon_size;
3096             switch(kind)
3097             {
3098             case wxRIBBON_BUTTON_DROPDOWN:
3099                 *dropdown_region = wxRect(icon_size);
3100                 break;
3101             case wxRIBBON_BUTTON_HYBRID:
3102                 *normal_region = wxRect(icon_size);
3103                 normal_region->height -= 2 + label_height;
3104                 dropdown_region->x = 0;
3105                 dropdown_region->y = normal_region->height;
3106                 dropdown_region->width = icon_size.GetWidth();
3107                 dropdown_region->height = icon_size.GetHeight() - normal_region->height;
3108                 break;
3109             case wxRIBBON_BUTTON_NORMAL:
3110             case wxRIBBON_BUTTON_TOGGLE:
3111                 *normal_region = wxRect(icon_size);
3112                 break;
3113             }
3114             break;
3115         }
3116     };
3117     return true;
3118 }
3119 
GetMinimisedPanelMinimumSize(wxDC & dc,const wxRibbonPanel * wnd,wxSize * desired_bitmap_size,wxDirection * expanded_panel_direction)3120 wxSize wxRibbonMSWArtProvider::GetMinimisedPanelMinimumSize(
3121                         wxDC& dc,
3122                         const wxRibbonPanel* wnd,
3123                         wxSize* desired_bitmap_size,
3124                         wxDirection* expanded_panel_direction)
3125 {
3126     if(desired_bitmap_size != NULL)
3127     {
3128         *desired_bitmap_size = wxSize(16, 16);
3129     }
3130     if(expanded_panel_direction != NULL)
3131     {
3132         if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
3133             *expanded_panel_direction = wxEAST;
3134         else
3135             *expanded_panel_direction = wxSOUTH;
3136     }
3137     wxSize base_size(42, 42);
3138 
3139     dc.SetFont(m_panel_label_font);
3140     wxSize label_size(dc.GetTextExtent(wnd->GetLabel()));
3141     label_size.IncBy(2, 2); // Allow for differences between this DC and a paint DC
3142     label_size.IncBy(6, 0); // Padding
3143     label_size.y *= 2; // Second line for dropdown button
3144 
3145     if(m_flags & wxRIBBON_BAR_FLOW_VERTICAL)
3146     {
3147         // Label alongside icon
3148         return wxSize(base_size.x + label_size.x,
3149             wxMax(base_size.y, label_size.y));
3150     }
3151     else
3152     {
3153         // Label beneath icon
3154         return wxSize(wxMax(base_size.x, label_size.x),
3155             base_size.y + label_size.y);
3156     }
3157 }
3158 
GetToolSize(wxDC & WXUNUSED (dc),wxWindow * WXUNUSED (wnd),wxSize bitmap_size,wxRibbonButtonKind kind,bool WXUNUSED (is_first),bool is_last,wxRect * dropdown_region)3159 wxSize wxRibbonMSWArtProvider::GetToolSize(
3160                         wxDC& WXUNUSED(dc),
3161                         wxWindow* WXUNUSED(wnd),
3162                         wxSize bitmap_size,
3163                         wxRibbonButtonKind kind,
3164                         bool WXUNUSED(is_first),
3165                         bool is_last,
3166                         wxRect* dropdown_region)
3167 {
3168     wxSize size(bitmap_size);
3169     size.IncBy(7, 6);
3170     if(is_last)
3171         size.IncBy(1, 0);
3172     if(kind & wxRIBBON_BUTTON_DROPDOWN)
3173     {
3174         size.IncBy(8, 0);
3175         if(dropdown_region)
3176         {
3177             if(kind == wxRIBBON_BUTTON_DROPDOWN)
3178                 *dropdown_region = size;
3179             else
3180                 *dropdown_region = wxRect(size.GetWidth() - 8, 0, 8, size.GetHeight());
3181         }
3182     }
3183     else
3184     {
3185         if(dropdown_region)
3186             *dropdown_region = wxRect(0, 0, 0, 0);
3187     }
3188     return size;
3189 }
3190 
3191 wxRect
GetBarToggleButtonArea(const wxRect & rect)3192 wxRibbonMSWArtProvider::GetBarToggleButtonArea(const wxRect& rect)
3193 {
3194     wxRect rectOut = wxRect(rect.GetWidth()-m_toggle_button_offset, 2, 20, 20);
3195     if ( (m_toggle_button_offset==22) && (m_help_button_offset==22) )
3196         m_help_button_offset += 22;
3197     return rectOut;
3198 }
3199 
3200 wxRect
GetRibbonHelpButtonArea(const wxRect & rect)3201 wxRibbonMSWArtProvider::GetRibbonHelpButtonArea(const wxRect& rect)
3202 {
3203     wxRect rectOut = wxRect(rect.GetWidth()-m_help_button_offset, 2, 20, 20);
3204     if ( (m_toggle_button_offset==22) && (m_help_button_offset==22) )
3205         m_toggle_button_offset += 22;
3206     return rectOut;
3207 }
3208 
3209 #endif // wxUSE_RIBBON
3210