1# -*- coding: utf-8 -*- 2#---------------------------------------------------------------------------- 3# Name: art_msw.py 4# Purpose: 5# 6# Author: Andrea Gavana <andrea.gavana@gmail.com> 7# 8# Created: 9# Version: 10# Date: 11# Licence: wxWindows license 12# Tags: phoenix-port, unittest, documented, py3-port 13#---------------------------------------------------------------------------- 14""" 15`art_msw` is responsible for drawing all the components of the ribbon 16interface using a Windows appearance. 17 18 19Description 20=========== 21 22This allows a ribbon bar to have a pluggable look-and-feel, while retaining the same 23underlying behaviour. As a single art provider is used for all ribbon components, a 24ribbon bar usually has a consistent (though unique) appearance. 25 26By default, a :class:`~wx.lib.agw.ribbon.bar.RibbonBar` uses an instance of a class called 27:class:`~wx.lib.agw.ribbon.art_default.RibbonDefaultArtProvider`, 28which resolves to :class:`~wx.lib.agw.ribbon.art_aui.RibbonAUIArtProvider`, 29:class:`~wx.lib.agw.ribbon.art_msw.RibbonMSWArtProvider`, or 30:class:`~wx.lib.agw.ribbon.art_osx.RibbonOSXArtProvider` - whichever is most appropriate 31to the current platform. These art providers are all 32slightly configurable with regard to colours and fonts, but for larger modifications, 33you can derive from one of these classes, or write a completely new art provider class. 34 35Call :meth:`RibbonBar.SetArtProvider() <lib.agw.ribbon.bar.RibbonBar.SetArtProvider>` to change the art provider being used. 36 37 38See Also 39======== 40 41:class:`~wx.lib.agw.ribbon.bar.RibbonBar` 42""" 43 44import wx 45 46from math import cos 47from math import pi as M_PI 48 49from . import panel as PANEL 50from . import page as PAGE 51 52from .art_internal import RibbonLoadPixmap, RibbonInterpolateColour, RibbonDrawParallelGradientLines 53from .art_internal import RibbonCanLabelBreakAtPosition 54from .art_internal import RibbonHSLColour 55 56from .art import * 57 58 59gallery_up_xpm = [b"5 5 2 1", b" c None", b"x c #FF00FF", b" ", b" x ", b" xxx ", b"xxxxx", b" "] 60gallery_down_xpm = [b"5 5 2 1", b" c None", b"x c #FF00FF", b" ", b"xxxxx", b" xxx ", b" x ", b" "] 61gallery_left_xpm = [b"5 5 2 1", b" c None", b"x c #FF00FF", b" x ", b" xx ", b" xxx ", b" xx ", b" x "] 62gallery_right_xpm = [b"5 5 2 1", b" c None", b"x c #FF00FF", b" x ", b" xx ", b" xxx ", b" xx ", b" x "] 63gallery_extension_xpm = [b"5 5 2 1", b" c None", b"x c #FF00FF", b"xxxxx", b" ", b"xxxxx", b" xxx ", b" x "] 64panel_extension_xpm = [b"7 7 2 1", b" c None", b"x c #FF00FF", b"xxxxxx ", b"x ", b"x ", 65 b"x x x", b"x xxx", b"x xxx", b" xxxx"] 66 67 68def LikePrimary(primary_hsl, is_gray, h, s, l): 69 70 return primary_hsl.ShiftHue(h).Saturated((is_gray and [0] or [s])[0]).Lighter(l).ToRGB() 71 72 73def LikeSecondary(secondary_hsl, is_gray, h, s, l): 74 75 return secondary_hsl.ShiftHue(h).Saturated((is_gray and [0] or [s])[0]).Lighter(l).ToRGB() 76 77 78def SingleLine(dc, rect, start, finish): 79 80 dc.DrawLine(start.x + rect.x, start.y + rect.y, finish.x + rect.x, finish.y + rect.y) 81 82 83class RibbonMSWArtProvider(object): 84 85 def __init__(self, set_colour_scheme=True): 86 87 self._flags = 0 88 self._tab_label_font = wx.NORMAL_FONT 89 self._button_bar_label_font = wx.NORMAL_FONT 90 self._panel_label_font = wx.NORMAL_FONT 91 92 self._gallery_up_bitmap = [wx.NullBitmap for i in range(4)] 93 self._gallery_down_bitmap = [wx.NullBitmap for i in range(4)] 94 self._gallery_extension_bitmap = [wx.NullBitmap for i in range(4)] 95 self._panel_extension_bitmap = [wx.NullBitmap for i in range(2)] 96 97 if set_colour_scheme: 98 self.SetColourScheme(wx.Colour(194, 216, 241), wx.Colour(255, 223, 114), wx.Colour(0, 0, 0)) 99 100 self._cached_tab_separator_visibility = -10.0 # valid visibilities are in range [0, 1] 101 self._tab_separation_size = 3 102 self._page_border_left = 2 103 self._page_border_top = 1 104 self._page_border_right = 2 105 self._page_border_bottom = 3 106 self._panel_x_separation_size = 1 107 self._panel_y_separation_size = 1 108 self._tool_group_separation_size = 3 109 self._gallery_bitmap_padding_left_size = 4 110 self._gallery_bitmap_padding_right_size = 4 111 self._gallery_bitmap_padding_top_size = 4 112 self._gallery_bitmap_padding_bottom__size = 4 113 self._cached_tab_separator = wx.NullBitmap 114 115 116 def GetColourScheme(self, primary, secondary, tertiary): 117 """ 118 Get the current colour scheme. 119 120 Returns three colours such that if :meth:`~RibbonMSWArtProvider.SetColourScheme` were called with them, the 121 colour scheme would be restored to what it was when :meth:`~RibbonMSWArtProvider.SetColourScheme` was last 122 called. In practice, this usually means that the returned values are the three 123 colours given in the last call to :meth:`~RibbonMSWArtProvider.SetColourScheme`, however if 124 :meth:`~RibbonMSWArtProvider.SetColourScheme` performs an idempotent operation upon the colours it is given 125 (like clamping a component of the colour), then the returned values may not be 126 the three colours given in the last call to :meth:`~RibbonMSWArtProvider.SetColourScheme`. 127 128 If :meth:`~RibbonMSWArtProvider.SetColourScheme` has not been called, then the returned values should result 129 in a colour scheme similar to, if not identical to, the default colours of the 130 art provider. Note that if :meth:`~RibbonMSWArtProvider.SetColour` is called, then :meth:`~RibbonMSWArtProvider.GetColourScheme` does 131 not try and return a colour scheme similar to colours being used - it's return 132 values are dependant upon the last values given to :meth:`~RibbonMSWArtProvider.SetColourScheme`, as 133 described above. 134 135 :param `primary`: Pointer to a location to store the primary colour, or ``None``; 136 :param `secondary`: Pointer to a location to store the secondary colour, or ``None``; 137 :param `tertiary`: Pointer to a location to store the tertiary colour, or ``None``. 138 139 """ 140 141 if primary != None: 142 primary = self._primary_scheme_colour 143 if secondary != None: 144 secondary = self._secondary_scheme_colour 145 if tertiary != None: 146 tertiary = self._tertiary_scheme_colour 147 148 return primary, secondary, tertiary 149 150 151 def SetColourScheme(self, primary, secondary, tertiary): 152 """ 153 Set all applicable colour settings from a few base colours. 154 155 Uses any or all of the three given colours to create a colour scheme, and then 156 sets all colour settings which are relevant to the art provider using that 157 scheme. Note that some art providers may not use the tertiary colour for 158 anything, and some may not use the secondary colour either. 159 160 :param `primary`: MISSING DESCRIPTION; 161 :param `secondary`: MISSING DESCRIPTION; 162 :param `tertiary`: MISSING DESCRIPTION. 163 164 :see: :meth:`~RibbonMSWArtProvider.SetColour`, :meth:`~RibbonMSWArtProvider.GetColourScheme` 165 """ 166 167 self._primary_scheme_colour = primary 168 self._secondary_scheme_colour = secondary 169 self._tertiary_scheme_colour = tertiary 170 171 primary_hsl = RibbonHSLColour(primary) 172 secondary_hsl = RibbonHSLColour(secondary) 173 # tertiary not used for anything 174 175 # Map primary saturation from [0, 1] to [.25, .75] 176 primary_is_gray = False 177 gray_saturation_threshold = 0.01 178 179 if primary_hsl.saturation <= gray_saturation_threshold: 180 primary_is_gray = True 181 else: 182 primary_hsl.saturation = cos(primary_hsl.saturation * M_PI) * -0.25 + 0.5 183 184 # Map primary luminance from [0, 1] to [.23, .83] 185 primary_hsl.luminance = cos(primary_hsl.luminance * M_PI) * -0.3 + 0.53 186 187 # Map secondary saturation from [0, 1] to [0.16, 0.84] 188 secondary_is_gray = False 189 190 if secondary_hsl.saturation <= gray_saturation_threshold: 191 secondary_is_gray = True 192 else: 193 secondary_hsl.saturation = cos(secondary_hsl.saturation * M_PI) * -0.34 + 0.5 194 195 # Map secondary luminance from [0, 1] to [0.1, 0.9] 196 secondary_hsl.luminance = cos(secondary_hsl.luminance * M_PI) * -0.4 + 0.5 197 198 self._page_border_pen = wx.Pen(LikePrimary(primary_hsl, primary_is_gray, 1.4, 0.00, -0.08)) 199 self._page_background_top_colour = LikePrimary(primary_hsl, primary_is_gray, -0.1, -0.03, 0.12) 200 self._page_hover_background_top_colour = LikePrimary(primary_hsl, primary_is_gray, -2.8, 0.27, 0.17) 201 self._page_background_top_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 0.1, -0.10, 0.08) 202 self._page_hover_background_top_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 3.2, 0.16, 0.13) 203 self._page_background_colour = LikePrimary(primary_hsl, primary_is_gray, 0.4, -0.09, 0.05) 204 self._page_hover_background_colour = LikePrimary(primary_hsl, primary_is_gray, 0.1, 0.19, 0.10) 205 self._page_background_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, -3.2, 0.27, 0.10) 206 self._page_hover_background_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 1.8, 0.01, 0.15) 207 208 self._tab_active_background_colour = LikePrimary(primary_hsl, primary_is_gray, -0.1, -0.31, 0.16) 209 self._tab_active_background_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, -0.1, -0.03, 0.12) 210 self._tab_separator_colour = LikePrimary(primary_hsl, primary_is_gray, 0.9, 0.24, 0.05) 211 self._tab_ctrl_background_brush = wx.Brush(LikePrimary(primary_hsl, primary_is_gray, 1.0, 0.39, 0.07)) 212 self._tab_hover_background_colour = LikePrimary(primary_hsl, primary_is_gray, 1.3, 0.15, 0.10) 213 self._tab_hover_background_top_colour = LikePrimary(primary_hsl, primary_is_gray, 1.4, 0.36, 0.08) 214 self._tab_border_pen = wx.Pen(LikePrimary(primary_hsl, primary_is_gray, 1.4, 0.03, -0.05) ) 215 self._tab_separator_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 1.7, -0.15, -0.18) 216 self._tab_hover_background_top_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 1.8, 0.34, 0.13) 217 self._tab_label_colour = LikePrimary(primary_hsl, primary_is_gray, 4.3, 0.13, -0.49) 218 self._tab_hover_background_gradient_colour = LikeSecondary(primary_hsl, secondary_is_gray, -1.5, -0.34, 0.01) 219 220 self._panel_minimised_border_gradient_pen = wx.Pen(LikePrimary(primary_hsl, primary_is_gray, -6.9, -0.17, -0.09)) 221 self._panel_minimised_border_pen = wx.Pen(LikePrimary(primary_hsl, primary_is_gray, -5.3, -0.24, -0.06)) 222 self._panel_border_gradient_pen = wx.Pen(LikePrimary(primary_hsl, primary_is_gray, -5.2, -0.15, -0.06)) 223 self._panel_border_pen = wx.Pen(LikePrimary(primary_hsl, primary_is_gray, -2.8, -0.32, 0.02)) 224 self._panel_label_background_brush = wx.Brush(LikePrimary(primary_hsl, primary_is_gray, -1.5, 0.03, 0.05)) 225 self._panel_active_background_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 0.5, 0.34, 0.05) 226 self._panel_hover_label_background_brush = wx.Brush(LikePrimary(primary_hsl, primary_is_gray, 1.0, 0.30, 0.09)) 227 self._panel_active_background_top_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 1.4, -0.17, -0.13) 228 self._panel_active_background_colour = LikePrimary(primary_hsl, primary_is_gray, 1.6, -0.18, -0.18) 229 self._panel_active_background_top_colour = LikePrimary(primary_hsl, primary_is_gray, 1.7, -0.20, -0.03) 230 self._panel_label_colour = LikePrimary(primary_hsl, primary_is_gray, 2.8, -0.14, -0.35) 231 self._panel_hover_label_colour = self._panel_label_colour 232 self._panel_minimised_label_colour = self._tab_label_colour 233 234 self._panel_hover_button_background_brush = wx.Brush(LikeSecondary(secondary_hsl, secondary_is_gray, -0.9, 0.16, -0.07)) 235 self._panel_hover_button_border_pen = wx.Pen(LikeSecondary(secondary_hsl, secondary_is_gray, -3.9, -0.16, -0.14)) 236 self.SetColour(RIBBON_ART_PANEL_BUTTON_FACE_COLOUR, LikePrimary(primary_hsl, primary_is_gray, 1.4, -0.21, -0.23)) 237 self.SetColour(RIBBON_ART_PANEL_BUTTON_HOVER_FACE_COLOUR, LikePrimary(primary_hsl, primary_is_gray, 1.5, -0.24, -0.29)) 238 239 self._gallery_button_disabled_background_colour = LikePrimary(primary_hsl, primary_is_gray, -2.8, -0.46, 0.09) 240 self._gallery_button_disabled_background_top_brush = wx.Brush(LikePrimary(primary_hsl, primary_is_gray, -2.8, -0.36, 0.15)) 241 self._gallery_hover_background_brush = wx.Brush(LikePrimary(primary_hsl, primary_is_gray, -0.8, 0.05, 0.15)) 242 self._gallery_border_pen = wx.Pen(LikePrimary(primary_hsl, primary_is_gray, 0.7, -0.02, 0.03)) 243 self._gallery_button_background_top_brush = wx.Brush(LikePrimary(primary_hsl, primary_is_gray, 0.8, 0.34, 0.13)) 244 self._gallery_button_background_colour = LikePrimary(primary_hsl, primary_is_gray, 1.3, 0.10, 0.08) 245 246 # SetColour used so that the relevant bitmaps are generated 247 self.SetColour(RIBBON_ART_GALLERY_BUTTON_FACE_COLOUR, LikePrimary(primary_hsl, primary_is_gray, 1.4, -0.21, -0.23)) 248 self.SetColour(RIBBON_ART_GALLERY_BUTTON_HOVER_FACE_COLOUR, LikePrimary(primary_hsl, primary_is_gray, 1.5, -0.24, -0.29)) 249 self.SetColour(RIBBON_ART_GALLERY_BUTTON_ACTIVE_FACE_COLOUR, LikePrimary(primary_hsl, primary_is_gray, 1.5, -0.24, -0.29)) 250 self.SetColour(RIBBON_ART_GALLERY_BUTTON_DISABLED_FACE_COLOUR, LikePrimary(primary_hsl, primary_is_gray, 0.0, -1.0, 0.0)) 251 self._gallery_button_disabled_background_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 1.5, -0.43, 0.12) 252 self._gallery_button_background_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 1.7, 0.11, 0.09) 253 self._gallery_item_border_pen = wx.Pen(LikeSecondary(secondary_hsl, secondary_is_gray, -3.9, -0.16, -0.14)) 254 self._gallery_button_hover_background_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -0.9, 0.16, -0.07) 255 self._gallery_button_hover_background_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, 0.1, 0.12, 0.03) 256 self._gallery_button_hover_background_top_brush = wx.Brush(LikeSecondary(secondary_hsl, secondary_is_gray, 4.3, 0.16, 0.17)) 257 258 self._gallery_button_active_background_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -9.9, 0.03, -0.22) 259 self._gallery_button_active_background_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -9.5, 0.14, -0.11) 260 self._gallery_button_active_background_top_brush = wx.Brush(LikeSecondary(secondary_hsl, secondary_is_gray, -9.0, 0.15, -0.08)) 261 262 self._button_bar_label_colour = self._tab_label_colour 263 self._button_bar_hover_border_pen = wx.Pen(LikeSecondary(secondary_hsl, secondary_is_gray, -6.2, -0.47, -0.14)) 264 self._button_bar_hover_background_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -0.6, 0.16, 0.04) 265 self._button_bar_hover_background_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -0.2, 0.16, -0.10) 266 self._button_bar_hover_background_top_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, 0.2, 0.16, 0.03) 267 self._button_bar_hover_background_top_colour = LikeSecondary(secondary_hsl, secondary_is_gray, 8.8, 0.16, 0.17) 268 self._button_bar_active_border_pen = wx.Pen(LikeSecondary(secondary_hsl, secondary_is_gray, -6.2, -0.47, -0.25)) 269 self._button_bar_active_background_top_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -8.4, 0.08, 0.06) 270 self._button_bar_active_background_top_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -9.7, 0.13, -0.07) 271 self._button_bar_active_background_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -9.9, 0.14, -0.14) 272 self._button_bar_active_background_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -8.7, 0.17, -0.03) 273 274 self._toolbar_border_pen = wx.Pen(LikePrimary(primary_hsl, primary_is_gray, 1.4, -0.21, -0.16)) 275 self.SetColour(RIBBON_ART_TOOLBAR_FACE_COLOUR, LikePrimary(primary_hsl, primary_is_gray, 1.4, -0.17, -0.22)) 276 self._tool_background_top_colour = LikePrimary(primary_hsl, primary_is_gray, -1.9, -0.07, 0.06) 277 self._tool_background_top_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 1.4, 0.12, 0.08) 278 self._tool_background_colour = LikePrimary(primary_hsl, primary_is_gray, 1.4, -0.09, 0.03) 279 self._tool_background_gradient_colour = LikePrimary(primary_hsl, primary_is_gray, 1.9, 0.11, 0.09) 280 self._tool_hover_background_top_colour = LikeSecondary(secondary_hsl, secondary_is_gray, 3.4, 0.11, 0.16) 281 self._tool_hover_background_top_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -1.4, 0.04, 0.08) 282 self._tool_hover_background_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -1.8, 0.16, -0.12) 283 self._tool_hover_background_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -2.6, 0.16, 0.05) 284 self._tool_active_background_top_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -9.9, -0.12, -0.09) 285 self._tool_active_background_top_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -8.5, 0.16, -0.12) 286 self._tool_active_background_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -7.9, 0.16, -0.20) 287 self._tool_active_background_gradient_colour = LikeSecondary(secondary_hsl, secondary_is_gray, -6.6, 0.16, -0.10) 288 289 # Invalidate cached tab separator 290 self._cached_tab_separator_visibility = -1.0 291 292 293 def Clone(self): 294 """ 295 Create a new art provider which is a clone of this one. 296 """ 297 298 copy = RibbonMSWArtProvider() 299 self.CloneTo(copy) 300 return copy 301 302 303 def CloneTo(self, copy): 304 305 for i in range(4): 306 copy._gallery_up_bitmap[i] = self._gallery_up_bitmap[i] 307 copy._gallery_down_bitmap[i] = self._gallery_down_bitmap[i] 308 copy._gallery_extension_bitmap[i] = self._gallery_extension_bitmap[i] 309 310 for i in range(2): 311 copy._panel_extension_bitmap[i] = self._panel_extension_bitmap[i] 312 313 copy._toolbar_drop_bitmap = self._toolbar_drop_bitmap 314 315 copy._primary_scheme_colour = self._primary_scheme_colour 316 copy._secondary_scheme_colour = self._secondary_scheme_colour 317 copy._tertiary_scheme_colour = self._tertiary_scheme_colour 318 319 copy._button_bar_label_colour = self._button_bar_label_colour 320 copy._tab_label_colour = self._tab_label_colour 321 copy._tab_separator_colour = self._tab_separator_colour 322 copy._tab_separator_gradient_colour = self._tab_separator_gradient_colour 323 copy._tab_active_background_colour = self._tab_hover_background_colour 324 copy._tab_active_background_gradient_colour = self._tab_hover_background_gradient_colour 325 copy._tab_hover_background_colour = self._tab_hover_background_colour 326 copy._tab_hover_background_gradient_colour = self._tab_hover_background_gradient_colour 327 copy._tab_hover_background_top_colour = self._tab_hover_background_top_colour 328 copy._tab_hover_background_top_gradient_colour = self._tab_hover_background_top_gradient_colour 329 copy._panel_label_colour = self._panel_label_colour 330 copy._panel_hover_label_colour = self._panel_hover_label_colour 331 copy._panel_minimised_label_colour = self._panel_minimised_label_colour 332 copy._panel_button_face_colour = self._panel_button_face_colour 333 copy._panel_button_hover_face_colour = self._panel_button_hover_face_colour 334 copy._panel_active_background_colour = self._panel_active_background_colour 335 copy._panel_active_background_gradient_colour = self._panel_active_background_gradient_colour 336 copy._panel_active_background_top_colour = self._panel_active_background_top_colour 337 copy._panel_active_background_top_gradient_colour = self._panel_active_background_top_gradient_colour 338 copy._page_background_colour = self._page_background_colour 339 copy._page_background_gradient_colour = self._page_background_gradient_colour 340 copy._page_background_top_colour = self._page_background_top_colour 341 copy._page_background_top_gradient_colour = self._page_background_top_gradient_colour 342 copy._page_hover_background_colour = self._page_hover_background_colour 343 copy._page_hover_background_gradient_colour = self._page_hover_background_gradient_colour 344 copy._page_hover_background_top_colour = self._page_hover_background_top_colour 345 copy._page_hover_background_top_gradient_colour = self._page_hover_background_top_gradient_colour 346 copy._button_bar_hover_background_colour = self._button_bar_hover_background_colour 347 copy._button_bar_hover_background_gradient_colour = self._button_bar_hover_background_gradient_colour 348 copy._button_bar_hover_background_top_colour = self._button_bar_hover_background_top_colour 349 copy._button_bar_hover_background_top_gradient_colour = self._button_bar_hover_background_top_gradient_colour 350 copy._button_bar_active_background_colour = self._button_bar_active_background_colour 351 copy._button_bar_active_background_gradient_colour = self._button_bar_active_background_gradient_colour 352 copy._button_bar_active_background_top_colour = self._button_bar_active_background_top_colour 353 copy._button_bar_active_background_top_gradient_colour = self._button_bar_active_background_top_gradient_colour 354 copy._gallery_button_background_colour = self._gallery_button_background_colour 355 copy._gallery_button_background_gradient_colour = self._gallery_button_background_gradient_colour 356 copy._gallery_button_hover_background_colour = self._gallery_button_hover_background_colour 357 copy._gallery_button_hover_background_gradient_colour = self._gallery_button_hover_background_gradient_colour 358 copy._gallery_button_active_background_colour = self._gallery_button_active_background_colour 359 copy._gallery_button_active_background_gradient_colour = self._gallery_button_active_background_gradient_colour 360 copy._gallery_button_disabled_background_colour = self._gallery_button_disabled_background_colour 361 copy._gallery_button_disabled_background_gradient_colour = self._gallery_button_disabled_background_gradient_colour 362 copy._gallery_button_face_colour = self._gallery_button_face_colour 363 copy._gallery_button_hover_face_colour = self._gallery_button_hover_face_colour 364 copy._gallery_button_active_face_colour = self._gallery_button_active_face_colour 365 copy._gallery_button_disabled_face_colour = self._gallery_button_disabled_face_colour 366 367 copy._tab_ctrl_background_brush = self._tab_ctrl_background_brush 368 copy._panel_label_background_brush = self._panel_label_background_brush 369 copy._panel_hover_label_background_brush = self._panel_hover_label_background_brush 370 copy._panel_hover_button_background_brush = self._panel_hover_button_background_brush 371 copy._gallery_hover_background_brush = self._gallery_hover_background_brush 372 copy._gallery_button_background_top_brush = self._gallery_button_background_top_brush 373 copy._gallery_button_hover_background_top_brush = self._gallery_button_hover_background_top_brush 374 copy._gallery_button_active_background_top_brush = self._gallery_button_active_background_top_brush 375 copy._gallery_button_disabled_background_top_brush = self._gallery_button_disabled_background_top_brush 376 377 copy._tab_label_font = self._tab_label_font 378 copy._button_bar_label_font = self._button_bar_label_font 379 copy._panel_label_font = self._panel_label_font 380 381 copy._page_border_pen = self._page_border_pen 382 copy._panel_border_pen = self._panel_border_pen 383 copy._panel_border_gradient_pen = self._panel_border_gradient_pen 384 copy._panel_hover_button_border_pen = self._panel_hover_button_border_pen 385 copy._panel_minimised_border_pen = self._panel_minimised_border_pen 386 copy._panel_minimised_border_gradient_pen = self._panel_minimised_border_gradient_pen 387 copy._tab_border_pen = self._tab_border_pen 388 copy._gallery_border_pen = self._gallery_border_pen 389 copy._button_bar_hover_border_pen = self._button_bar_hover_border_pen 390 copy._button_bar_active_border_pen = self._button_bar_active_border_pen 391 copy._gallery_item_border_pen = self._gallery_item_border_pen 392 copy._toolbar_border_pen = self._toolbar_border_pen 393 394 copy._flags = self._flags 395 copy._tab_separation_size = self._tab_separation_size 396 copy._page_border_left = self._page_border_left 397 copy._page_border_top = self._page_border_top 398 copy._page_border_right = self._page_border_right 399 copy._page_border_bottom = self._page_border_bottom 400 copy._panel_x_separation_size = self._panel_x_separation_size 401 copy._panel_y_separation_size = self._panel_y_separation_size 402 copy._gallery_bitmap_padding_left_size = self._gallery_bitmap_padding_left_size 403 copy._gallery_bitmap_padding_right_size = self._gallery_bitmap_padding_right_size 404 copy._gallery_bitmap_padding_top_size = self._gallery_bitmap_padding_top_size 405 copy._gallery_bitmap_padding_bottom__size = self._gallery_bitmap_padding_bottom__size 406 407 408 def GetFlags(self): 409 """ 410 Get the previously set style flags. 411 """ 412 413 return self._flags 414 415 416 def SetFlags(self, flags): 417 """ 418 Set the style flags. 419 420 Normally called automatically by :meth:`RibbonBar.SetArtProvider() <lib.agw.ribbon.bar.RibbonBar.SetArtProvider>` with the ribbon 421 bar's style flags, so that the art provider has the same flags as the bar which 422 it is serving. 423 424 :param `flags`: MISSING DESCRIPTION. 425 426 """ 427 428 if (flags ^ self._flags) & RIBBON_BAR_FLOW_VERTICAL: 429 if flags & RIBBON_BAR_FLOW_VERTICAL: 430 self._page_border_left += 1 431 self._page_border_right += 1 432 self._page_border_top -= 1 433 self._page_border_bottom -= 1 434 else: 435 self._page_border_left -= 1 436 self._page_border_right -= 1 437 self._page_border_top += 1 438 self._page_border_bottom += 1 439 440 self._flags = flags 441 442 # Need to reload some bitmaps when flags change 443 self.Reload(RIBBON_ART_GALLERY_BUTTON_FACE_COLOUR) 444 self.Reload(RIBBON_ART_GALLERY_BUTTON_HOVER_FACE_COLOUR) 445 self.Reload(RIBBON_ART_GALLERY_BUTTON_ACTIVE_FACE_COLOUR) 446 self.Reload(RIBBON_ART_GALLERY_BUTTON_DISABLED_FACE_COLOUR) 447 self.Reload(RIBBON_ART_PANEL_BUTTON_FACE_COLOUR) 448 self.Reload(RIBBON_ART_PANEL_BUTTON_HOVER_FACE_COLOUR) 449 450 451 def Reload(self, setting): 452 453 self.SetColour(setting, self.GetColour(setting)) 454 455 456 def GetMetric(self, id): 457 """ 458 Get the value of a certain integer setting. 459 460 can be one of the size values of `RibbonArtSetting`. 461 462 :param `id`: a metric id. 463 464 """ 465 466 if id == RIBBON_ART_TAB_SEPARATION_SIZE: 467 return self._tab_separation_size 468 elif id == RIBBON_ART_PAGE_BORDER_LEFT_SIZE: 469 return self._page_border_left 470 elif id == RIBBON_ART_PAGE_BORDER_TOP_SIZE: 471 return self._page_border_top 472 elif id == RIBBON_ART_PAGE_BORDER_RIGHT_SIZE: 473 return self._page_border_right 474 elif id == RIBBON_ART_PAGE_BORDER_BOTTOM_SIZE: 475 return self._page_border_bottom 476 elif id == RIBBON_ART_PANEL_X_SEPARATION_SIZE: 477 return self._panel_x_separation_size 478 elif id == RIBBON_ART_PANEL_Y_SEPARATION_SIZE: 479 return self._panel_y_separation_size 480 elif id == RIBBON_ART_TOOL_GROUP_SEPARATION_SIZE: 481 return self._tool_group_separation_size 482 elif id == RIBBON_ART_GALLERY_BITMAP_PADDING_LEFT_SIZE: 483 return self._gallery_bitmap_padding_left_size 484 elif id == RIBBON_ART_GALLERY_BITMAP_PADDING_RIGHT_SIZE: 485 return self._gallery_bitmap_padding_right_size 486 elif id == RIBBON_ART_GALLERY_BITMAP_PADDING_TOP_SIZE: 487 return self._gallery_bitmap_padding_top_size 488 elif id == RIBBON_ART_GALLERY_BITMAP_PADDING_BOTTOM_SIZE: 489 return self._gallery_bitmap_padding_bottom__size 490 else: 491 raise Exception("Invalid Metric Ordinal") 492 493 494 def SetMetric(self, id, new_val): 495 """ 496 Set the value of a certain integer setting to the value. 497 498 can be one of the size values of `RibbonArtSetting`. 499 500 :param `id`: a metric id; 501 :param `new_val`: the new value of the metric setting. 502 503 """ 504 505 if id == RIBBON_ART_TAB_SEPARATION_SIZE: 506 self._tab_separation_size = new_val 507 elif id == RIBBON_ART_PAGE_BORDER_LEFT_SIZE: 508 self._page_border_left = new_val 509 elif id == RIBBON_ART_PAGE_BORDER_TOP_SIZE: 510 self._page_border_top = new_val 511 elif id == RIBBON_ART_PAGE_BORDER_RIGHT_SIZE: 512 self._page_border_right = new_val 513 elif id == RIBBON_ART_PAGE_BORDER_BOTTOM_SIZE: 514 self._page_border_bottom = new_val 515 elif id == RIBBON_ART_PANEL_X_SEPARATION_SIZE: 516 self._panel_x_separation_size = new_val 517 elif id == RIBBON_ART_PANEL_Y_SEPARATION_SIZE: 518 self._panel_y_separation_size = new_val 519 elif id == RIBBON_ART_TOOL_GROUP_SEPARATION_SIZE: 520 self._tool_group_separation_size = new_val 521 elif id == RIBBON_ART_GALLERY_BITMAP_PADDING_LEFT_SIZE: 522 self._gallery_bitmap_padding_left_size = new_val 523 elif id == RIBBON_ART_GALLERY_BITMAP_PADDING_RIGHT_SIZE: 524 self._gallery_bitmap_padding_right_size = new_val 525 elif id == RIBBON_ART_GALLERY_BITMAP_PADDING_TOP_SIZE: 526 self._gallery_bitmap_padding_top_size = new_val 527 elif id == RIBBON_ART_GALLERY_BITMAP_PADDING_BOTTOM_SIZE: 528 self._gallery_bitmap_padding_bottom__size = new_val 529 else: 530 raise Exception("Invalid Metric Ordinal") 531 532 533 def SetFont(self, id, font): 534 """ 535 Set the value of a certain font setting to the value. 536 537 can be one of the font values of `RibbonArtSetting`. 538 539 :param `id`: a font id; 540 :param `font`: the new font. 541 542 """ 543 544 if id == RIBBON_ART_TAB_LABEL_FONT: 545 self._tab_label_font = font 546 elif id == RIBBON_ART_BUTTON_BAR_LABEL_FONT: 547 self._button_bar_label_font = font 548 elif id == RIBBON_ART_PANEL_LABEL_FONT: 549 self._panel_label_font = font 550 else: 551 raise Exception("Invalid Font Ordinal") 552 553 554 def GetFont(self, id): 555 """ 556 Get the value of a certain font setting. 557 558 can be one of the font values of `RibbonArtSetting`. 559 560 :param `id`: the font id. 561 562 """ 563 564 if id == RIBBON_ART_TAB_LABEL_FONT: 565 return self._tab_label_font 566 elif id == RIBBON_ART_BUTTON_BAR_LABEL_FONT: 567 return self._button_bar_label_font 568 elif id == RIBBON_ART_PANEL_LABEL_FONT: 569 return self._panel_label_font 570 else: 571 raise Exception("Invalid Font Ordinal") 572 573 574 def GetColour(self, id): 575 """ 576 Get the value of a certain colour setting. 577 578 can be one of the colour values of `RibbonArtSetting`. 579 580 :param `id`: the colour id. 581 582 """ 583 584 if id == RIBBON_ART_BUTTON_BAR_LABEL_COLOUR: 585 return self._button_bar_label_colour 586 elif id == RIBBON_ART_BUTTON_BAR_HOVER_BORDER_COLOUR: 587 return self._button_bar_hover_border_pen.GetColour() 588 elif id == RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_TOP_COLOUR: 589 return self._button_bar_hover_background_top_colour 590 elif id == RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR: 591 return self._button_bar_hover_background_top_gradient_colour 592 elif id == RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_COLOUR: 593 return self._button_bar_hover_background_colour 594 elif id == RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_GRADIENT_COLOUR: 595 return self._button_bar_hover_background_gradient_colour 596 elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BORDER_COLOUR: 597 return self._button_bar_active_border_pen.GetColour() 598 elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_TOP_COLOUR: 599 return self._button_bar_active_background_top_colour 600 elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR: 601 return self._button_bar_active_background_top_gradient_colour 602 elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_COLOUR: 603 return self._button_bar_active_background_colour 604 elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_GRADIENT_COLOUR: 605 return self._button_bar_active_background_gradient_colour 606 elif id == RIBBON_ART_GALLERY_BORDER_COLOUR: 607 return self._gallery_border_pen.GetColour() 608 elif id == RIBBON_ART_GALLERY_HOVER_BACKGROUND_COLOUR: 609 return self._gallery_hover_background_brush.GetColour() 610 elif id == RIBBON_ART_GALLERY_BUTTON_BACKGROUND_COLOUR: 611 return self._gallery_button_background_colour 612 elif id == RIBBON_ART_GALLERY_BUTTON_BACKGROUND_GRADIENT_COLOUR: 613 return self._gallery_button_background_gradient_colour 614 elif id == RIBBON_ART_GALLERY_BUTTON_BACKGROUND_TOP_COLOUR: 615 return self._gallery_button_background_top_brush.GetColour() 616 elif id == RIBBON_ART_GALLERY_BUTTON_FACE_COLOUR: 617 return self._gallery_button_face_colour 618 elif id == RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_COLOUR: 619 return self._gallery_button_hover_background_colour 620 elif id == RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_GRADIENT_COLOUR: 621 return self._gallery_button_hover_background_gradient_colour 622 elif id == RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_TOP_COLOUR: 623 return self._gallery_button_hover_background_top_brush.GetColour() 624 elif id == RIBBON_ART_GALLERY_BUTTON_HOVER_FACE_COLOUR: 625 return self._gallery_button_face_colour 626 elif id == RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_COLOUR: 627 return self._gallery_button_active_background_colour 628 elif id == RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_GRADIENT_COLOUR: 629 return self._gallery_button_active_background_gradient_colour 630 elif id == RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_TOP_COLOUR: 631 return self._gallery_button_background_top_brush.GetColour() 632 elif id == RIBBON_ART_GALLERY_BUTTON_ACTIVE_FACE_COLOUR: 633 return self._gallery_button_active_face_colour 634 elif id == RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_COLOUR: 635 return self._gallery_button_disabled_background_colour 636 elif id == RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_GRADIENT_COLOUR: 637 return self._gallery_button_disabled_background_gradient_colour 638 elif id == RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_TOP_COLOUR: 639 return self._gallery_button_disabled_background_top_brush.GetColour() 640 elif id == RIBBON_ART_GALLERY_BUTTON_DISABLED_FACE_COLOUR: 641 return self._gallery_button_disabled_face_colour 642 elif id == RIBBON_ART_GALLERY_ITEM_BORDER_COLOUR: 643 return self._gallery_item_border_pen.GetColour() 644 elif id in [RIBBON_ART_TAB_CTRL_BACKGROUND_COLOUR, RIBBON_ART_TAB_CTRL_BACKGROUND_GRADIENT_COLOUR]: 645 return self._tab_ctrl_background_brush.GetColour() 646 elif id == RIBBON_ART_TAB_LABEL_COLOUR: 647 return self._tab_label_colour 648 elif id == RIBBON_ART_TAB_SEPARATOR_COLOUR: 649 return self._tab_separator_colour 650 elif id == RIBBON_ART_TAB_SEPARATOR_GRADIENT_COLOUR: 651 return self._tab_separator_gradient_colour 652 elif id in [RIBBON_ART_TAB_ACTIVE_BACKGROUND_TOP_COLOUR, RIBBON_ART_TAB_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR]: 653 return wx.Colour(0, 0, 0) 654 elif id == RIBBON_ART_TAB_ACTIVE_BACKGROUND_COLOUR: 655 return self._tab_active_background_colour 656 elif id == RIBBON_ART_TAB_ACTIVE_BACKGROUND_GRADIENT_COLOUR: 657 return self._tab_active_background_gradient_colour 658 elif id == RIBBON_ART_TAB_HOVER_BACKGROUND_TOP_COLOUR: 659 return self._tab_hover_background_top_colour 660 elif id == RIBBON_ART_TAB_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR: 661 return self._tab_hover_background_top_gradient_colour 662 elif id == RIBBON_ART_TAB_HOVER_BACKGROUND_COLOUR: 663 return self._tab_hover_background_colour 664 elif id == RIBBON_ART_TAB_HOVER_BACKGROUND_GRADIENT_COLOUR: 665 return self._tab_hover_background_gradient_colour 666 elif id == RIBBON_ART_TAB_BORDER_COLOUR: 667 return self._tab_border_pen.GetColour() 668 elif id == RIBBON_ART_PANEL_BORDER_COLOUR: 669 return self._panel_border_pen.GetColour() 670 elif id == RIBBON_ART_PANEL_BORDER_GRADIENT_COLOUR: 671 return self._panel_border_gradient_pen.GetColour() 672 elif id == RIBBON_ART_PANEL_MINIMISED_BORDER_COLOUR: 673 return self._panel_minimised_border_pen.GetColour() 674 elif id == RIBBON_ART_PANEL_MINIMISED_BORDER_GRADIENT_COLOUR: 675 return self._panel_minimised_border_gradient_pen.GetColour() 676 elif id in [RIBBON_ART_PANEL_LABEL_BACKGROUND_COLOUR, RIBBON_ART_PANEL_LABEL_BACKGROUND_GRADIENT_COLOUR]: 677 return self._panel_label_background_brush.GetColour() 678 elif id == RIBBON_ART_PANEL_LABEL_COLOUR: 679 return self._panel_label_colour 680 elif id == RIBBON_ART_PANEL_MINIMISED_LABEL_COLOUR: 681 return self._panel_minimised_label_colour 682 elif id in [RIBBON_ART_PANEL_HOVER_LABEL_BACKGROUND_COLOUR, RIBBON_ART_PANEL_HOVER_LABEL_BACKGROUND_GRADIENT_COLOUR]: 683 return self._panel_hover_label_background_brush.GetColour() 684 elif id == RIBBON_ART_PANEL_HOVER_LABEL_COLOUR: 685 return self._panel_hover_label_colour 686 elif id == RIBBON_ART_PANEL_ACTIVE_BACKGROUND_TOP_COLOUR: 687 return self._panel_active_background_top_colour 688 elif id == RIBBON_ART_PANEL_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR: 689 return self._panel_active_background_top_gradient_colour 690 elif id == RIBBON_ART_PANEL_ACTIVE_BACKGROUND_COLOUR: 691 return self._panel_active_background_colour 692 elif id == RIBBON_ART_PANEL_ACTIVE_BACKGROUND_GRADIENT_COLOUR: 693 return self._panel_active_background_gradient_colour 694 elif id == RIBBON_ART_PANEL_BUTTON_FACE_COLOUR: 695 return self._panel_button_face_colour 696 elif id == RIBBON_ART_PANEL_BUTTON_HOVER_FACE_COLOUR: 697 return self._panel_button_hover_face_colour 698 elif id == RIBBON_ART_PAGE_BORDER_COLOUR: 699 return self._page_border_pen.GetColour() 700 elif id == RIBBON_ART_PAGE_BACKGROUND_TOP_COLOUR: 701 return self._page_background_top_colour 702 elif id == RIBBON_ART_PAGE_BACKGROUND_TOP_GRADIENT_COLOUR: 703 return self._page_background_top_gradient_colour 704 elif id == RIBBON_ART_PAGE_BACKGROUND_COLOUR: 705 return self._page_background_colour 706 elif id == RIBBON_ART_PAGE_BACKGROUND_GRADIENT_COLOUR: 707 return self._page_background_gradient_colour 708 elif id == RIBBON_ART_PAGE_HOVER_BACKGROUND_TOP_COLOUR: 709 return self._page_hover_background_top_colour 710 elif id == RIBBON_ART_PAGE_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR: 711 return self._page_hover_background_top_gradient_colour 712 elif id == RIBBON_ART_PAGE_HOVER_BACKGROUND_COLOUR: 713 return self._page_hover_background_colour 714 elif id == RIBBON_ART_PAGE_HOVER_BACKGROUND_GRADIENT_COLOUR: 715 return self._page_hover_background_gradient_colour 716 elif id in [RIBBON_ART_TOOLBAR_BORDER_COLOUR, RIBBON_ART_TOOLBAR_HOVER_BORDER_COLOUR]: 717 return self._toolbar_border_pen.GetColour() 718 elif id == RIBBON_ART_TOOLBAR_FACE_COLOUR: 719 return self._tool_face_colour 720 else: 721 raise Exception("Invalid Colour Ordinal") 722 723 724 def SetColour(self, id, colour): 725 """ 726 Set the value of a certain colour setting to the value. 727 728 can be one of the colour values of `RibbonArtSetting`, though not all colour 729 settings will have an affect on every art provider. 730 731 :param `id`: the colour id; 732 :param `colour`: the colour. 733 734 :see: :meth:`~RibbonMSWArtProvider.SetColourScheme` 735 """ 736 737 if id == RIBBON_ART_BUTTON_BAR_LABEL_COLOUR: 738 self._button_bar_label_colour = colour 739 elif id == RIBBON_ART_BUTTON_BAR_HOVER_BORDER_COLOUR: 740 self._button_bar_hover_border_pen.SetColour(colour) 741 elif id == RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_TOP_COLOUR: 742 self._button_bar_hover_background_top_colour = colour 743 elif id == RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR: 744 self._button_bar_hover_background_top_gradient_colour = colour 745 elif id == RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_COLOUR: 746 self._button_bar_hover_background_colour = colour 747 elif id == RIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_GRADIENT_COLOUR: 748 self._button_bar_hover_background_gradient_colour = colour 749 elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BORDER_COLOUR: 750 self._button_bar_active_border_pen.SetColour(colour) 751 elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_TOP_COLOUR: 752 self._button_bar_active_background_top_colour = colour 753 elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR: 754 self._button_bar_active_background_top_gradient_colour = colour 755 elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_COLOUR: 756 self._button_bar_active_background_colour = colour 757 elif id == RIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_GRADIENT_COLOUR: 758 self._button_bar_active_background_gradient_colour = colour 759 elif id == RIBBON_ART_GALLERY_BORDER_COLOUR: 760 self._gallery_border_pen.SetColour(colour) 761 elif id == RIBBON_ART_GALLERY_HOVER_BACKGROUND_COLOUR: 762 self._gallery_hover_background_brush.SetColour(colour) 763 elif id == RIBBON_ART_GALLERY_BUTTON_BACKGROUND_COLOUR: 764 self._gallery_button_background_colour = colour 765 elif id == RIBBON_ART_GALLERY_BUTTON_BACKGROUND_GRADIENT_COLOUR: 766 self._gallery_button_background_gradient_colour = colour 767 elif id == RIBBON_ART_GALLERY_BUTTON_BACKGROUND_TOP_COLOUR: 768 self._gallery_button_background_top_brush.SetColour(colour) 769 elif id == RIBBON_ART_GALLERY_BUTTON_FACE_COLOUR: 770 self._gallery_button_face_colour = colour 771 772 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 773 self._gallery_up_bitmap[0] = RibbonLoadPixmap(gallery_left_xpm, colour) 774 self._gallery_down_bitmap[0] = RibbonLoadPixmap(gallery_right_xpm, colour) 775 else: 776 self._gallery_up_bitmap[0] = RibbonLoadPixmap(gallery_up_xpm, colour) 777 self._gallery_down_bitmap[0] = RibbonLoadPixmap(gallery_down_xpm, colour) 778 779 self._gallery_extension_bitmap[0] = RibbonLoadPixmap(gallery_extension_xpm, colour) 780 781 elif id == RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_COLOUR: 782 self._gallery_button_hover_background_colour = colour 783 elif id == RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_GRADIENT_COLOUR: 784 self._gallery_button_hover_background_gradient_colour = colour 785 elif id == RIBBON_ART_GALLERY_BUTTON_HOVER_BACKGROUND_TOP_COLOUR: 786 self._gallery_button_hover_background_top_brush.SetColour(colour) 787 elif id == RIBBON_ART_GALLERY_BUTTON_HOVER_FACE_COLOUR: 788 self._gallery_button_hover_face_colour = colour 789 790 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 791 self._gallery_up_bitmap[1] = RibbonLoadPixmap(gallery_left_xpm, colour) 792 self._gallery_down_bitmap[1] = RibbonLoadPixmap(gallery_right_xpm, colour) 793 else: 794 self._gallery_up_bitmap[1] = RibbonLoadPixmap(gallery_up_xpm, colour) 795 self._gallery_down_bitmap[1] = RibbonLoadPixmap(gallery_down_xpm, colour) 796 797 self._gallery_extension_bitmap[1] = RibbonLoadPixmap(gallery_extension_xpm, colour) 798 799 elif id == RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_COLOUR: 800 self._gallery_button_active_background_colour = colour 801 elif id == RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_GRADIENT_COLOUR: 802 self._gallery_button_active_background_gradient_colour = colour 803 elif id == RIBBON_ART_GALLERY_BUTTON_ACTIVE_BACKGROUND_TOP_COLOUR: 804 self._gallery_button_background_top_brush.SetColour(colour) 805 elif id == RIBBON_ART_GALLERY_BUTTON_ACTIVE_FACE_COLOUR: 806 self._gallery_button_active_face_colour = colour 807 808 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 809 self._gallery_up_bitmap[2] = RibbonLoadPixmap(gallery_left_xpm, colour) 810 self._gallery_down_bitmap[2] = RibbonLoadPixmap(gallery_right_xpm, colour) 811 else: 812 self._gallery_up_bitmap[2] = RibbonLoadPixmap(gallery_up_xpm, colour) 813 self._gallery_down_bitmap[2] = RibbonLoadPixmap(gallery_down_xpm, colour) 814 815 self._gallery_extension_bitmap[2] = RibbonLoadPixmap(gallery_extension_xpm, colour) 816 817 elif id == RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_COLOUR: 818 self._gallery_button_disabled_background_colour = colour 819 elif id == RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_GRADIENT_COLOUR: 820 self._gallery_button_disabled_background_gradient_colour = colour 821 elif id == RIBBON_ART_GALLERY_BUTTON_DISABLED_BACKGROUND_TOP_COLOUR: 822 self._gallery_button_disabled_background_top_brush.SetColour(colour) 823 elif id == RIBBON_ART_GALLERY_BUTTON_DISABLED_FACE_COLOUR: 824 self._gallery_button_disabled_face_colour = colour 825 826 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 827 self._gallery_up_bitmap[3] = RibbonLoadPixmap(gallery_left_xpm, colour) 828 self._gallery_down_bitmap[3] = RibbonLoadPixmap(gallery_right_xpm, colour) 829 else: 830 self._gallery_up_bitmap[3] = RibbonLoadPixmap(gallery_up_xpm, colour) 831 self._gallery_down_bitmap[3] = RibbonLoadPixmap(gallery_down_xpm, colour) 832 833 self._gallery_extension_bitmap[3] = RibbonLoadPixmap(gallery_extension_xpm, colour) 834 835 elif id == RIBBON_ART_GALLERY_ITEM_BORDER_COLOUR: 836 self._gallery_item_border_pen.SetColour(colour) 837 838 elif id in [RIBBON_ART_TAB_CTRL_BACKGROUND_COLOUR, RIBBON_ART_TAB_CTRL_BACKGROUND_GRADIENT_COLOUR]: 839 self._tab_ctrl_background_brush.SetColour(colour) 840 self._cached_tab_separator_visibility = -1.0 841 elif id == RIBBON_ART_TAB_LABEL_COLOUR: 842 self._tab_label_colour = colour 843 elif id == RIBBON_ART_TAB_SEPARATOR_COLOUR: 844 self._tab_separator_colour = colour 845 self._cached_tab_separator_visibility = -1.0 846 elif id == RIBBON_ART_TAB_SEPARATOR_GRADIENT_COLOUR: 847 self._tab_separator_gradient_colour = colour 848 self._cached_tab_separator_visibility = -1.0 849 elif id in [RIBBON_ART_TAB_ACTIVE_BACKGROUND_TOP_COLOUR, RIBBON_ART_TAB_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR]: 850 pass 851 elif id == RIBBON_ART_TAB_ACTIVE_BACKGROUND_COLOUR: 852 self._tab_active_background_colour = colour 853 elif id == RIBBON_ART_TAB_ACTIVE_BACKGROUND_GRADIENT_COLOUR: 854 self._tab_active_background_gradient_colour = colour 855 elif id == RIBBON_ART_TAB_HOVER_BACKGROUND_TOP_COLOUR: 856 self._tab_hover_background_top_colour = colour 857 elif id == RIBBON_ART_TAB_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR: 858 self._tab_hover_background_top_gradient_colour = colour 859 elif id == RIBBON_ART_TAB_HOVER_BACKGROUND_COLOUR: 860 self._tab_hover_background_colour = colour 861 elif id == RIBBON_ART_TAB_HOVER_BACKGROUND_GRADIENT_COLOUR: 862 self._tab_hover_background_gradient_colour = colour 863 elif id == RIBBON_ART_TAB_BORDER_COLOUR: 864 self._tab_border_pen.SetColour(colour) 865 elif id == RIBBON_ART_PANEL_BORDER_COLOUR: 866 self._panel_border_pen.SetColour(colour) 867 elif id == RIBBON_ART_PANEL_BORDER_GRADIENT_COLOUR: 868 self._panel_border_gradient_pen.SetColour(colour) 869 elif id == RIBBON_ART_PANEL_MINIMISED_BORDER_COLOUR: 870 self._panel_minimised_border_pen.SetColour(colour) 871 elif id == RIBBON_ART_PANEL_MINIMISED_BORDER_GRADIENT_COLOUR: 872 self._panel_minimised_border_gradient_pen.SetColour(colour) 873 elif id in [RIBBON_ART_PANEL_LABEL_BACKGROUND_COLOUR, RIBBON_ART_PANEL_LABEL_BACKGROUND_GRADIENT_COLOUR]: 874 self._panel_label_background_brush.SetColour(colour) 875 elif id == RIBBON_ART_PANEL_LABEL_COLOUR: 876 self._panel_label_colour = colour 877 elif id in [RIBBON_ART_PANEL_HOVER_LABEL_BACKGROUND_COLOUR, RIBBON_ART_PANEL_HOVER_LABEL_BACKGROUND_GRADIENT_COLOUR]: 878 self._panel_hover_label_background_brush.SetColour(colour) 879 elif id == RIBBON_ART_PANEL_HOVER_LABEL_COLOUR: 880 self._panel_hover_label_colour = colour 881 elif id == RIBBON_ART_PANEL_MINIMISED_LABEL_COLOUR: 882 self._panel_minimised_label_colour = colour 883 elif id == RIBBON_ART_PANEL_ACTIVE_BACKGROUND_TOP_COLOUR: 884 self._panel_active_background_top_colour = colour 885 elif id == RIBBON_ART_PANEL_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR: 886 self._panel_active_background_top_gradient_colour = colour 887 elif id == RIBBON_ART_PANEL_ACTIVE_BACKGROUND_COLOUR: 888 self._panel_active_background_colour = colour 889 elif id == RIBBON_ART_PANEL_ACTIVE_BACKGROUND_GRADIENT_COLOUR: 890 self._panel_active_background_gradient_colour = colour 891 elif id == RIBBON_ART_PANEL_BUTTON_FACE_COLOUR: 892 self._panel_button_face_colour = colour 893 self._panel_extension_bitmap[0] = RibbonLoadPixmap(panel_extension_xpm, colour) 894 elif id == RIBBON_ART_PANEL_BUTTON_HOVER_FACE_COLOUR: 895 self._panel_button_hover_face_colour = colour 896 self._panel_extension_bitmap[1] = RibbonLoadPixmap(panel_extension_xpm, colour) 897 elif id == RIBBON_ART_PAGE_BORDER_COLOUR: 898 self._page_border_pen.SetColour(colour) 899 elif id == RIBBON_ART_PAGE_BACKGROUND_TOP_COLOUR: 900 self._page_background_top_colour = colour 901 elif id == RIBBON_ART_PAGE_BACKGROUND_TOP_GRADIENT_COLOUR: 902 self._page_background_top_gradient_colour = colour 903 elif id == RIBBON_ART_PAGE_BACKGROUND_COLOUR: 904 self._page_background_colour = colour 905 elif id == RIBBON_ART_PAGE_BACKGROUND_GRADIENT_COLOUR: 906 self._page_background_gradient_colour = colour 907 elif id == RIBBON_ART_PAGE_HOVER_BACKGROUND_TOP_COLOUR: 908 self._page_hover_background_top_colour = colour 909 elif id == RIBBON_ART_PAGE_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR: 910 self._page_hover_background_top_gradient_colour = colour 911 elif id == RIBBON_ART_PAGE_HOVER_BACKGROUND_COLOUR: 912 self._page_hover_background_colour = colour 913 elif id == RIBBON_ART_PAGE_HOVER_BACKGROUND_GRADIENT_COLOUR: 914 self._page_hover_background_gradient_colour = colour 915 elif id in [RIBBON_ART_TOOLBAR_BORDER_COLOUR, RIBBON_ART_TOOLBAR_HOVER_BORDER_COLOUR]: 916 self._toolbar_border_pen.SetColour(colour) 917 elif id == RIBBON_ART_TOOLBAR_FACE_COLOUR: 918 self._tool_face_colour = colour 919 self._toolbar_drop_bitmap = RibbonLoadPixmap(gallery_down_xpm, colour) 920 else: 921 raise Exception("Invalid Colour Ordinal") 922 923 924 def DrawTabCtrlBackground(self, dc, wnd, rect): 925 """ 926 Draw the background of the tab region of a ribbon bar. 927 928 :param `dc`: The device context to draw onto; 929 :param `wnd`: The window which is being drawn onto; 930 :param `rect`: The rectangle within which to draw. 931 932 """ 933 934 dc.SetPen(wx.TRANSPARENT_PEN) 935 936 dc.SetBrush(self._tab_ctrl_background_brush) 937 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) 938 939 dc.SetPen(self._page_border_pen) 940 941 if rect.width > 6: 942 dc.DrawLine(rect.x + 3, rect.y + rect.height - 1, rect.x + rect.width - 3, rect.y + rect.height - 1) 943 else: 944 dc.DrawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width, rect.y + rect.height - 1) 945 946 947 def DrawTab(self, dc, wnd, tab): 948 """ 949 Draw a single tab in the tab region of a ribbon bar. 950 951 :param `dc`: The device context to draw onto; 952 :param `wnd`: The window which is being drawn onto (not the :class:`~wx.lib.agw.ribbon.page.RibbonPage` associated 953 with the tab being drawn); 954 :param `tab`: The rectangle within which to draw, and also the tab label, icon, and 955 state (active and/or hovered). The drawing rectangle will be entirely within a 956 rectangle on the same device context previously painted with :meth:`~RibbonMSWArtProvider.DrawTabCtrlBackground`. 957 The rectangle's width will be at least the minimum value returned by :meth:`~RibbonMSWArtProvider.GetBarTabWidth`, 958 and height will be the value returned by :meth:`~RibbonMSWArtProvider.GetTabCtrlHeight`. 959 960 """ 961 962 if tab.rect.height <= 2: 963 return 964 965 if tab.active or tab.hovered: 966 if tab.active: 967 background = wx.Rect(*tab.rect) 968 background.x += 2 969 background.y += 2 970 background.width -= 4 971 background.height -= 2 972 973 dc.GradientFillLinear(background, self._tab_active_background_colour, 974 self._tab_active_background_gradient_colour, wx.SOUTH) 975 976 # TODO: active and hovered 977 978 elif tab.hovered: 979 background = wx.Rect(*tab.rect) 980 background.x += 2 981 background.y += 2 982 background.width -= 4 983 background.height -= 3 984 h = background.height 985 background.height /= 2 986 dc.GradientFillLinear(background, self._tab_hover_background_top_colour, 987 self._tab_hover_background_top_gradient_colour, wx.SOUTH) 988 989 background.y += background.height 990 background.height = h - background.height 991 dc.GradientFillLinear(background, self._tab_hover_background_colour, 992 self._tab_hover_background_gradient_colour, wx.SOUTH) 993 994 border_points = [wx.Point() for i in range(6)] 995 border_points[0] = wx.Point(1, tab.rect.height - 2) 996 border_points[1] = wx.Point(1, 3) 997 border_points[2] = wx.Point(3, 1) 998 border_points[3] = wx.Point(tab.rect.width - 4, 1) 999 border_points[4] = wx.Point(tab.rect.width - 2, 3) 1000 border_points[5] = wx.Point(tab.rect.width - 2, tab.rect.height - 1) 1001 1002 dc.SetPen(self._tab_border_pen) 1003 dc.DrawLines(border_points, tab.rect.x, tab.rect.y) 1004 1005 if tab.active: 1006 # Give the tab a curved outward border at the bottom 1007 dc.DrawPoint(tab.rect.x, tab.rect.y + tab.rect.height - 2) 1008 dc.DrawPoint(tab.rect.x + tab.rect.width - 1, tab.rect.y + tab.rect.height - 2) 1009 1010 p = wx.Pen(self._tab_active_background_gradient_colour) 1011 dc.SetPen(p) 1012 1013 # Technically the first two points are the wrong colour, but they're near enough 1014 dc.DrawPoint(tab.rect.x + 1, tab.rect.y + tab.rect.height - 2) 1015 dc.DrawPoint(tab.rect.x + tab.rect.width - 2, tab.rect.y + tab.rect.height - 2) 1016 dc.DrawPoint(tab.rect.x + 1, tab.rect.y + tab.rect.height - 1) 1017 dc.DrawPoint(tab.rect.x, tab.rect.y + tab.rect.height - 1) 1018 dc.DrawPoint(tab.rect.x + tab.rect.width - 2, tab.rect.y + tab.rect.height - 1) 1019 dc.DrawPoint(tab.rect.x + tab.rect.width - 1, tab.rect.y + tab.rect.height - 1) 1020 1021 if self._flags & RIBBON_BAR_SHOW_PAGE_ICONS: 1022 icon = tab.page.GetIcon() 1023 1024 if icon.IsOk(): 1025 x = tab.rect.x + 4 1026 if self._flags & RIBBON_BAR_SHOW_PAGE_LABELS == 0: 1027 x = tab.rect.x + (tab.rect.width - icon.GetWidth()) / 2 1028 1029 dc.DrawBitmap(icon, x, tab.rect.y + 1 + (tab.rect.height - 1 - icon.GetHeight()) / 2, True) 1030 1031 if self._flags & RIBBON_BAR_SHOW_PAGE_LABELS: 1032 label = tab.page.GetLabel() 1033 if label.strip(): 1034 dc.SetFont(self._tab_label_font) 1035 dc.SetTextForeground(self._tab_label_colour) 1036 dc.SetBackgroundMode(wx.TRANSPARENT) 1037 1038 text_width, text_height = dc.GetTextExtent(label) 1039 width = tab.rect.width - 5 1040 x = tab.rect.x + 3 1041 1042 if self._flags & RIBBON_BAR_SHOW_PAGE_ICONS: 1043 x += 3 + tab.page.GetIcon().GetWidth() 1044 width -= 3 + tab.page.GetIcon().GetWidth() 1045 1046 y = tab.rect.y + (tab.rect.height - text_height) / 2 1047 1048 if width <= text_width: 1049 dc.SetClippingRegion(x, tab.rect.y, width, tab.rect.height) 1050 dc.DrawText(label, x, y) 1051 else: 1052 dc.DrawText(label, x + (width - text_width) / 2 + 1, y) 1053 1054 1055 def DrawTabSeparator(self, dc, wnd, rect, visibility): 1056 """ 1057 Draw a separator between two tabs in a ribbon bar. 1058 1059 :param `dc`: The device context to draw onto; 1060 :param `wnd`: The window which is being drawn onto; 1061 :param `rect`: The rectangle within which to draw, which will be entirely 1062 within a rectangle on the same device context previously painted with 1063 :meth:`~RibbonMSWArtProvider.DrawTabCtrlBackground`; 1064 :param `visibility`: The opacity with which to draw the separator. Values 1065 are in the range [0, 1], with 0 being totally transparent, and 1 being totally 1066 opaque. 1067 1068 """ 1069 1070 if visibility <= 0.0: 1071 return 1072 1073 if visibility > 1.0: 1074 visibility = 1.0 1075 1076 # The tab separator is relatively expensive to draw (for its size), and is 1077 # usually drawn multiple times sequentially (in different positions), so it 1078 # makes sense to draw it once and cache it. 1079 if not self._cached_tab_separator.IsOk() or self._cached_tab_separator.GetSize() != rect.GetSize() or \ 1080 visibility != self._cached_tab_separator_visibility: 1081 1082 size = wx.Rect(0, 0, *rect.GetSize()) 1083 self.ReallyDrawTabSeparator(wnd, size, visibility) 1084 1085 dc.DrawBitmap(self._cached_tab_separator, rect.x, rect.y, False) 1086 1087 1088 def ReallyDrawTabSeparator(self, wnd, rect, visibility): 1089 1090 if not self._cached_tab_separator.IsOk() or self._cached_tab_separator.GetSize() != rect.GetSize(): 1091 self._cached_tab_separator = wx.Bitmap(*rect.GetSize()) 1092 1093 dc = wx.MemoryDC(self._cached_tab_separator) 1094 self.DrawTabCtrlBackground(dc, wnd, rect) 1095 1096 x = rect.x + rect.width / 2 1097 h = float(rect.height - 1) 1098 1099 r1 = self._tab_ctrl_background_brush.GetColour().Red() * (1.0 - visibility) + 0.5 1100 g1 = self._tab_ctrl_background_brush.GetColour().Green() * (1.0 - visibility) + 0.5 1101 b1 = self._tab_ctrl_background_brush.GetColour().Blue() * (1.0 - visibility) + 0.5 1102 r2 = self._tab_separator_colour.Red() 1103 g2 = self._tab_separator_colour.Green() 1104 b2 = self._tab_separator_colour.Blue() 1105 r3 = self._tab_separator_gradient_colour.Red() 1106 g3 = self._tab_separator_gradient_colour.Green() 1107 b3 = self._tab_separator_gradient_colour.Blue() 1108 1109 for i in range(rect.height-1): 1110 1111 p = float(i)/h 1112 1113 r = int((p * r3 + (1.0 - p) * r2) * visibility + r1) 1114 g = int((p * g3 + (1.0 - p) * g2) * visibility + g1) 1115 b = int((p * b3 + (1.0 - p) * b2) * visibility + b1) 1116 1117 P = wx.Pen(wx.Colour(r, g, b)) 1118 dc.SetPen(P) 1119 dc.DrawPoint(x, rect.y + i) 1120 1121 self._cached_tab_separator_visibility = visibility 1122 1123 1124 def DrawPartialPageBackground(self, dc, wnd, rect, allow_hovered_or_page=True, offset=None, hovered=False): 1125 1126 if isinstance(allow_hovered_or_page, bool): 1127 self.DrawPartialPageBackground2(dc, wnd, rect, allow_hovered_or_page) 1128 else: 1129 self.DrawPartialPageBackground1(dc, wnd, rect, allow_hovered_or_page, offset, hovered) 1130 1131 1132 def DrawPartialPageBackground1(self, dc, wnd, rect, page, offset, hovered=False): 1133 1134 background = wx.Rect(0, 0, *page.GetSize()) 1135 background = page.AdjustRectToIncludeScrollButtons(background) 1136 background.height -= 2 1137 1138 # Page background isn't dependant upon the width of the page 1139 # (at least not the part of it intended to be painted by this 1140 # function). Set to wider than the page itself for when externally 1141 # expanded panels need a background - the expanded panel can be wider 1142 # than the bar. 1143 1144 background.x = 0 1145 background.width = 10000 1146 1147 # upper_rect, lower_rect, paint_rect are all in page co-ordinates 1148 upper_rect = wx.Rect(*background) 1149 upper_rect.height /= 5 1150 1151 lower_rect = wx.Rect(*background) 1152 lower_rect.y += upper_rect.height 1153 lower_rect.height -= upper_rect.height 1154 1155 paint_rect = wx.Rect(*rect) 1156 paint_rect.x += offset.x 1157 paint_rect.y += offset.y 1158 1159 if hovered: 1160 bg_top = self._page_hover_background_top_colour 1161 bg_top_grad = self._page_hover_background_top_gradient_colour 1162 bg_btm = self._page_hover_background_colour 1163 bg_btm_grad = self._page_hover_background_gradient_colour 1164 else: 1165 bg_top = self._page_background_top_colour 1166 bg_top_grad = self._page_background_top_gradient_colour 1167 bg_btm = self._page_background_colour 1168 bg_btm_grad = self._page_background_gradient_colour 1169 1170 if paint_rect.Intersects(upper_rect): 1171 rect = wx.Rect(*upper_rect) 1172 rect.Intersect(paint_rect) 1173 rect.x -= offset.x 1174 rect.y -= offset.y 1175 starting_colour = RibbonInterpolateColour(bg_top, bg_top_grad, 1176 paint_rect.y, upper_rect.y, 1177 upper_rect.y + upper_rect.height) 1178 ending_colour = RibbonInterpolateColour(bg_top, bg_top_grad, 1179 paint_rect.y + paint_rect.height, upper_rect.y, 1180 upper_rect.y + upper_rect.height) 1181 dc.GradientFillLinear(rect, starting_colour, ending_colour, wx.SOUTH) 1182 1183 1184 if paint_rect.Intersects(lower_rect): 1185 rect = wx.Rect(*lower_rect) 1186 rect.Intersect(paint_rect) 1187 rect.x -= offset.x 1188 rect.y -= offset.y 1189 starting_colour = RibbonInterpolateColour(bg_btm, bg_btm_grad, 1190 paint_rect.y, lower_rect.y, 1191 lower_rect.y + lower_rect.height) 1192 ending_colour = RibbonInterpolateColour(bg_btm, bg_btm_grad, 1193 paint_rect.y + paint_rect.height, 1194 lower_rect.y, lower_rect.y + lower_rect.height) 1195 1196 dc.GradientFillLinear(rect, starting_colour, ending_colour, wx.SOUTH) 1197 1198 1199 def DrawPageBackground(self, dc, wnd, rect): 1200 """ 1201 Draw the background of a ribbon page. 1202 1203 :param `dc`: The device context to draw onto; 1204 :param `wnd`: The window which is being drawn onto (which is commonly the 1205 :class:`~wx.lib.agw.ribbon.page.RibbonPage` whose background is being drawn, but doesn't have to be); 1206 :param `rect`: The rectangle within which to draw. 1207 1208 :see: :meth:`~RibbonMSWArtProvider.GetPageBackgroundRedrawArea` 1209 """ 1210 1211 dc.SetPen(wx.TRANSPARENT_PEN) 1212 dc.SetBrush(self._tab_ctrl_background_brush) 1213 1214 edge = wx.Rect(*rect) 1215 1216 edge.width = 2 1217 dc.DrawRectangle(edge.x, edge.y, edge.width, edge.height) 1218 1219 edge.x += rect.width - 2 1220 dc.DrawRectangle(edge.x, edge.y, edge.width, edge.height) 1221 1222 edge = wx.Rect(*rect) 1223 edge.height = 2 1224 edge.y += (rect.height - edge.height) 1225 dc.DrawRectangle(edge.x, edge.y, edge.width, edge.height) 1226 1227 background = wx.Rect(*rect) 1228 background.x += 2 1229 background.width -= 4 1230 background.height -= 2 1231 1232 background.height /= 5 1233 dc.GradientFillLinear(background, self._page_background_top_colour, 1234 self._page_background_top_gradient_colour, wx.SOUTH) 1235 1236 background.y += background.height 1237 background.height = rect.height - 2 - background.height 1238 dc.GradientFillLinear(background, self._page_background_colour, 1239 self._page_background_gradient_colour, wx.SOUTH) 1240 1241 border_points = [wx.Point() for i in range(8)] 1242 border_points[0] = wx.Point(2, 0) 1243 border_points[1] = wx.Point(1, 1) 1244 border_points[2] = wx.Point(1, rect.height - 4) 1245 border_points[3] = wx.Point(3, rect.height - 2) 1246 border_points[4] = wx.Point(rect.width - 4, rect.height - 2) 1247 border_points[5] = wx.Point(rect.width - 2, rect.height - 4) 1248 border_points[6] = wx.Point(rect.width - 2, 1) 1249 border_points[7] = wx.Point(rect.width - 4, -1) 1250 1251 dc.SetPen(self._page_border_pen) 1252 dc.DrawLines(border_points, rect.x, rect.y) 1253 1254 1255 def DrawScrollButton(self, dc, wnd, rect_, style): 1256 """ 1257 Draw a ribbon-style scroll button. 1258 1259 :param `dc`: The device context to draw onto; 1260 :param `wnd`: The window which is being drawn onto; 1261 :param `rect`: The rectangle within which to draw. The size of this rectangle 1262 will be at least the size returned by :meth:`~RibbonMSWArtProvider.GetScrollButtonMinimumSize` for a 1263 scroll button with the same style. For tab scroll buttons, this rectangle 1264 will be entirely within a rectangle on the same device context previously 1265 painted with :meth:`~RibbonMSWArtProvider.DrawTabCtrlBackground`, but this is not guaranteed for other 1266 types of button (for example, page scroll buttons will not be painted on an 1267 area previously painted with :meth:`~RibbonMSWArtProvider.DrawPageBackground` ); 1268 :param `style`: A combination of flags from `RibbonScrollButtonStyle`, 1269 including a direction, a for flag, and one or more states. 1270 1271 """ 1272 1273 rect = wx.Rect(*rect_) 1274 1275 if (style & RIBBON_SCROLL_BTN_FOR_MASK) == RIBBON_SCROLL_BTN_FOR_PAGE: 1276 1277 # Page scroll buttons do not have the luxury of rendering on top of anything 1278 # else, and their size includes some padding, hence the background painting 1279 # and size adjustment. 1280 dc.SetPen(wx.TRANSPARENT_PEN) 1281 dc.SetBrush(self._tab_ctrl_background_brush) 1282 dc.DrawRectangle(rect) 1283 dc.SetClippingRegion(rect) 1284 1285 result = style & RIBBON_SCROLL_BTN_DIRECTION_MASK 1286 1287 if result == RIBBON_SCROLL_BTN_LEFT: 1288 rect.x += 1 1289 elif result == RIBBON_SCROLL_BTN_RIGHT: 1290 rect.y -= 1 1291 rect.width -= 1 1292 elif result == RIBBON_SCROLL_BTN_UP: 1293 rect.x += 1 1294 rect.y -= 1 1295 rect.width -= 2 1296 rect.height += 1 1297 elif result == RIBBON_SCROLL_BTN_DOWN: 1298 rect.x += 1 1299 rect.width -= 2 1300 rect.height -= 1 1301 1302 background = wx.Rect(*rect) 1303 background.x += 1 1304 background.y += 1 1305 background.width -= 2 1306 background.height -= 2 1307 1308 if style & RIBBON_SCROLL_BTN_UP: 1309 background.height /= 2 1310 else: 1311 background.height /= 5 1312 1313 dc.GradientFillLinear(background, self._page_background_top_colour, 1314 self._page_background_top_gradient_colour, wx.SOUTH) 1315 1316 background.y += background.height 1317 background.height = rect.height - 2 - background.height 1318 dc.GradientFillLinear(background, self._page_background_colour, 1319 self._page_background_gradient_colour, wx.SOUTH) 1320 1321 border_points = [wx.Point() for i in range(7)] 1322 result = style & RIBBON_SCROLL_BTN_DIRECTION_MASK 1323 1324 if result == RIBBON_SCROLL_BTN_LEFT: 1325 border_points[0] = wx.Point(2, 0) 1326 border_points[1] = wx.Point(rect.width - 1, 0) 1327 border_points[2] = wx.Point(rect.width - 1, rect.height - 1) 1328 border_points[3] = wx.Point(2, rect.height - 1) 1329 border_points[4] = wx.Point(0, rect.height - 3) 1330 border_points[5] = wx.Point(0, 2) 1331 1332 elif result == RIBBON_SCROLL_BTN_RIGHT: 1333 border_points[0] = wx.Point(0, 0) 1334 border_points[1] = wx.Point(rect.width - 3, 0) 1335 border_points[2] = wx.Point(rect.width - 1, 2) 1336 border_points[3] = wx.Point(rect.width - 1, rect.height - 3) 1337 border_points[4] = wx.Point(rect.width - 3, rect.height - 1) 1338 border_points[5] = wx.Point(0, rect.height - 1) 1339 1340 elif result == RIBBON_SCROLL_BTN_UP: 1341 border_points[0] = wx.Point(2, 0) 1342 border_points[1] = wx.Point(rect.width - 3, 0) 1343 border_points[2] = wx.Point(rect.width - 1, 2) 1344 border_points[3] = wx.Point(rect.width - 1, rect.height - 1) 1345 border_points[4] = wx.Point(0, rect.height - 1) 1346 border_points[5] = wx.Point(0, 2) 1347 1348 elif result == RIBBON_SCROLL_BTN_DOWN: 1349 border_points[0] = wx.Point(0, 0) 1350 border_points[1] = wx.Point(rect.width - 1, 0) 1351 border_points[2] = wx.Point(rect.width - 1, rect.height - 3) 1352 border_points[3] = wx.Point(rect.width - 3, rect.height - 1) 1353 border_points[4] = wx.Point(2, rect.height - 1) 1354 border_points[5] = wx.Point(0, rect.height - 3) 1355 1356 border_points[6] = border_points[0] 1357 1358 dc.SetPen(self._page_border_pen) 1359 dc.DrawLines(border_points, rect.x, rect.y) 1360 1361 # NB: Code for handling hovered/active state is temporary 1362 arrow_points = [wx.Point() for i in range(3)] 1363 result = style & RIBBON_SCROLL_BTN_DIRECTION_MASK 1364 1365 if result == RIBBON_SCROLL_BTN_LEFT: 1366 arrow_points[0] = wx.Point(rect.width / 2 - 2, rect.height / 2) 1367 if style & RIBBON_SCROLL_BTN_ACTIVE: 1368 arrow_points[0].y += 1 1369 arrow_points[1] = arrow_points[0] + wx.Point(3, -3) 1370 arrow_points[2] = arrow_points[0] + wx.Point(3, 3) 1371 1372 elif result == RIBBON_SCROLL_BTN_RIGHT: 1373 arrow_points[0] = wx.Point(rect.width / 2 + 2, rect.height / 2) 1374 if style & RIBBON_SCROLL_BTN_ACTIVE: 1375 arrow_points[0].y += 1 1376 arrow_points[1] = arrow_points[0] - wx.Point(3, 3) 1377 arrow_points[2] = arrow_points[0] - wx.Point(3, -3) 1378 1379 elif result == RIBBON_SCROLL_BTN_UP: 1380 arrow_points[0] = wx.Point(rect.width / 2, rect.height / 2 - 2) 1381 if style & RIBBON_SCROLL_BTN_ACTIVE: 1382 arrow_points[0].y += 1 1383 arrow_points[1] = arrow_points[0] + wx.Point( 3, 3) 1384 arrow_points[2] = arrow_points[0] + wx.Point(-3, 3) 1385 1386 elif result == RIBBON_SCROLL_BTN_DOWN: 1387 arrow_points[0] = wx.Point(rect.width / 2, rect.height / 2 + 2) 1388 if style & RIBBON_SCROLL_BTN_ACTIVE: 1389 arrow_points[0].y += 1 1390 arrow_points[1] = arrow_points[0] - wx.Point( 3, 3) 1391 arrow_points[2] = arrow_points[0] - wx.Point(-3, 3) 1392 1393 dc.SetPen(wx.TRANSPARENT_PEN) 1394 B = wx.Brush((style & RIBBON_SCROLL_BTN_HOVERED and [self._tab_active_background_colour] or [self._tab_label_colour])[0]) 1395 dc.SetBrush(B) 1396 dc.DrawPolygon(arrow_points, rect.x, rect.y) 1397 1398 1399 def DrawDropdownArrow(self, dc, x, y, colour): 1400 1401 arrow_points = [wx.Point() for i in range(3)] 1402 brush = wx.Brush(colour) 1403 arrow_points[0] = wx.Point(1, 2) 1404 arrow_points[1] = arrow_points[0] + wx.Point(-3, -3) 1405 arrow_points[2] = arrow_points[0] + wx.Point( 3, -3) 1406 dc.SetPen(wx.TRANSPARENT_PEN) 1407 dc.SetBrush(brush) 1408 dc.DrawPolygon(arrow_points, x, y) 1409 1410 1411 def RemovePanelPadding(self, rect): 1412 1413 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 1414 rect.y += 1 1415 rect.height -= 2 1416 else: 1417 rect.x += 1 1418 rect.width -= 2 1419 1420 return rect 1421 1422 1423 def DrawPanelBackground(self, dc, wnd, rect): 1424 """ 1425 Draw the background and chrome for a ribbon panel. 1426 1427 This should draw the border, background, label, and any other items of a panel 1428 which are outside the client area of a panel. Note that when a panel is 1429 minimised, this function is not called - only :meth:`~RibbonMSWArtProvider.DrawMinimisedPanel` is called, 1430 so a background should be explicitly painted by that if required. 1431 1432 :param `dc`: The device context to draw onto; 1433 :param `wnd`: The window which is being drawn onto, which is always the panel 1434 whose background and chrome is being drawn. The panel label and other panel 1435 attributes can be obtained by querying this; 1436 :param `rect`: The rectangle within which to draw. 1437 1438 """ 1439 1440 self.DrawPartialPageBackground(dc, wnd, rect, False) 1441 1442 true_rect = wx.Rect(*rect) 1443 true_rect = self.RemovePanelPadding(true_rect) 1444 1445 dc.SetFont(self._panel_label_font) 1446 dc.SetPen(wx.TRANSPARENT_PEN) 1447 1448 has_ext_button = wnd.HasExtButton() 1449 1450 if wnd.IsHovered(): 1451 dc.SetBrush(self._panel_hover_label_background_brush) 1452 dc.SetTextForeground(self._panel_hover_label_colour) 1453 else: 1454 dc.SetBrush(self._panel_label_background_brush) 1455 dc.SetTextForeground(self._panel_label_colour) 1456 1457 label_rect = wx.Rect(*true_rect) 1458 label = wnd.GetLabel().strip() 1459 clip_label = False 1460 label_size = wx.Size(*dc.GetTextExtent(label)) 1461 1462 label_rect.SetX(label_rect.GetX() + 1) 1463 label_rect.SetWidth(label_rect.GetWidth() - 2) 1464 label_rect.SetHeight(label_size.GetHeight() + 2) 1465 label_rect.SetY(true_rect.GetBottom() - label_rect.GetHeight()) 1466 label_height = label_rect.GetHeight() 1467 1468 label_bg_rect = wx.Rect(*label_rect) 1469 1470 if has_ext_button: 1471 label_rect.SetWidth(label_rect.GetWidth() - 13) 1472 1473 if label_size.GetWidth() > label_rect.GetWidth(): 1474 # Test if there is enough length for 3 letters and ... 1475 new_label = label[0:3] + "..." 1476 label_size = wx.Size(*dc.GetTextExtent(new_label)) 1477 1478 if label_size.GetWidth() > label_rect.GetWidth(): 1479 # Not enough room for three characters and ... 1480 # Display the entire label and just crop it 1481 clip_label = True 1482 else: 1483 # Room for some characters and ... 1484 # Display as many characters as possible and append ... 1485 for l in range(len(label)-1, 3, -1): 1486 new_label = label[0:l] + "..." 1487 label_size = wx.Size(*dc.GetTextExtent(new_label)) 1488 if label_size.GetWidth() <= label_rect.GetWidth(): 1489 label = new_label 1490 break 1491 1492 dc.DrawRectangle(label_rect) 1493 1494 if clip_label: 1495 clip = wx.DCClipper(dc, label_rect) 1496 dc.DrawText(label, label_rect.x, label_rect.y + (label_rect.GetHeight() - label_size.GetHeight()) / 2) 1497 else: 1498 dc.DrawText(label, label_rect.x + (label_rect.GetWidth() - label_size.GetWidth()) / 2, 1499 label_rect.y + (label_rect.GetHeight() - label_size.GetHeight()) / 2) 1500 1501 if has_ext_button: 1502 if wnd.IsExtButtonHovered(): 1503 dc.SetPen(self._panel_hover_button_border_pen) 1504 dc.SetBrush(self._panel_hover_button_background_brush) 1505 dc.DrawRoundedRectangle(label_rect.GetRight(), label_rect.GetBottom() - 13, 13, 13, 1) 1506 dc.DrawBitmap(self._panel_extension_bitmap[1], label_rect.GetRight() + 3, label_rect.GetBottom() - 10, True) 1507 else: 1508 dc.DrawBitmap(self._panel_extension_bitmap[0], label_rect.GetRight() + 3, label_rect.GetBottom() - 10, True) 1509 1510 if wnd.IsHovered(): 1511 client_rect = wx.Rect(*true_rect) 1512 client_rect.x += 1 1513 client_rect.width -= 2 1514 client_rect.y += 1 1515 client_rect.height -= 2 + label_height 1516 self.DrawPartialPageBackground(dc, wnd, client_rect, True) 1517 1518 self.DrawPanelBorder(dc, true_rect, self._panel_border_pen, self._panel_border_gradient_pen) 1519 1520 1521 def GetPanelExtButtonArea(self, dc, wnd, rect): 1522 """ 1523 Retrieve the extension button area rectangle. 1524 1525 :param `dc`: The device context used to measure text extents; 1526 :param `wnd`: The panel where the extension button resides; 1527 :param `rect`: The panel client rectangle. 1528 """ 1529 1530 true_rect = wx.Rect(self.RemovePanelPadding(rect)) 1531 true_rect = wx.Rect(true_rect.GetRight()-13, true_rect.GetBottom()-13, 13, 13) 1532 return true_rect 1533 1534 1535 def DrawGalleryBackground(self, dc, wnd, rect): 1536 """ 1537 Draw the background and chrome for a :class:`~wx.lib.agw.ribbon.gallery.RibbonGallery` control. 1538 1539 This should draw the border, brackground, scroll buttons, extension button, and 1540 any other UI elements which are not attached to a specific gallery item. 1541 1542 :param `dc`: The device context to draw onto; 1543 :param `wnd`: The window which is being drawn onto, which is always the gallery 1544 whose background and chrome is being drawn. Attributes used during drawing like 1545 the gallery hover state and individual button states can be queried from this 1546 parameter by :meth:`RibbonGallery.IsHovered() <lib.agw.ribbon.gallery.RibbonGallery.IsHovered>`, 1547 :meth:`RibbonGallery.GetExtensionButtonState() <lib.agw.ribbon.gallery.RibbonGallery.GetExtensionButtonState>`, 1548 :meth:`RibbonGallery.GetUpButtonState() <lib.agw.ribbon.gallery.RibbonGallery.GetUpButtonState>`, and 1549 :meth:`RibbonGallery.GetDownButtonState() <lib.agw.ribbon.gallery.RibbonGallery.GetDownButtonState>`; 1550 :param `rect`: The rectangle within which to draw. This rectangle is the entire 1551 area of the gallery control, not just the client rectangle. 1552 """ 1553 1554 self.DrawPartialPageBackground(dc, wnd, rect) 1555 1556 if wnd.IsHovered(): 1557 dc.SetPen(wx.TRANSPARENT_PEN) 1558 dc.SetBrush(self._gallery_hover_background_brush) 1559 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 1560 dc.DrawRectangle(rect.x + 1, rect.y + 1, rect.width - 2, rect.height - 16) 1561 else: 1562 dc.DrawRectangle(rect.x + 1, rect.y + 1, rect.width - 16, rect.height - 2) 1563 1564 dc.SetPen(self._gallery_border_pen) 1565 # Outline 1566 dc.DrawLine(rect.x + 1, rect.y, rect.x + rect.width - 1, rect.y) 1567 dc.DrawLine(rect.x, rect.y + 1, rect.x, rect.y + rect.height - 1) 1568 dc.DrawLine(rect.x + 1, rect.y + rect.height - 1, rect.x + rect.width - 1, rect.y + rect.height - 1) 1569 dc.DrawLine(rect.x + rect.width - 1, rect.y + 1, rect.x + rect.width - 1, rect.y + rect.height - 1) 1570 1571 self.DrawGalleryBackgroundCommon(dc, wnd, rect) 1572 1573 1574 def DrawGalleryBackgroundCommon(self, dc, wnd, rect): 1575 1576 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 1577 # Divider between items and buttons 1578 dc.DrawLine(rect.x, rect.y + rect.height - 15, rect.x + rect.width, rect.y + rect.height - 15) 1579 1580 up_btn = wx.Rect(rect.x, rect.y + rect.height - 15, rect.width / 3, 15) 1581 down_btn = wx.Rect(up_btn.GetRight() + 1, up_btn.GetTop(), up_btn.GetWidth(), up_btn.GetHeight()) 1582 dc.DrawLine(down_btn.GetLeft(), down_btn.GetTop(), down_btn.GetLeft(), down_btn.GetBottom()) 1583 ext_btn = wx.Rect(down_btn.GetRight() + 1, up_btn.GetTop(), rect.width - up_btn.GetWidth() - down_btn.GetWidth() - 1, up_btn.GetHeight()) 1584 dc.DrawLine(ext_btn.GetLeft(), ext_btn.GetTop(), ext_btn.GetLeft(), ext_btn.GetBottom()) 1585 1586 else: 1587 # Divider between items and buttons 1588 dc.DrawLine(rect.x + rect.width - 15, rect.y, rect.x + rect.width - 15, rect.y + rect.height) 1589 1590 up_btn = wx.Rect(rect.x + rect.width - 15, rect.y, 15, rect.height / 3) 1591 down_btn = wx.Rect(up_btn.GetLeft(), up_btn.GetBottom() + 1, up_btn.GetWidth(), up_btn.GetHeight()) 1592 dc.DrawLine(down_btn.GetLeft(), down_btn.GetTop(), down_btn.GetRight(), down_btn.GetTop()) 1593 ext_btn = wx.Rect(up_btn.GetLeft(), down_btn.GetBottom() + 1, up_btn.GetWidth(), rect.height - up_btn.GetHeight() - down_btn.GetHeight() - 1) 1594 dc.DrawLine(ext_btn.GetLeft(), ext_btn.GetTop(), ext_btn.GetRight(), ext_btn.GetTop()) 1595 1596 self.DrawGalleryButton(dc, up_btn, wnd.GetUpButtonState(), self._gallery_up_bitmap) 1597 self.DrawGalleryButton(dc, down_btn, wnd.GetDownButtonState(), self._gallery_down_bitmap) 1598 self.DrawGalleryButton(dc, ext_btn, wnd.GetExtensionButtonState(), self._gallery_extension_bitmap) 1599 1600 1601 def DrawGalleryButton(self, dc, rect, state, bitmaps): 1602 1603 if state == RIBBON_GALLERY_BUTTON_NORMAL: 1604 btn_top_brush = self._gallery_button_background_top_brush 1605 btn_colour = self._gallery_button_background_colour 1606 btn_grad_colour = self._gallery_button_background_gradient_colour 1607 btn_bitmap = bitmaps[0] 1608 elif state == RIBBON_GALLERY_BUTTON_HOVERED: 1609 btn_top_brush = self._gallery_button_hover_background_top_brush 1610 btn_colour = self._gallery_button_hover_background_colour 1611 btn_grad_colour = self._gallery_button_hover_background_gradient_colour 1612 btn_bitmap = bitmaps[1] 1613 elif state == RIBBON_GALLERY_BUTTON_ACTIVE: 1614 btn_top_brush = self._gallery_button_active_background_top_brush 1615 btn_colour = self._gallery_button_active_background_colour 1616 btn_grad_colour = self._gallery_button_active_background_gradient_colour 1617 btn_bitmap = bitmaps[2] 1618 elif state == RIBBON_GALLERY_BUTTON_DISABLED: 1619 btn_top_brush = self._gallery_button_disabled_background_top_brush 1620 btn_colour = self._gallery_button_disabled_background_colour 1621 btn_grad_colour = self._gallery_button_disabled_background_gradient_colour 1622 btn_bitmap = bitmaps[3] 1623 1624 rect.x += 1 1625 rect.y += 1 1626 1627 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 1628 rect.width -= 1 1629 rect.height -= 2 1630 else: 1631 rect.width -= 2 1632 rect.height -= 1 1633 1634 dc.SetPen(wx.TRANSPARENT_PEN) 1635 dc.SetBrush(btn_top_brush) 1636 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height / 2) 1637 1638 lower = wx.Rect(*rect) 1639 lower.height = (lower.height + 1) / 2 1640 lower.y += rect.height - lower.height 1641 dc.GradientFillLinear(lower, btn_colour, btn_grad_colour, wx.SOUTH) 1642 1643 dc.DrawBitmap(btn_bitmap, rect.x + rect.width / 2 - 2, lower.y - 2, True) 1644 1645 1646 def DrawGalleryItemBackground(self, dc, wnd, rect, item): 1647 """ 1648 Draw the background of a single item in a :class:`~wx.lib.agw.ribbon.gallery.RibbonGallery` control. 1649 1650 This is painted on top of a gallery background, and behind the items bitmap. 1651 Unlike :meth:`~RibbonMSWArtProvider.DrawButtonBarButton` and :meth:`~RibbonMSWArtProvider.DrawTool`, it is not expected to draw the 1652 item bitmap - that is done by the gallery control itself. 1653 1654 :param `dc`: The device context to draw onto; 1655 :param `wnd`: The window which is being drawn onto, which is always the gallery 1656 which contains the item being drawn; 1657 :param `rect`: The rectangle within which to draw. The size of this rectangle 1658 will be the size of the item's bitmap, expanded by gallery item padding values 1659 (``RIBBON_ART_GALLERY_BITMAP_PADDING_LEFT_SIZE``, ``RIBBON_ART_GALLERY_BITMAP_PADDING_RIGHT_SIZE``, 1660 ``RIBBON_ART_GALLERY_BITMAP_PADDING_TOP_SIZE``, and ``RIBBON_ART_GALLERY_BITMAP_PADDING_BOTTOM_SIZE``). 1661 The drawing rectangle will be entirely within a rectangle on the same device 1662 context previously painted with :meth:`~RibbonMSWArtProvider.DrawGalleryBackground`; 1663 :param `item`: The item whose background is being painted. Typically the background 1664 will vary if the item is hovered, active, or selected; :meth:`RibbonGallery.GetSelection() <lib.agw.ribbon.gallery.RibbonGallery.GetSelection>`, 1665 :meth:`RibbonGallery.GetActiveItem() <lib.agw.ribbon.gallery.RibbonGallery.GetActiveItem>`, and 1666 :meth:`RibbonGallery.GetHoveredItem() <lib.agw.ribbon.gallery.RibbonGallery.GetHoveredItem>` can be 1667 called to test if the given item is in one of these states. 1668 1669 """ 1670 1671 if wnd.GetHoveredItem() != item and wnd.GetActiveItem() != item and \ 1672 wnd.GetSelection() != item: 1673 return 1674 1675 dc.SetPen(self._gallery_item_border_pen) 1676 dc.DrawLine(rect.x + 1, rect.y, rect.x + rect.width - 1, rect.y) 1677 dc.DrawLine(rect.x, rect.y + 1, rect.x, rect.y + rect.height - 1) 1678 dc.DrawLine(rect.x + 1, rect.y + rect.height - 1, rect.x + rect.width - 1, rect.y + rect.height - 1) 1679 dc.DrawLine(rect.x + rect.width - 1, rect.y + 1, rect.x + rect.width - 1, rect.y + rect.height - 1) 1680 1681 if wnd.GetActiveItem() == item or wnd.GetSelection() == item: 1682 top_brush = self._gallery_button_active_background_top_brush 1683 bg_colour = self._gallery_button_active_background_colour 1684 bg_gradient_colour = self._gallery_button_active_background_gradient_colour 1685 else: 1686 top_brush = self._gallery_button_hover_background_top_brush 1687 bg_colour = self._gallery_button_hover_background_colour 1688 bg_gradient_colour = self._gallery_button_hover_background_gradient_colour 1689 1690 upper = wx.Rect(*rect) 1691 upper.x += 1 1692 upper.width -= 2 1693 upper.y += 1 1694 upper.height /= 3 1695 dc.SetPen(wx.TRANSPARENT_PEN) 1696 dc.SetBrush(top_brush) 1697 dc.DrawRectangle(upper.x, upper.y, upper.width, upper.height) 1698 1699 lower = wx.Rect(*upper) 1700 lower.y += lower.height 1701 lower.height = rect.height - 2 - lower.height 1702 dc.GradientFillLinear(lower, bg_colour, bg_gradient_colour, wx.SOUTH) 1703 1704 1705 def DrawPanelBorder(self, dc, rect, primary_colour, secondary_colour): 1706 1707 border_points = [wx.Point() for i in range(9)] 1708 border_points[0] = wx.Point(2, 0) 1709 border_points[1] = wx.Point(rect.width - 3, 0) 1710 border_points[2] = wx.Point(rect.width - 1, 2) 1711 border_points[3] = wx.Point(rect.width - 1, rect.height - 3) 1712 border_points[4] = wx.Point(rect.width - 3, rect.height - 1) 1713 border_points[5] = wx.Point(2, rect.height - 1) 1714 border_points[6] = wx.Point(0, rect.height - 3) 1715 border_points[7] = wx.Point(0, 2) 1716 1717 if primary_colour.GetColour() == secondary_colour.GetColour(): 1718 border_points[8] = border_points[0] 1719 dc.SetPen(primary_colour) 1720 dc.DrawLines(border_points, rect.x, rect.y) 1721 else: 1722 dc.SetPen(primary_colour) 1723 dc.DrawLines(border_points[0:3], rect.x, rect.y) 1724 1725 SingleLine(dc, rect, border_points[0], border_points[7]) 1726 dc.SetPen(secondary_colour) 1727 dc.DrawLines(border_points[4:7], rect.x, rect.y) 1728 SingleLine(dc, rect, border_points[4], border_points[3]) 1729 1730 border_points[6] = border_points[2] 1731 RibbonDrawParallelGradientLines(dc, 2, border_points[6:8], 0, 1, 1732 border_points[3].y - border_points[2].y + 1, rect.x, rect.y, 1733 primary_colour.GetColour(), secondary_colour.GetColour()) 1734 1735 1736 def DrawMinimisedPanel(self, dc, wnd, rect, bitmap): 1737 """ 1738 Draw a minimised ribbon panel. 1739 1740 :param `dc`: The device context to draw onto; 1741 :param `wnd`: The window which is being drawn onto, which is always the panel 1742 which is minimised. The panel label can be obtained from this window. The 1743 minimised icon obtained from querying the window may not be the size requested 1744 by :meth:`~RibbonMSWArtProvider.GetMinimisedPanelMinimumSize` - the argument contains the icon in the 1745 requested size; 1746 :param `rect`: The rectangle within which to draw. The size of the rectangle 1747 will be at least the size returned by :meth:`~RibbonMSWArtProvider.GetMinimisedPanelMinimumSize`; 1748 :param `bitmap`: A copy of the panel's minimised bitmap rescaled to the size 1749 returned by :meth:`~RibbonMSWArtProvider.GetMinimisedPanelMinimumSize`. 1750 1751 """ 1752 1753 self.DrawPartialPageBackground(dc, wnd, rect, False) 1754 1755 true_rect = wx.Rect(*rect) 1756 true_rect = self.RemovePanelPadding(true_rect) 1757 1758 if wnd.GetExpandedPanel() != None: 1759 client_rect = wx.Rect(*true_rect) 1760 client_rect.x += 1 1761 client_rect.width -= 2 1762 client_rect.y += 1 1763 client_rect.height = (rect.y + rect.height / 5) - client_rect.x 1764 dc.GradientFillLinear(client_rect, 1765 self._panel_active_background_top_colour, 1766 self._panel_active_background_top_gradient_colour, wx.SOUTH) 1767 1768 client_rect.y += client_rect.height 1769 client_rect.height = (true_rect.y + true_rect.height) - client_rect.y 1770 dc.GradientFillLinear(client_rect, 1771 self._panel_active_background_colour, 1772 self._panel_active_background_gradient_colour, wx.SOUTH) 1773 1774 elif wnd.IsHovered(): 1775 client_rect = wx.Rect(*true_rect) 1776 client_rect.x += 1 1777 client_rect.width -= 2 1778 client_rect.y += 1 1779 client_rect.height -= 2 1780 self.DrawPartialPageBackground(dc, wnd, client_rect, True) 1781 1782 preview = self.DrawMinimisedPanelCommon(dc, wnd, true_rect) 1783 1784 dc.SetBrush(self._panel_hover_label_background_brush) 1785 dc.SetPen(wx.TRANSPARENT_PEN) 1786 dc.DrawRectangle(preview.x + 1, preview.y + preview.height - 8, preview.width - 2, 7) 1787 1788 mid_pos = rect.y + rect.height / 5 - preview.y 1789 1790 if mid_pos < 0 or mid_pos >= preview.height: 1791 full_rect = wx.Rect(*preview) 1792 full_rect.x += 1 1793 full_rect.y += 1 1794 full_rect.width -= 2 1795 full_rect.height -= 9 1796 if mid_pos < 0: 1797 dc.GradientFillLinear(full_rect, self._page_hover_background_colour, 1798 self._page_hover_background_gradient_colour, wx.SOUTH) 1799 else: 1800 dc.GradientFillLinear(full_rect, self._page_hover_background_top_colour, 1801 self._page_hover_background_top_gradient_colour, wx.SOUTH) 1802 1803 else: 1804 top_rect = wx.Rect(*preview) 1805 top_rect.x += 1 1806 top_rect.y += 1 1807 top_rect.width -= 2 1808 top_rect.height = mid_pos 1809 dc.GradientFillLinear(top_rect, self._page_hover_background_top_colour, 1810 self._page_hover_background_top_gradient_colour, wx.SOUTH) 1811 1812 btm_rect = wx.Rect(*top_rect) 1813 btm_rect.y = preview.y + mid_pos 1814 btm_rect.height = preview.y + preview.height - 7 - btm_rect.y 1815 dc.GradientFillLinear(btm_rect, self._page_hover_background_colour, 1816 self._page_hover_background_gradient_colour, wx.SOUTH) 1817 1818 if bitmap.IsOk(): 1819 dc.DrawBitmap(bitmap, preview.x + (preview.width - bitmap.GetWidth()) / 2, 1820 preview.y + (preview.height - 7 - bitmap.GetHeight()) / 2, True) 1821 1822 self.DrawPanelBorder(dc, preview, self._panel_border_pen, self._panel_border_gradient_pen) 1823 self.DrawPanelBorder(dc, true_rect, self._panel_minimised_border_pen, self._panel_minimised_border_gradient_pen) 1824 1825 1826 def DrawMinimisedPanelCommon(self, dc, wnd, true_rect): 1827 1828 preview = wx.Rect(0, 0, 32, 32) 1829 1830 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 1831 preview.x = true_rect.x + 4 1832 preview.y = true_rect.y + (true_rect.height - preview.height) / 2 1833 else: 1834 preview.x = true_rect.x + (true_rect.width - preview.width) / 2 1835 preview.y = true_rect.y + 4 1836 1837 dc.SetFont(self._panel_label_font) 1838 label_width, label_height = dc.GetTextExtent(wnd.GetLabel()) 1839 1840 xpos = true_rect.x + (true_rect.width - label_width + 1) / 2 1841 ypos = preview.y + preview.height + 5 1842 1843 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 1844 xpos = preview.x + preview.width + 5 1845 ypos = true_rect.y + (true_rect.height - label_height) / 2 1846 1847 dc.SetTextForeground(self._panel_minimised_label_colour) 1848 dc.DrawText(wnd.GetLabel(), xpos, ypos) 1849 1850 arrow_points = [wx.Point() for i in range(3)] 1851 1852 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 1853 xpos += label_width 1854 arrow_points[0] = wx.Point(xpos + 5, ypos + label_height / 2) 1855 arrow_points[1] = arrow_points[0] + wx.Point(-3, 3) 1856 arrow_points[2] = arrow_points[0] + wx.Point(-3, -3) 1857 else: 1858 ypos += label_height 1859 arrow_points[0] = wx.Point(true_rect.width / 2, ypos + 5) 1860 arrow_points[1] = arrow_points[0] + wx.Point(-3, -3) 1861 arrow_points[2] = arrow_points[0] + wx.Point( 3, -3) 1862 1863 dc.SetPen(wx.TRANSPARENT_PEN) 1864 B = wx.Brush(self._panel_minimised_label_colour) 1865 dc.SetBrush(B) 1866 dc.DrawPolygon(arrow_points, true_rect.x, true_rect.y) 1867 1868 return preview 1869 1870 1871 def DrawButtonBarBackground(self, dc, wnd, rect): 1872 """ 1873 Draw the background for a :class:`~wx.lib.agw.ribbon.buttonbar.RibbonButtonBar` control. 1874 1875 :param `dc`: The device context to draw onto; 1876 :param `wnd`: The window which is being drawn onto (which will typically be 1877 the button bar itself, though this is not guaranteed); 1878 :param `rect`: The rectangle within which to draw. 1879 1880 """ 1881 1882 self.DrawPartialPageBackground(dc, wnd, rect, True) 1883 1884 1885 def DrawPartialPageBackground2(self, dc, wnd, rect, allow_hovered=True): 1886 1887 # Assume the window is a child of a ribbon page, and also check for a 1888 # hovered panel somewhere between the window and the page, as it causes 1889 # the background to change. 1890 offset = wx.Point(*wnd.GetPosition()) 1891 page = None 1892 parent = wnd.GetParent() 1893 hovered = False 1894 panel = None 1895 1896 if isinstance(wnd, PANEL.RibbonPanel): 1897 panel = wnd 1898 hovered = allow_hovered and panel.IsHovered() 1899 if panel.GetExpandedDummy() != None: 1900 offset = panel.GetExpandedDummy().GetPosition() 1901 parent = panel.GetExpandedDummy().GetParent() 1902 1903 while 1: 1904 1905 if panel is None: 1906 panel = parent 1907 if isinstance(panel, PANEL.RibbonPanel): 1908 hovered = allow_hovered and panel.IsHovered() 1909 if panel.GetExpandedDummy() != None: 1910 parent = panel.GetExpandedDummy() 1911 1912 page = parent 1913 if isinstance(page, PAGE.RibbonPage): 1914 break 1915 1916 offset += parent.GetPosition() 1917 parent = parent.GetParent() 1918 if parent is None: 1919 break 1920 1921 if page != None: 1922 self.DrawPartialPageBackground(dc, wnd, rect, page, offset, hovered) 1923 return 1924 1925 # No page found - fallback to painting with a stock brush 1926 dc.SetBrush(wx.WHITE_BRUSH) 1927 dc.SetPen(wx.TRANSPARENT_PEN) 1928 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) 1929 1930 1931 def DrawButtonBarButton(self, dc, wnd, rect, kind, state, label, bitmap_large, bitmap_small): 1932 """ 1933 Draw a single button for a :class:`~wx.lib.agw.ribbon.buttonbar.RibbonButtonBar` control. 1934 1935 :param `dc`: The device context to draw onto; 1936 :param `wnd`: The window which is being drawn onto; 1937 :param `rect`: The rectangle within which to draw. The size of this rectangle 1938 will be a size previously returned by :meth:`~RibbonMSWArtProvider.GetButtonBarButtonSize`, and the 1939 rectangle will be entirely within a rectangle on the same device context 1940 previously painted with :meth:`~RibbonMSWArtProvider.DrawButtonBarBackground`; 1941 :param `kind`: The kind of button to draw (normal, dropdown or hybrid); 1942 :param `state`: Combination of a size flag and state flags from the 1943 `RibbonButtonBarButtonState` enumeration; 1944 :param `label`: The label of the button; 1945 :param `bitmap_large`: The large bitmap of the button (or the large disabled 1946 bitmap when ``RIBBON_BUTTONBAR_BUTTON_DISABLED`` is set in `state`); 1947 :param `bitmap_small`: The small bitmap of the button (or the small disabled 1948 bitmap when ``RIBBON_BUTTONBAR_BUTTON_DISABLED`` is set in `state`). 1949 1950 """ 1951 1952 if kind == RIBBON_BUTTON_TOGGLE: 1953 kind = RIBBON_BUTTON_NORMAL 1954 if state & RIBBON_BUTTONBAR_BUTTON_TOGGLED: 1955 state ^= RIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK 1956 1957 if state & (RIBBON_BUTTONBAR_BUTTON_HOVER_MASK | RIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK): 1958 if state & RIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK: 1959 dc.SetPen(self._button_bar_active_border_pen) 1960 else: 1961 dc.SetPen(self._button_bar_hover_border_pen) 1962 1963 bg_rect = wx.Rect(*rect) 1964 bg_rect.x += 1 1965 bg_rect.y += 1 1966 bg_rect.width -= 2 1967 bg_rect.height -= 2 1968 1969 bg_rect_top = wx.Rect(*bg_rect) 1970 bg_rect_top.height /= 3 1971 bg_rect.y += bg_rect_top.height 1972 bg_rect.height -= bg_rect_top.height 1973 1974 if kind == RIBBON_BUTTON_HYBRID: 1975 1976 result = state & RIBBON_BUTTONBAR_BUTTON_SIZE_MASK 1977 1978 if result == RIBBON_BUTTONBAR_BUTTON_LARGE: 1979 iYBorder = rect.y + bitmap_large.GetHeight() + 4 1980 partial_bg = wx.Rect(*rect) 1981 1982 if state & RIBBON_BUTTONBAR_BUTTON_NORMAL_HOVERED: 1983 partial_bg.SetBottom(iYBorder - 1) 1984 else: 1985 partial_bg.height -= (iYBorder - partial_bg.y + 1) 1986 partial_bg.y = iYBorder + 1 1987 1988 dc.DrawLine(rect.x, iYBorder, rect.x + rect.width, iYBorder) 1989 bg_rect.Intersect(partial_bg) 1990 bg_rect_top.Intersect(partial_bg) 1991 1992 elif result == RIBBON_BUTTONBAR_BUTTON_MEDIUM: 1993 iArrowWidth = 9 1994 1995 if state & RIBBON_BUTTONBAR_BUTTON_NORMAL_HOVERED: 1996 bg_rect.width -= iArrowWidth 1997 bg_rect_top.width -= iArrowWidth 1998 dc.DrawLine(bg_rect_top.x + bg_rect_top.width, rect.y, bg_rect_top.x + bg_rect_top.width, 1999 rect.y + rect.height) 2000 else: 2001 iArrowWidth -= 1 2002 bg_rect.x += bg_rect.width - iArrowWidth 2003 bg_rect_top.x += bg_rect_top.width - iArrowWidth 2004 bg_rect.width = iArrowWidth 2005 bg_rect_top.width = iArrowWidth 2006 dc.DrawLine(bg_rect_top.x - 1, rect.y, bg_rect_top.x - 1, rect.y + rect.height) 2007 2008 if state & RIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK: 2009 2010 dc.GradientFillLinear(bg_rect_top, self._button_bar_active_background_top_colour, 2011 self._button_bar_active_background_top_gradient_colour, wx.SOUTH) 2012 dc.GradientFillLinear(bg_rect, self._button_bar_active_background_colour, 2013 self._button_bar_active_background_gradient_colour, wx.SOUTH) 2014 2015 else: 2016 dc.GradientFillLinear(bg_rect_top, self._button_bar_hover_background_top_colour, 2017 self._button_bar_hover_background_top_gradient_colour, wx.SOUTH) 2018 dc.GradientFillLinear(bg_rect, self._button_bar_hover_background_colour, 2019 self._button_bar_hover_background_gradient_colour, wx.SOUTH) 2020 2021 border_points = [wx.Point() for i in range(9)] 2022 border_points[0] = wx.Point(2, 0) 2023 border_points[1] = wx.Point(rect.width - 3, 0) 2024 border_points[2] = wx.Point(rect.width - 1, 2) 2025 border_points[3] = wx.Point(rect.width - 1, rect.height - 3) 2026 border_points[4] = wx.Point(rect.width - 3, rect.height - 1) 2027 border_points[5] = wx.Point(2, rect.height - 1) 2028 border_points[6] = wx.Point(0, rect.height - 3) 2029 border_points[7] = wx.Point(0, 2) 2030 border_points[8] = border_points[0] 2031 2032 dc.DrawLines(border_points, rect.x, rect.y) 2033 2034 dc.SetFont(self._button_bar_label_font) 2035 dc.SetTextForeground(self._button_bar_label_colour) 2036 self.DrawButtonBarButtonForeground(dc, rect, kind, state, label, bitmap_large, bitmap_small) 2037 2038 2039 def DrawButtonBarButtonForeground(self, dc, rect, kind, state, label, bitmap_large, bitmap_small): 2040 2041 result = state & RIBBON_BUTTONBAR_BUTTON_SIZE_MASK 2042 2043 if result == RIBBON_BUTTONBAR_BUTTON_LARGE: 2044 2045 padding = 2 2046 dc.DrawBitmap(bitmap_large, rect.x + (rect.width - bitmap_large.GetWidth()) / 2, 2047 rect.y + padding, True) 2048 ypos = rect.y + padding + bitmap_large.GetHeight() + padding 2049 arrow_width = (kind == RIBBON_BUTTON_NORMAL and [0] or [8])[0] 2050 2051 label_w, label_h = dc.GetTextExtent(label) 2052 2053 if label_w + 2 * padding <= rect.width: 2054 2055 dc.DrawText(label, rect.x + (rect.width - label_w) / 2, ypos) 2056 if arrow_width != 0: 2057 self.DrawDropdownArrow(dc, rect.x + rect.width / 2, 2058 ypos + (label_h * 3) / 2, 2059 self._button_bar_label_colour) 2060 else: 2061 breaki = len(label) 2062 2063 while breaki > 0: 2064 breaki -= 1 2065 if RibbonCanLabelBreakAtPosition(label, breaki): 2066 label_top = label[0:breaki] 2067 label_w, label_h = dc.GetTextExtent(label_top) 2068 2069 if label_w + 2 * padding <= rect.width: 2070 dc.DrawText(label_top, rect.x + (rect.width - label_w) / 2, ypos) 2071 ypos += label_h 2072 label_bottom = label[breaki:] 2073 label_w, label_h = dc.GetTextExtent(label_bottom) 2074 label_w += arrow_width 2075 iX = rect.x + (rect.width - label_w) / 2 2076 dc.DrawText(label_bottom, iX, ypos) 2077 2078 if arrow_width != 0: 2079 self.DrawDropdownArrow(dc, iX + 2 +label_w - arrow_width, 2080 ypos + label_h / 2 + 1, 2081 self._button_bar_label_colour) 2082 2083 break 2084 2085 elif result == RIBBON_BUTTONBAR_BUTTON_MEDIUM: 2086 2087 x_cursor = rect.x + 2 2088 dc.DrawBitmap(bitmap_small, x_cursor, rect.y + (rect.height - bitmap_small.GetHeight())/2, True) 2089 x_cursor += bitmap_small.GetWidth() + 2 2090 label_w, label_h = dc.GetTextExtent(label) 2091 dc.DrawText(label, x_cursor, rect.y + (rect.height - label_h) / 2) 2092 x_cursor += label_w + 3 2093 2094 if kind != RIBBON_BUTTON_NORMAL: 2095 self.DrawDropdownArrow(dc, x_cursor, rect.y + rect.height / 2, 2096 self._button_bar_label_colour) 2097 2098 else: 2099 # TODO 2100 pass 2101 2102 2103 def DrawToolBarBackground(self, dc, wnd, rect): 2104 """ 2105 Draw the background for a :class:`~wx.lib.agw.ribbon.toolbar.RibbonToolBar` control. 2106 2107 2108 :param `dc`: The device context to draw onto; 2109 :param `wnd`: The which is being drawn onto. In most cases this will be a 2110 :class:`~wx.lib.agw.ribbon.toolbar.RibbonToolBar`, but it doesn't have to be; 2111 :param `rect`: The rectangle within which to draw. Some of this rectangle 2112 will later be drawn over using :meth:`~RibbonMSWArtProvider.DrawToolGroupBackground` and :meth:`~RibbonMSWArtProvider.DrawTool`, 2113 but not all of it will (unless there is only a single group of tools). 2114 2115 """ 2116 2117 self.DrawPartialPageBackground(dc, wnd, rect) 2118 2119 2120 def DrawToolGroupBackground(self, dc, wnd, rect): 2121 """ 2122 Draw the background for a group of tools on a :class:`~wx.lib.agw.ribbon.toolbar.RibbonToolBar` control. 2123 2124 :param `dc`: The device context to draw onto; 2125 :param `wnd`: The window which is being drawn onto. In most cases this will 2126 be a :class:`~wx.lib.agw.ribbon.toolbar.RibbonToolBar`, but it doesn't have to be; 2127 :param `rect`: The rectangle within which to draw. This rectangle is a union 2128 of the individual tools' rectangles. As there are no gaps between tools, 2129 this rectangle will be painted over exactly once by calls to :meth:`~RibbonMSWArtProvider.DrawTool`. 2130 The group background could therefore be painted by :meth:`~RibbonMSWArtProvider.DrawTool`, though it 2131 can be conceptually easier and more efficient to draw it all at once here. 2132 The rectangle will be entirely within a rectangle on the same device context 2133 previously painted with :meth:`~RibbonMSWArtProvider.DrawToolBarBackground`. 2134 2135 """ 2136 2137 dc.SetPen(self._toolbar_border_pen) 2138 outline = [wx.Point() for i in range(9)] 2139 outline[0] = wx.Point(2, 0) 2140 outline[1] = wx.Point(rect.width - 3, 0) 2141 outline[2] = wx.Point(rect.width - 1, 2) 2142 outline[3] = wx.Point(rect.width - 1, rect.height - 3) 2143 outline[4] = wx.Point(rect.width - 3, rect.height - 1) 2144 outline[5] = wx.Point(2, rect.height - 1) 2145 outline[6] = wx.Point(0, rect.height - 3) 2146 outline[7] = wx.Point(0, 2) 2147 outline[8] = outline[0] 2148 2149 dc.DrawLines(outline, rect.x, rect.y) 2150 2151 2152 def DrawTool(self, dc, wnd, rect, bitmap, kind, state): 2153 """ 2154 Draw a single tool (for a :class:`~wx.lib.agw.ribbon.toolbar.RibbonToolBar` control). 2155 2156 :param `dc`: The device context to draw onto; 2157 :param `wnd`: The window which is being drawn onto. In most cases this will 2158 be a :class:`~wx.lib.agw.ribbon.toolbar.RibbonToolBar`, but it doesn't have to be; 2159 :param `rect`: The rectangle within which to draw. The size of this rectangle 2160 will at least the size returned by :meth:`~RibbonMSWArtProvider.GetToolSize`, and the height of it will 2161 be equal for all tools within the same group. The rectangle will be entirely 2162 within a rectangle on the same device context previously painted with 2163 :meth:`~RibbonMSWArtProvider.DrawToolGroupBackground`; 2164 :param `bitmap`: The bitmap to use as the tool's foreground. If the tool is a 2165 hybrid or dropdown tool, then the foreground should also contain a standard 2166 dropdown button; 2167 :param `kind`: The kind of tool to draw (normal, dropdown, or hybrid); 2168 :param `state`: A combination of `RibbonToolBarToolState` flags giving the 2169 state of the tool and it's relative position within a tool group. 2170 2171 """ 2172 2173 if kind == RIBBON_BUTTON_TOGGLE: 2174 if state & RIBBON_TOOLBAR_TOOL_TOGGLED: 2175 state ^= RIBBON_TOOLBAR_TOOL_ACTIVE_MASK 2176 2177 bg_rect = wx.Rect(*rect) 2178 bg_rect.Deflate(1, 1) 2179 2180 if state & RIBBON_TOOLBAR_TOOL_LAST == 0: 2181 bg_rect.width += 1 2182 2183 is_split_hybrid = (kind == RIBBON_BUTTON_HYBRID and (state & (RIBBON_TOOLBAR_TOOL_HOVER_MASK | RIBBON_TOOLBAR_TOOL_ACTIVE_MASK))) 2184 2185 # Background 2186 bg_rect_top = wx.Rect(*bg_rect) 2187 bg_rect_top.height = (bg_rect_top.height * 2) / 5 2188 bg_rect_btm = wx.Rect(*bg_rect) 2189 bg_rect_btm.y += bg_rect_top.height 2190 bg_rect_btm.height -= bg_rect_top.height 2191 2192 bg_top_colour = self._tool_background_top_colour 2193 bg_top_grad_colour = self._tool_background_top_gradient_colour 2194 bg_colour = self._tool_background_colour 2195 bg_grad_colour = self._tool_background_gradient_colour 2196 2197 if state & RIBBON_TOOLBAR_TOOL_ACTIVE_MASK: 2198 bg_top_colour = self._tool_active_background_top_colour 2199 bg_top_grad_colour = self._tool_active_background_top_gradient_colour 2200 bg_colour = self._tool_active_background_colour 2201 bg_grad_colour = self._tool_active_background_gradient_colour 2202 2203 elif state & RIBBON_TOOLBAR_TOOL_HOVER_MASK: 2204 bg_top_colour = self._tool_hover_background_top_colour 2205 bg_top_grad_colour = self._tool_hover_background_top_gradient_colour 2206 bg_colour = self._tool_hover_background_colour 2207 bg_grad_colour = self._tool_hover_background_gradient_colour 2208 2209 dc.GradientFillLinear(bg_rect_top, bg_top_colour, bg_top_grad_colour, wx.SOUTH) 2210 dc.GradientFillLinear(bg_rect_btm, bg_colour, bg_grad_colour, wx.SOUTH) 2211 2212 if is_split_hybrid: 2213 nonrect = wx.Rect(*bg_rect) 2214 if state & (RIBBON_TOOLBAR_TOOL_DROPDOWN_HOVERED | RIBBON_TOOLBAR_TOOL_DROPDOWN_ACTIVE): 2215 nonrect.width -= 8 2216 else: 2217 nonrect.x += nonrect.width - 8 2218 nonrect.width = 8 2219 2220 B = wx.Brush(self._tool_hover_background_top_colour) 2221 dc.SetPen(wx.TRANSPARENT_PEN) 2222 dc.SetBrush(B) 2223 dc.DrawRectangle(nonrect.x, nonrect.y, nonrect.width, nonrect.height) 2224 2225 # Border 2226 dc.SetPen(self._toolbar_border_pen) 2227 2228 if state & RIBBON_TOOLBAR_TOOL_FIRST: 2229 dc.DrawPoint(rect.x + 1, rect.y + 1) 2230 dc.DrawPoint(rect.x + 1, rect.y + rect.height - 2) 2231 else: 2232 dc.DrawLine(rect.x, rect.y + 1, rect.x, rect.y + rect.height - 1) 2233 2234 if state & RIBBON_TOOLBAR_TOOL_LAST: 2235 dc.DrawPoint(rect.x + rect.width - 2, rect.y + 1) 2236 dc.DrawPoint(rect.x + rect.width - 2, rect.y + rect.height - 2) 2237 2238 # Foreground 2239 avail_width = bg_rect.GetWidth() 2240 2241 if kind & RIBBON_BUTTON_DROPDOWN: 2242 avail_width -= 8 2243 if is_split_hybrid: 2244 dc.DrawLine(rect.x + avail_width + 1, rect.y, rect.x + avail_width + 1, rect.y + rect.height) 2245 2246 dc.DrawBitmap(self._toolbar_drop_bitmap, bg_rect.x + avail_width + 2, 2247 bg_rect.y + (bg_rect.height / 2) - 2, True) 2248 2249 dc.DrawBitmap(bitmap, bg_rect.x + (avail_width - bitmap.GetWidth()) / 2, 2250 bg_rect.y + (bg_rect.height - bitmap.GetHeight()) / 2, True) 2251 2252 2253 def GetBarTabWidth(self, dc, wnd, label, bitmap, ideal=None, small_begin_need_separator=None, 2254 small_must_have_separator=None, minimum=None): 2255 2256 """ 2257 Calculate the ideal and minimum width (in pixels) of a tab in a ribbon bar. 2258 2259 :param `dc`: A device context to use when one is required for size calculations; 2260 :param `wnd`: The window onto which the tab will eventually be drawn; 2261 :param `label`: The tab's label (or "" if it has none); 2262 :param `bitmap`: The tab's icon (or :class:`NullBitmap` if it has none); 2263 :param `ideal`: The ideal width (in pixels) of the tab; 2264 :param `small_begin_need_separator`: A size less than the size, at which a 2265 tab separator should begin to be drawn (i.e. drawn, but still fairly transparent); 2266 :param `small_must_have_separator`: A size less than the size, at which a 2267 tab separator must be drawn (i.e. drawn at full opacity); 2268 :param `minimum`: A size less than the size, and greater than or equal to 2269 zero, which is the minimum pixel width for the tab. 2270 2271 """ 2272 2273 width = 0 2274 mini = 0 2275 2276 if (self._flags & RIBBON_BAR_SHOW_PAGE_LABELS) and label.strip(): 2277 dc.SetFont(self._tab_label_font) 2278 width += dc.GetTextExtent(label)[0] 2279 mini += min(25, width) # enough for a few chars 2280 2281 if bitmap.IsOk(): 2282 # gap between label and bitmap 2283 width += 4 2284 mini += 2 2285 2286 if (self._flags & RIBBON_BAR_SHOW_PAGE_ICONS) and bitmap.IsOk(): 2287 width += bitmap.GetWidth() 2288 mini += bitmap.GetWidth() 2289 2290 ideal = width + 30 2291 small_begin_need_separator = width + 20 2292 small_must_have_separator = width + 10 2293 minimum = mini 2294 2295 return ideal, small_begin_need_separator, small_must_have_separator, minimum 2296 2297 2298 def GetTabCtrlHeight(self, dc, wnd, pages): 2299 """ 2300 Calculate the height (in pixels) of the tab region of a ribbon bar. 2301 2302 Note that as the tab region can contain scroll buttons, the height should be 2303 greater than or equal to the minimum height for a tab scroll button. 2304 2305 :param `dc`: A device context to use when one is required for size calculations; 2306 :param `wnd`: The window onto which the tabs will eventually be drawn; 2307 :param `pages`: The tabs which will acquire the returned height. 2308 2309 """ 2310 2311 text_height = 0 2312 icon_height = 0 2313 2314 if len(pages) <= 1 and (self._flags & RIBBON_BAR_ALWAYS_SHOW_TABS) == 0: 2315 # To preserve space, a single tab need not be displayed. We still need 2316 # two pixels of border / padding though. 2317 return 2 2318 2319 if self._flags & RIBBON_BAR_SHOW_PAGE_LABELS: 2320 dc.SetFont(self._tab_label_font) 2321 text_height = dc.GetTextExtent("ABCDEFXj")[1] + 10 2322 2323 if self._flags & RIBBON_BAR_SHOW_PAGE_ICONS: 2324 for info in pages: 2325 if info.page.GetIcon().IsOk(): 2326 icon_height = max(icon_height, info.page.GetIcon().GetHeight() + 4) 2327 2328 return max(text_height, icon_height) 2329 2330 2331 def GetScrollButtonMinimumSize(self, dc, wnd, style): 2332 """ 2333 Calculate the minimum size (in pixels) of a scroll button. 2334 2335 :param `dc`: A device context to use when one is required for size calculations; 2336 :param `wnd`: The window onto which the scroll button will eventually be drawn; 2337 :param `style`: A combination of flags from `RibbonScrollButtonStyle`, including 2338 a direction, and a for flag (state flags may be given too, but should be ignored, 2339 as a button should retain a constant size, regardless of its state). 2340 2341 """ 2342 2343 return wx.Size(12, 12) 2344 2345 2346 def GetPanelSize(self, dc, wnd, client_size, client_offset=None): 2347 """ 2348 Calculate the size of a panel for a given client size. 2349 2350 This should increment the given size by enough to fit the panel label and other 2351 chrome. 2352 2353 :param `dc`: A device context to use if one is required for size calculations; 2354 :param `wnd`: The ribbon panel in question; 2355 :param `client_size`: The client size; 2356 :param `client_offset`: The offset where the client rectangle begins within the 2357 panel (may be ``None``). 2358 2359 :see: :meth:`~RibbonMSWArtProvider.GetPanelClientSize` 2360 """ 2361 2362 dc.SetFont(self._panel_label_font) 2363 label_size = wx.Size(*dc.GetTextExtent(wnd.GetLabel())) 2364 2365 client_size.IncBy(0, label_size.GetHeight()) 2366 2367 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 2368 client_size.IncBy(4, 8) 2369 else: 2370 client_size.IncBy(6, 6) 2371 2372 if client_offset != None: 2373 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 2374 client_offset = wx.Point(2, 3) 2375 else: 2376 client_offset = wx.Point(3, 2) 2377 2378 return client_size 2379 2380 2381 def GetPanelClientSize(self, dc, wnd, size, client_offset=None): 2382 """ 2383 Calculate the client size of a panel for a given overall size. 2384 2385 This should act as the inverse to :meth:`~RibbonMSWArtProvider.GetPanelSize`, and decrement the given size 2386 by enough to fit the panel label and other chrome. 2387 2388 :param `dc`: A device context to use if one is required for size calculations; 2389 :param `wnd`: The ribbon panel in question; 2390 :param `size`: The overall size to calculate client size for; 2391 :param `client_offset`: The offset where the returned client size begins within 2392 the given (may be ``None``). 2393 2394 :see: :meth:`~RibbonMSWArtProvider.GetPanelSize` 2395 """ 2396 2397 dc.SetFont(self._panel_label_font) 2398 label_size = wx.Size(*dc.GetTextExtent(wnd.GetLabel())) 2399 2400 size.DecBy(0, label_size.GetHeight()) 2401 2402 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 2403 size.DecBy(4, 8) 2404 else: 2405 size.DecBy(6, 6) 2406 2407 if client_offset != None: 2408 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 2409 client_offset = wx.Point(2, 3) 2410 else: 2411 client_offset = wx.Point(3, 2) 2412 2413 if size.x < 0: 2414 size.x = 0 2415 if size.y < 0: 2416 size.y = 0 2417 2418 return size, client_offset 2419 2420 2421 def GetGallerySize(self, dc, wnd, client_size): 2422 """ 2423 Calculate the size of a :class:`~wx.lib.agw.ribbon.gallery.RibbonGallery` control for a given client size. 2424 2425 This should increment the given size by enough to fit the gallery border, 2426 buttons, and any other chrome. 2427 2428 :param `dc`: A device context to use if one is required for size calculations; 2429 :param `wnd`: The gallery in question; 2430 :param `client_size`: The client size. 2431 2432 :see: :meth:`~RibbonMSWArtProvider.GetGalleryClientSize` 2433 """ 2434 2435 client_size.IncBy(2, 1) # Left / top padding 2436 2437 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 2438 client_size.IncBy(1, 16) # Right / bottom padding 2439 else: 2440 client_size.IncBy(16, 1) # Right / bottom padding 2441 2442 return client_size 2443 2444 2445 def GetGalleryClientSize(self, dc, wnd, size, client_offset=None, scroll_up_button=None, 2446 scroll_down_button=None, extension_button=None): 2447 2448 """ 2449 Calculate the client size of a :class:`~wx.lib.agw.ribbon.gallery.RibbonGallery` control for a given size. 2450 2451 This should act as the inverse to :meth:`~RibbonMSWArtProvider.GetGallerySize`, and decrement the given 2452 size by enough to fir the gallery border, buttons, and other chrome. 2453 2454 :param `dc`: A device context to use if one is required for size calculations; 2455 :param `wnd`: The gallery in question; 2456 :param `size`: The overall size to calculate the client size for; 2457 :param `client_offset`: The position within the given size at which the 2458 returned client size begins; 2459 :param `scroll_up_button`: The rectangle within the given size which the 2460 scroll up button occupies; 2461 :param `scroll_down_button`: The rectangle within the given size which the 2462 scroll down button occupies; 2463 :param `extension_button`: The rectangle within the given size which the 2464 extension button occupies. 2465 2466 """ 2467 2468 scroll_up = wx.Rect() 2469 scroll_down = wx.Rect() 2470 extension = wx.Rect() 2471 2472 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 2473 # Flow is vertical - put buttons on bottom 2474 scroll_up.y = size.GetHeight() - 15 2475 scroll_up.height = 15 2476 scroll_up.x = 0 2477 scroll_up.width = (size.GetWidth() + 2) / 3 2478 scroll_down.y = scroll_up.y 2479 scroll_down.height = scroll_up.height 2480 scroll_down.x = scroll_up.x + scroll_up.width 2481 scroll_down.width = scroll_up.width 2482 extension.y = scroll_down.y 2483 extension.height = scroll_down.height 2484 extension.x = scroll_down.x + scroll_down.width 2485 extension.width = size.GetWidth() - scroll_up.width - scroll_down.width 2486 size.DecBy(1, 16) 2487 size.DecBy(2, 1) 2488 2489 else: 2490 # Flow is horizontal - put buttons on right 2491 scroll_up.x = size.GetWidth() - 15 2492 scroll_up.width = 15 2493 scroll_up.y = 0 2494 scroll_up.height = (size.GetHeight() + 2) / 3 2495 scroll_down.x = scroll_up.x 2496 scroll_down.width = scroll_up.width 2497 scroll_down.y = scroll_up.y + scroll_up.height 2498 scroll_down.height = scroll_up.height 2499 extension.x = scroll_down.x 2500 extension.width = scroll_down.width 2501 extension.y = scroll_down.y + scroll_down.height 2502 extension.height = size.GetHeight() - scroll_up.height - scroll_down.height 2503 size.DecBy(16, 1) 2504 size.DecBy( 2, 1) 2505 2506 client_offset = wx.Point(2, 1) 2507 scroll_up_button = scroll_up 2508 scroll_down_button = scroll_down 2509 extension_button = extension 2510 2511 return size, client_offset, scroll_up_button, scroll_down_button, extension_button 2512 2513 2514 def GetPageBackgroundRedrawArea(self, dc, wnd, page_old_size, page_new_size): 2515 """ 2516 Calculate the portion of a page background which needs to be redrawn when a page 2517 is resized. 2518 2519 To optimise the drawing of page backgrounds, as small an area as possible should 2520 be returned. Of couse, if the way in which a background is drawn means that the 2521 entire background needs to be repainted on resize, then the entire new size 2522 should be returned. 2523 2524 :param `dc`: A device context to use when one is required for size calculations; 2525 :param `wnd`: The page which is being resized; 2526 :param `page_old_size`: The size of the page prior to the resize (which has 2527 already been painted); 2528 :param `page_new_size`: The size of the page after the resize. 2529 2530 """ 2531 2532 if page_new_size.GetWidth() != page_old_size.GetWidth(): 2533 if page_new_size.GetHeight() != page_old_size.GetHeight(): 2534 # Width and height both changed - redraw everything 2535 return wx.Rect(0, 0, *page_new_size) 2536 else: 2537 # Only width changed - redraw right hand side 2538 right_edge_width = 4 2539 new_rect = wx.Rect(page_new_size.GetWidth() - right_edge_width, 0, right_edge_width, page_new_size.GetHeight()) 2540 old_rect = wx.Rect(page_old_size.GetWidth() - right_edge_width, 0, right_edge_width, page_old_size.GetHeight()) 2541 2542 else: 2543 if page_new_size.GetHeight() == page_old_size.GetHeight(): 2544 # Nothing changed (should never happen) - redraw nothing 2545 return wx.Rect(0, 0, 0, 0) 2546 else: 2547 # Height changed - need to redraw everything (as the background 2548 # gradient is done vertically). 2549 return wx.Rect(0, 0, *page_new_size) 2550 2551 new_rect.Union(old_rect) 2552 new_rect.Intersect(wx.Rect(0, 0, *page_new_size)) 2553 return new_rect 2554 2555 2556 def GetButtonBarButtonSize(self, dc, wnd, kind, size, label, bitmap_size_large, bitmap_size_small, 2557 button_size=None, normal_region=None, dropdown_region=None): 2558 """ 2559 Calculate the size of a button within a :class:`~wx.lib.agw.ribbon.buttonbar.RibbonButtonBar`. 2560 2561 :param `dc`: A device context to use when one is required for size calculations; 2562 :param `wnd`: The window onto which the button will eventually be drawn 2563 (which is normally a :class:`~wx.lib.agw.ribbon.buttonbar.RibbonButtonBar`, though this is not guaranteed); 2564 :param `kind`: The kind of button; 2565 :param `size`: The size-class to calculate the size for. Buttons on a button 2566 bar can have three distinct sizes: ``RIBBON_BUTTONBAR_BUTTON_SMALL``, 2567 ``RIBBON_BUTTONBAR_BUTTON_MEDIUM``, and ``RIBBON_BUTTONBAR_BUTTON_LARGE``. 2568 If the requested size-class is not applicable, then ``False`` should be returned; 2569 :param `label`: The label of the button; 2570 :param `bitmap_size_large`: The size of all "large" bitmaps on the button bar; 2571 :param `bitmap_size_small`: The size of all "small" bitmaps on the button bar; 2572 :param `button_size`: The size, in pixels, of the button; 2573 :param `normal_region`: The region of the button which constitutes the normal button; 2574 :param `dropdown_region`: The region of the button which constitutes the dropdown button. 2575 2576 :returns: ``True`` if a size exists for the button, ``False`` otherwise. 2577 """ 2578 2579 drop_button_width = 8 2580 2581 normal_region = wx.Rect() 2582 dropdown_region = wx.Rect() 2583 2584 dc.SetFont(self._button_bar_label_font) 2585 result = size & RIBBON_BUTTONBAR_BUTTON_SIZE_MASK 2586 2587 if result == RIBBON_BUTTONBAR_BUTTON_SMALL: 2588 # Small bitmap, no label 2589 button_size = wx.Size(bitmap_size_small + wx.Size(6, 4)) 2590 2591 if kind in [RIBBON_BUTTON_NORMAL, RIBBON_BUTTON_TOGGLE]: 2592 normal_region = wx.Rect(0, 0, *button_size) 2593 dropdown_region = wx.Rect(0, 0, 0, 0) 2594 2595 elif kind == RIBBON_BUTTON_DROPDOWN: 2596 button_size += wx.Size(drop_button_width, 0) 2597 dropdown_region = wx.Rect(0, 0, *button_size) 2598 normal_region = wx.Rect(0, 0, 0, 0) 2599 2600 elif kind == RIBBON_BUTTON_HYBRID: 2601 normal_region = wx.Rect(0, 0, *button_size) 2602 dropdown_region = wx.Rect(button_size.GetWidth(), 0, drop_button_width, button_size.GetHeight()) 2603 button_size += wx.Size(drop_button_width, 0) 2604 2605 elif result == RIBBON_BUTTONBAR_BUTTON_MEDIUM: 2606 # Small bitmap, with label to the right 2607 is_supported, button_size, normal_region, dropdown_region = self.GetButtonBarButtonSize(dc, wnd, kind, 2608 RIBBON_BUTTONBAR_BUTTON_SMALL, 2609 label, bitmap_size_large, 2610 bitmap_size_small) 2611 text_size = dc.GetTextExtent(label)[0] 2612 button_size.SetWidth(button_size.GetWidth() + text_size) 2613 2614 if kind == RIBBON_BUTTON_DROPDOWN: 2615 dropdown_region.SetWidth(dropdown_region.GetWidth() + text_size) 2616 2617 elif kind == RIBBON_BUTTON_HYBRID: 2618 dropdown_region.SetX(dropdown_region.GetX() + text_size) 2619 normal_region.SetWidth(normal_region.GetWidth() + text_size) 2620 # no break 2621 elif kind in [RIBBON_BUTTON_NORMAL, RIBBON_BUTTON_TOGGLE]: 2622 normal_region.SetWidth(normal_region.GetWidth() + text_size) 2623 2624 elif result == RIBBON_BUTTONBAR_BUTTON_LARGE: 2625 # Large bitmap, with label below (possibly split over 2 lines) 2626 2627 icon_size = wx.Size(*bitmap_size_large) 2628 icon_size += wx.Size(4, 4) 2629 best_width, label_height = dc.GetTextExtent(label) 2630 last_line_extra_width = 0 2631 2632 if kind not in [RIBBON_BUTTON_NORMAL, RIBBON_BUTTON_TOGGLE]: 2633 last_line_extra_width += 8 2634 2635 for i in range(0, len(label)): 2636 if RibbonCanLabelBreakAtPosition(label, i): 2637 2638 width = max(dc.GetTextExtent(label[0:i])[0], 2639 dc.GetTextExtent(label[i+1:])[0] + last_line_extra_width) 2640 if width < best_width: 2641 best_width = width 2642 2643 label_height *= 2 # Assume two lines even when only one is used 2644 # (to give all buttons a consistent height) 2645 icon_size.SetWidth(max(icon_size.GetWidth(), best_width) + 6) 2646 icon_size.SetHeight(icon_size.GetHeight() + label_height) 2647 button_size = wx.Size(*icon_size) 2648 2649 if kind == RIBBON_BUTTON_DROPDOWN: 2650 dropdown_region = wx.Rect(0, 0, *icon_size) 2651 elif kind == RIBBON_BUTTON_HYBRID: 2652 normal_region = wx.Rect(0, 0, *icon_size) 2653 normal_region.height -= 2 + label_height 2654 dropdown_region.x = 0 2655 dropdown_region.y = normal_region.height 2656 dropdown_region.width = icon_size.GetWidth() 2657 dropdown_region.height = icon_size.GetHeight() - normal_region.height 2658 elif kind in [RIBBON_BUTTON_NORMAL, RIBBON_BUTTON_TOGGLE]: 2659 normal_region = wx.Rect(0, 0, *icon_size) 2660 2661 return True, button_size, normal_region, dropdown_region 2662 2663 2664 def GetMinimisedPanelMinimumSize(self, dc, wnd, desired_bitmap_size=None, expanded_panel_direction=None): 2665 """ 2666 Calculate the size of a minimised ribbon panel. 2667 2668 :param `dc`: A device context to use when one is required for size calculations; 2669 :param `wnd`: The ribbon panel in question. Attributes like the panel label can 2670 be queried from this; 2671 :param `desired_bitmap_size`: MISSING DESCRIPTION; 2672 :param `expanded_panel_direction`: MISSING DESCRIPTION. 2673 2674 """ 2675 2676 if desired_bitmap_size != None: 2677 desired_bitmap_size = wx.Size(16, 16) 2678 2679 if expanded_panel_direction != None: 2680 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 2681 expanded_panel_direction = wx.EAST 2682 else: 2683 expanded_panel_direction = wx.SOUTH 2684 2685 base_size = wx.Size(42, 42) 2686 2687 dc.SetFont(self._panel_label_font) 2688 label_size = wx.Size(*dc.GetTextExtent(wnd.GetLabel())) 2689 label_size.IncBy(2, 2) # Allow for differences between this DC and a paint DC 2690 label_size.IncBy(6, 0) # Padding 2691 label_size.y *= 2 # Second line for dropdown button 2692 2693 if self._flags & RIBBON_BAR_FLOW_VERTICAL: 2694 # Label alongside icon 2695 return wx.Size(base_size.x + label_size.x, max(base_size.y, label_size.y)), \ 2696 desired_bitmap_size, expanded_panel_direction 2697 else: 2698 # Label beneath icon 2699 return wx.Size(max(base_size.x, label_size.x), base_size.y + label_size.y), \ 2700 desired_bitmap_size, expanded_panel_direction 2701 2702 2703 def GetToolSize(self, dc, wnd, bitmap_size, kind, is_first, is_last, dropdown_region=None): 2704 """ 2705 Calculate the size of a tool within a :class:`~wx.lib.agw.ribbon.toolbar.RibbonToolBar`. 2706 2707 :param `dc`: A device context to use when one is required for size calculations; 2708 :param `wnd`: The window onto which the tool will eventually be drawn; 2709 :param `bitmap_size`: The size of the tool's foreground bitmap; 2710 :param `kind`: The kind of tool (normal, dropdown, or hybrid); 2711 :param `is_first`: ``True`` if the tool is the first within its group. ``False`` 2712 otherwise; 2713 :param `is_last`: ``True`` if the tool is the last within its group. ``False`` 2714 otherwise; 2715 :param `dropdown_region`: For dropdown and hybrid tools, the region within the 2716 returned size which counts as the dropdown part. 2717 """ 2718 2719 size = wx.Size(*bitmap_size) 2720 size.IncBy(7, 6) 2721 2722 if is_last: 2723 size.IncBy(1, 0) 2724 2725 if kind & RIBBON_BUTTON_DROPDOWN: 2726 size.IncBy(8, 0) 2727 if kind == RIBBON_BUTTON_DROPDOWN: 2728 dropdown_region = wx.Rect(0, 0, *size) 2729 else: 2730 dropdown_region = wx.Rect(size.GetWidth() - 8, 0, 8, size.GetHeight()) 2731 else: 2732 dropdown_region = wx.Rect(0, 0, 0, 0) 2733 2734 return size, dropdown_region 2735 2736