Custom frame (Phoenix)

Keywords : Shaped frame, Customized frame, Customized button, Transparency, Roll, Unroll, Fade in, Fade out, Shape, Region, BufferedPaintDC, BufferedDC, ClientDC, AcceleratorTable, Design.


Demonstrating :

Tested py3.x, wx4.x and Win10.

Do you ready to use some examples ? ;)

Test, modify, correct, improve and share your discoveries ! (!)


Shaped frame :

First example

skin_main_1.png

skin_about_1.png

   1 # sample_one.py
   2 
   3 import sys
   4 import os
   5 import platform
   6 import time
   7 import wx
   8 import wx.adv
   9 import wx.lib.fancytext as fancytext
  10 
  11 # class MyAboutDlg
  12 # class MyWindow
  13 # class MyButtonBox
  14 # class MyPanel
  15 # class MyFrame
  16 # class MyApp
  17 
  18 #-------------------------------------------------------------------------------
  19 
  20 class MyAboutDlg(wx.Frame):
  21     """
  22     Thanks to Robin Dunn.
  23     """
  24     def __init__(self, parent):
  25         style = (wx.FRAME_SHAPED | wx.SIMPLE_BORDER |
  26                  wx.CLIP_CHILDREN | wx.STAY_ON_TOP |
  27                  wx.SYSTEM_MENU | wx.CLOSE_BOX |
  28                  wx.NO_FULL_REPAINT_ON_RESIZE)
  29         wx.Frame.__init__(self,
  30                           parent,
  31                           id=-1,
  32                           title="About...",
  33                           style=style)
  34 
  35         #------------
  36 
  37         # Attributes.
  38         self.hasShape = False
  39         self.delta = wx.Point(0,0)
  40 
  41         #------------
  42 
  43         # Return application name.
  44         self.app_name = wx.GetApp().GetAppName()
  45         # Return bitmaps folder.
  46         self.bitmaps_dir = wx.GetApp().GetBitmapsDir()
  47         # Return icons folder.
  48         self.icons_dir = wx.GetApp().GetIconsDir()
  49 
  50         #------------
  51 
  52         # Simplified init method.
  53         self.SetProperties()
  54         self.CreateCtrls()
  55         self.BindEvents()
  56 
  57         #------------
  58 
  59         self.CenterOnParent(wx.BOTH)
  60         self.GetParent().Enable(False)
  61 
  62         #------------
  63 
  64         self.Show(True)
  65 
  66         #------------
  67 
  68         self.eventLoop = wx.GUIEventLoop()
  69         self.eventLoop.Run()
  70 
  71     #---------------------------------------------------------------------------
  72 
  73     def SetProperties(self):
  74         """
  75         Set the dialog properties (title, icon, transparency...).
  76         """
  77 
  78         self.SetTransparent(230)
  79 
  80         #------------
  81 
  82         frameIcon = wx.Icon(os.path.join(self.icons_dir,
  83                                          "icon_wxWidgets.ico"),
  84                             type=wx.BITMAP_TYPE_ICO)
  85         self.SetIcon(frameIcon)
  86 
  87 
  88     def CreateCtrls(self):
  89         """
  90         Make widgets for my dialog.
  91         """
  92 
  93         # Load a background bitmap.
  94         self.bmp = wx.Bitmap(os.path.join(self.bitmaps_dir,
  95                                           "skin_about_1.png"),
  96                              type=wx.BITMAP_TYPE_PNG)
  97         mask = wx.Mask(self.bmp, wx.RED)
  98         self.bmp.SetMask(mask)
  99 
 100         #------------
 101 
 102         self.SetClientSize((self.bmp.GetWidth(), self.bmp.GetHeight()))
 103 
 104         #------------
 105 
 106         if wx.Platform == "__WXGTK__":
 107             # wxGTK requires that the window be created before you can
 108             # set its shape, so delay the call to SetWindowShape until
 109             # this event.
 110             self.Bind(wx.EVT_WINDOW_CREATE, self.SetWindowShape)
 111         else:
 112             # On wxMSW and wxMac the window has already
 113             # been created, so go for it.
 114             self.SetWindowShape()
 115 
 116 
 117     def BindEvents(self):
 118         """
 119         Bind all the events related to my dialog.
 120         """
 121 
 122         # Bind some events to an events handler.
 123         self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
 124         self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
 125         self.Bind(wx.EVT_RIGHT_UP, self.OnCloseWindow)  # Panel right clic.
 126         self.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick)  # View mask.
 127         self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
 128         self.Bind(wx.EVT_WINDOW_CREATE, self.SetWindowShape)
 129         self.Bind(wx.EVT_MOTION, self.OnMouseMove)
 130         self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
 131         self.Bind(wx.EVT_PAINT, self.OnPaint)
 132 
 133         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
 134 
 135 
 136     def SetWindowShape(self, event=None):
 137         """
 138         ...
 139         """
 140 
 141         # Use the bitmap's mask to determine the region.
 142         r = wx.Region(self.bmp)
 143         self.hasShape = self.SetShape(r)
 144 
 145 
 146     def OnEraseBackground(self, event):
 147         """
 148         ...
 149         """
 150 
 151         dc = event.GetDC()
 152         if not dc:
 153             dc = wx.ClientDC(self)
 154             rect = self.GetUpdateRegion().GetBox()
 155             dc.SetClippingRect(rect)
 156 
 157 
 158     def OnDoubleClick(self, event):
 159         """
 160         ...
 161         """
 162 
 163         if self.hasShape:
 164             self.SetShape(wx.Region())
 165             self.hasShape = False
 166         else:
 167             self.SetWindowShape()
 168 
 169 
 170     def OnLeftDown(self, event):
 171         """
 172         ...
 173         """
 174 
 175         self.CaptureMouse()
 176         x, y = self.ClientToScreen(event.GetPosition())
 177         originx, originy = self.GetPosition()
 178         dx = x - originx
 179         dy = y - originy
 180         self.delta = ((dx, dy))
 181 
 182 
 183     def OnLeftUp(self, evt):
 184         """
 185         ...
 186         """
 187 
 188         if self.HasCapture():
 189             self.ReleaseMouse()
 190 
 191 
 192     def OnMouseMove(self, event):
 193         """
 194         ...
 195         """
 196 
 197         if event.Dragging() and event.LeftIsDown():
 198             x, y = self.ClientToScreen(event.GetPosition())
 199             fp = (x - self.delta[0], y - self.delta[1])
 200             self.Move(fp)
 201 
 202 
 203     def OnPaint(self, event):
 204         """
 205         ...
 206         """
 207 
 208         dc = wx.PaintDC(self)
 209         dc.DrawBitmap(self.bmp, -1, -1, True)
 210 
 211         #------------
 212 
 213         # These are strings.
 214         py_version = sys.version.split()[0]
 215 
 216         str1 = (('<font style="normal" family="default" color="yellow" size="10" weight="bold">'
 217                  'Programming : </font>'
 218                  '<font style="normal" family="default" color="white" size="10" weight="normal">'
 219                  'Python {}</font>').format(py_version))   # Python 3.6.5
 220 
 221         str2 = (('<font style="normal" family="default" color="red" size="10" weight="bold">'
 222                  'GUI toolkit : </font>'
 223                  '<font style="normal" family="default" color="white" size="10" weight="normal">'
 224                  'wxPython {}</font>').format(wx.VERSION_STRING))  # wxPython 4.0.2
 225 
 226         str3 = (('<font style="normal" family="default" color="brown" size="10" weight="bold">'
 227                  'Library : </font>'
 228                  '<font style="normal" family="default" color="white" size="10" weight="normal">'
 229                  '{}</font>').format(wx.GetLibraryVersionInfo().VersionString))   # wxWidgets 3.0.5
 230 
 231         str4 = (('<font style="normal" family="default" color="cyan" size="10" weight="bold">'
 232                  'Operating system : </font>'
 233                  '<font style="normal" family="default" color="white" size="10" weight="normal">'
 234                  '{}</font>').format(platform.system()))   # Windows
 235 
 236         str5 = (('<font style="normal" family="default" color="gray" size="9" weight="normal">'
 237                  '{}</font>').format(self.app_name))   # Custom Gui
 238 
 239         str6 = (('<font style="normal" family="default" color="White" size="8" weight="normal">'
 240                  'Right clic or Esc for Exit</font>'))
 241 
 242         #------------
 243 
 244         # Return main image size.
 245         bw, bh = self.bmp.GetWidth(), self.bmp.GetHeight()
 246 
 247         # Draw text.
 248         # Need width to calculate x position of str1.
 249         tw, th = fancytext.GetExtent(str1, dc)
 250         # Centered text.
 251         fancytext.RenderToDC(str1, dc, (bw-tw)/2, 50)
 252 
 253         #------------
 254 
 255         # Need width to calculate x position of str2.
 256         tw, th = fancytext.GetExtent(str2, dc)
 257         # Centered text.
 258         fancytext.RenderToDC(str2, dc, (bw-tw)/2, 70)
 259 
 260         #------------
 261 
 262         # Need width to calculate x position of str3.
 263         tw, th = fancytext.GetExtent(str3, dc)
 264         # Centered text.
 265         fancytext.RenderToDC(str3, dc, (bw-tw)/2, 90)
 266 
 267         #------------
 268 
 269         # Need width to calculate x position of str4.
 270         tw, th = fancytext.GetExtent(str4, dc)
 271         # Centered text.
 272         fancytext.RenderToDC(str4, dc, (bw-tw)/2, 110)
 273 
 274         #------------
 275 
 276         # Need width to calculate x position of str5.
 277         tw, th = fancytext.GetExtent(str5, dc)
 278         # Centered text.
 279         fancytext.RenderToDC(str5, dc, (bw-tw)/2, 150)
 280 
 281         #------------
 282 
 283         # Need width to calculate x position of str6.
 284         tw, th = fancytext.GetExtent(str6, dc)
 285         # Centered text.
 286         fancytext.RenderToDC(str6, dc, (bw-tw)/2, 185)
 287 
 288 
 289     def OnKeyUp(self, event):
 290         """
 291         ...
 292         """
 293 
 294         if event.GetKeyCode() == wx.WXK_ESCAPE:
 295             self.OnCloseWindow(event)
 296 
 297         event.Skip()
 298 
 299 
 300     def OnCloseWindow(self, event):
 301         """
 302         ...
 303         """
 304 
 305         self.GetParent().Enable(True)
 306         self.eventLoop.Exit()
 307         self.Destroy()
 308 
 309 #-------------------------------------------------------------------------------
 310 
 311 class MyWindow(wx.Control):
 312     """
 313     Thanks to Cody Precord.
 314     """
 315     def __init__(self, parent, label,
 316                  foreground, background,
 317                  normal, pressed=None, disabled=None):
 318         super(MyWindow, self).__init__(parent, -1,
 319                                        style=wx.BORDER_NONE)
 320 
 321         #------------
 322 
 323         # Attributes.
 324         self.label = label
 325         self.foreground = foreground
 326         self.background = background
 327 
 328         if wx.Platform == "__WXGTK__":
 329             self.color = "#9e9d9d"
 330 
 331         else:
 332             self.color = "#b1b1b0"
 333 
 334         self.normal = normal
 335         self.pressed = pressed
 336         self.disabled = disabled
 337 
 338         self._clicked = False
 339 
 340         #------------
 341 
 342         self.region = wx.Region(normal, wx.Colour(0, 0, 0, 0))
 343 
 344         #------------
 345 
 346         # Simplified init method.
 347         self.SetProperties(label, foreground, background)
 348         self.BindEvents()
 349 
 350     #---------------------------------------------------------------------------
 351 
 352     def SetProperties(self, label, foreground, background):
 353         """
 354         ...
 355         """
 356 
 357         self.label = label
 358         self.foreground = foreground
 359         self.background = background
 360         self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
 361 
 362 
 363     def BindEvents(self):
 364         """
 365         Bind some events to an events handler.
 366         """
 367 
 368         self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
 369         self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
 370         self.Bind(wx.EVT_PAINT, self.OnPaint)
 371         self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
 372         self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDclick)
 373         self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
 374         self.Bind(wx.EVT_MOTION, self.OnMotion)
 375         self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeave)
 376         self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
 377 
 378 
 379     def SetLabel(self, label):
 380         """
 381         ...
 382         """
 383 
 384         self.label = label
 385         self.Refresh()
 386 
 387 
 388     def DoGetBestSize(self):
 389         """
 390         ...
 391         """
 392 
 393         return self.normal.GetSize()
 394 
 395 
 396     def GetLabel(self):
 397         """
 398         ...
 399         """
 400 
 401         return self.label
 402 
 403 
 404     def GetLabelColor(self):
 405         """
 406         ...
 407         """
 408 
 409         return self.foreground
 410 
 411 
 412     def Enable(self, *args, **kwargs):
 413         """
 414         ...
 415         """
 416 
 417         super(MyWindow, self).Enable(*args, **kwargs)
 418         self.Refresh()
 419 
 420 
 421     def Disable(self, *args, **kwargs):
 422         """
 423         ...
 424         """
 425 
 426         super(MyWindow, self).Disable(*args, **kwargs)
 427         self.Refresh()
 428 
 429 
 430     def PostEvent(self):
 431         """
 432         ...
 433         """
 434 
 435         event = wx.CommandEvent()
 436         event.SetEventObject(self)
 437         event.SetEventType(wx.EVT_BUTTON.typeId)
 438         wx.PostEvent(self, event)
 439 
 440 
 441     def OnSize(self, event):
 442         """
 443         ...
 444         """
 445 
 446         event.Skip()
 447         self.Refresh()
 448 
 449 
 450     def Getbackground(self):
 451         """
 452         ...
 453         """
 454 
 455         return self.background
 456 
 457 
 458     def OnPaint(self, event):
 459         """
 460         ...
 461         """
 462 
 463         dc = wx.BufferedPaintDC(self)
 464         dc.Clear()
 465         gcdc = wx.GCDC(dc)
 466 
 467         # Set the background color.
 468         if wx.Platform == "__WXGTK__":
 469             gcdc.SetBackground(wx.Brush("grey55"))
 470         else:
 471             gcdc.SetBackground(wx.Brush(self.background))
 472 
 473         gcdc.Clear()
 474 
 475         # Get the working rectangle we can draw in.
 476         rect = self.GetClientRect()
 477 
 478         # Font size and style.
 479         fontSize = self.GetFont().GetPointSize()
 480 
 481         if wx.Platform == "__WXGTK__":
 482             boldFont = wx.Font(fontSize-1, wx.DEFAULT,
 483                                wx.NORMAL, wx.NORMAL, False, "")
 484         else:
 485             boldFont = wx.Font(fontSize+2, wx.DEFAULT,
 486                                wx.NORMAL, wx.BOLD, False, "")
 487 
 488         if wx.Platform == "__WXMSW__":
 489             pen = wx.Pen(self.color, 1, wx.SOLID)
 490 
 491         else:
 492             pen = wx.Pen(self.color, 1, wx.SOLID)
 493 
 494         gcdc.SetPen(pen)
 495 
 496         x, y = self.GetSize()
 497         # x, y , width, height, radius
 498         gcdc.DrawRoundedRectangle (0, 0, 71, 25, 3)
 499 
 500         bitmap = self.normal
 501 
 502         w, h = bitmap.GetWidth(), bitmap.GetHeight()
 503 
 504         if self.clicked:
 505             bitmap = self.pressed or bitmap
 506         if not self.IsEnabled():
 507             bitmap = self.normal or bitmap
 508 
 509         # Draw a bitmap with an alpha channel.
 510         # image, x, y, transparency.
 511         dc.DrawBitmap(bitmap, 0, 0, True)
 512 
 513         if wx.Platform == "__WXGTK__":
 514             # Add the Caption.
 515             # White text - Shadow.
 516             rect = wx.Rect(rect.x, rect.y+3,
 517                            rect.width, 22)
 518 
 519         else:
 520             rect = wx.Rect(rect.x, rect.y+3,
 521                            rect.width, 20)
 522 
 523         dc.SetFont(boldFont)
 524         dc.SetTextForeground(wx.WHITE)
 525         dc.DrawLabel(self.label, rect, wx.ALIGN_CENTER)
 526 
 527         if wx.Platform == "__WXGTK__":
 528             # Add the Caption.
 529             # Black text.
 530             rect = wx.Rect(rect.x, rect.y,
 531                            rect.width, 21)
 532 
 533         else:
 534             rect = wx.Rect(rect.x, rect.y,
 535                            rect.width, 19)
 536 
 537         gcdc.SetFont(boldFont)
 538         # Get the text color.
 539         dc.SetTextForeground(self.foreground)
 540         dc.DrawLabel(self.label, rect, wx.ALIGN_CENTER)
 541 
 542 
 543     def SetClicked(self, clicked):
 544         """
 545         ...
 546         """
 547 
 548         if clicked != self._clicked:
 549             self._clicked = clicked
 550             self.Refresh()
 551 
 552 
 553     def GetClicked(self):
 554         """
 555         ...
 556         """
 557 
 558         return self._clicked
 559 
 560 
 561     clicked = property(GetClicked, SetClicked)
 562     def OnLeftDown(self, event):
 563         """
 564         ...
 565         """
 566 
 567         x, y = event.GetPosition()
 568         if self.region.Contains(x, y):
 569             self.clicked = True
 570             self.SetFocus()
 571 
 572 
 573     def OnLeftDclick(self, event):
 574         """
 575         ...
 576         """
 577 
 578         self.OnLeftDown(event)
 579 
 580 
 581     def OnLeftUp(self, event):
 582         """
 583         ...
 584         """
 585 
 586         if self.clicked:
 587             x, y = event.GetPosition()
 588             if self.region.Contains(x, y):
 589                 self.PostEvent()
 590         self.clicked = False
 591 
 592 
 593     def OnMotion(self, event):
 594         """
 595         ...
 596         """
 597 
 598         if self.clicked:
 599             x, y = event.GetPosition()
 600             if not self.region.Contains(x, y):
 601                 self.clicked = False
 602 
 603 
 604     def OnLeave(self, event):
 605         """
 606         ...
 607         """
 608 
 609         self.clicked = False
 610 
 611 
 612     def OnSetFocus(self, event):
 613         """
 614         ...
 615         """
 616 
 617         self.color = "white"
 618         self.Refresh()
 619 
 620 
 621     def OnKillFocus(self, event):
 622         """
 623         ...
 624         """
 625 
 626         if wx.Platform == "__WXGTK__":
 627             self.color = "#9e9d9d"
 628 
 629         else:
 630             self.color = "#b1b1b0"
 631 
 632         self.Refresh()
 633 
 634 
 635     def OnKeyUp(self, event):
 636         """
 637         ...
 638         """
 639 
 640         if event.GetKeyCode() == wx.WXK_SPACE:
 641             self.PostEvent()
 642             return
 643 
 644         elif event.GetKeyCode() == wx.WXK_ESCAPE:
 645             self.GetTopLevelParent().OnCloseWindow(True)
 646 
 647         event.Skip()
 648 
 649 #-------------------------------------------------------------------------------
 650 
 651 class MyButtonBox(wx.Panel):
 652     """
 653     Thanks to Cody Precord.
 654     """
 655     def __init__(self, parent, caption):
 656         super(MyButtonBox, self).__init__(parent,
 657                                            style=wx.NO_BORDER |
 658                                            wx.TAB_TRAVERSAL)
 659 
 660         #------------
 661 
 662         # Attributes.
 663         self._caption = caption
 664 
 665         #------------
 666 
 667         # Simplified init method.
 668         self.DoLayout()
 669 
 670     #---------------------------------------------------------------------------
 671 
 672     def DoLayout(self):
 673         """
 674         ...
 675         """
 676 
 677         self._csizer = wx.BoxSizer(wx.VERTICAL)
 678         msizer = wx.BoxSizer(wx.HORIZONTAL)
 679         msizer.Add(self._csizer, 0 )
 680         self.SetSizer(msizer)
 681 
 682 
 683     def DoGetBestSize(self):
 684         """
 685         ...
 686         """
 687 
 688         size = super(MyButtonBox, self).DoGetBestSize()
 689 
 690         # Compensate for wide caption labels.
 691         tw = self.GetTextExtent(self._caption)[0]
 692         size.SetWidth(max(size.width, size.height))
 693         return size
 694 
 695 
 696     def AddItem(self, item):
 697         """
 698         Add a window or sizer item to the MyButtonBox.
 699         """
 700 
 701         self._csizer.Add(item, 0 )
 702 
 703 #-------------------------------------------------------------------------------
 704 
 705 class MyPanel(wx.Panel):
 706     """
 707     Thanks to Cody Precord.
 708     """
 709     def __init__(self, parent):
 710         wx.Panel.__init__(self, parent)
 711 
 712         #------------
 713 
 714         # Return bitmaps folder.
 715         self.bitmaps_dir = wx.GetApp().GetBitmapsDir()
 716 
 717         #------------
 718 
 719         # Create a timer.
 720         self.timer = wx.Timer(self)
 721         self.timer.Start(1000)
 722         self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
 723 
 724         #------------
 725 
 726         # Simplified init method.
 727         self.SetProperties()
 728         self.CreateCtrls()
 729         self.BindEvents()
 730 
 731     #---------------------------------------------------------------------------
 732 
 733     def SetProperties(self):
 734         """
 735         ...
 736         """
 737 
 738         self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
 739 
 740 
 741     def CreateCtrls(self):
 742         """
 743         ...
 744         """
 745 
 746         # Load an background bitmap.
 747         self.bitmap = wx.Bitmap(os.path.join(self.bitmaps_dir,
 748                                              "skin_main_1.png"),
 749                                 type=wx.BITMAP_TYPE_PNG)
 750 
 751         #------------
 752 
 753         # Buttons box.
 754         self.box1 = MyButtonBox(self, "")   # Button About.
 755         self.box2 = MyButtonBox(self, "")   # Button Quit.
 756 
 757         #------------
 758 
 759         # Buttons bitmap.
 760         bmp1 = wx.Bitmap(os.path.join(self.bitmaps_dir,
 761                                       "btn_exit_normal.png"),
 762                          type=wx.BITMAP_TYPE_PNG)
 763 
 764         bmp2 = wx.Bitmap(os.path.join(self.bitmaps_dir,
 765                                       "btn_exit_pressed.png"),
 766                          type=wx.BITMAP_TYPE_PNG)
 767 
 768         bmp3 = wx.Bitmap(os.path.join(self.bitmaps_dir,
 769                                       "btn_exit_disabled.png"),
 770                          type=wx.BITMAP_TYPE_PNG)
 771 
 772         bmpA = wx.Bitmap(os.path.join(self.bitmaps_dir,
 773                                       "btn_about_normal.png"),
 774                          type=wx.BITMAP_TYPE_PNG)
 775 
 776         bmpB = wx.Bitmap(os.path.join(self.bitmaps_dir,
 777                                       "btn_about_pressed.png"),
 778                          type=wx.BITMAP_TYPE_PNG)
 779 
 780         bmpC = wx.Bitmap(os.path.join(self.bitmaps_dir,
 781                                       "btn_about_disabled.png"),
 782                          type=wx.BITMAP_TYPE_PNG)
 783 
 784         # Buttons panel.
 785         self.btn1 = MyWindow(self.box1, "", "black", "#9e9d9d", bmpA, bmpB, bmpC)
 786         self.btn1.SetToolTip("This is a customized button.")
 787         self.btn1.Bind(wx.EVT_BUTTON, self.OnBtnAbout)
 788         self.btn1.SetFocus() # Necessary for Linux.
 789 
 790         self.btn2 = MyWindow(self.box2, "", "black", "#9e9d9d", bmp1, bmp2, bmp3)
 791         self.btn2.SetToolTip("This is a customized button.")
 792         self.btn2.Bind(wx.EVT_BUTTON, self.OnBtnClose)
 793         # self.btn2.Enable(False)
 794 
 795         # Return main image size.
 796         bw, bh = self.bitmap.GetWidth(), self.bitmap.GetHeight()
 797 
 798         self.box1.AddItem(self.btn1)
 799         self.box2.AddItem(self.btn2)
 800 
 801         self.box1.SetPosition(((bw-21+170)/2, 50))
 802         self.box1.SetSize((21, 21))
 803 
 804         self.box2.SetPosition(((bw-50)/2, 415))
 805         self.box2.SetSize((50, 50))
 806 
 807 
 808     def BindEvents(self):
 809         """
 810         Bind some events to an events handler.
 811         """
 812 
 813         self.Bind(wx.EVT_PAINT, self.OnPaint)
 814         self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
 815 
 816 
 817     def OnEraseBackground(self, event):
 818         """
 819         ...
 820         """
 821 
 822         dc = event.GetDC()
 823         if not dc:
 824             dc = wx.ClientDC(self)
 825             rect = self.GetUpdateRegion().GetBox()
 826             dc.SetClippingRect(rect)
 827 
 828 
 829     def OnBtnAbout(self, event):
 830         """
 831         ...
 832         """
 833 
 834         self.GetParent().OnAbout(True)
 835 
 836         print("About button was clicked.")
 837 
 838 
 839     def OnBtnClose(self, event):
 840         """
 841         ...
 842         """
 843 
 844         self.GetParent().OnCloseWindow(self)
 845 
 846         print("Close button was clicked.")
 847 
 848 
 849     def Draw(self, dc):
 850         """
 851         ...
 852         """
 853 
 854         # Draw a bitmap with an alpha channel
 855         # on top of the last group.
 856         # image, x, y, transparence
 857         dc.DrawBitmap(self.bitmap, 0, 0, True)
 858 
 859         #------------
 860 
 861         fontSize = self.GetFont().GetPointSize()
 862 
 863         # wx.Font(pointSize, family, style, weight, underline, faceName)
 864         if wx.Platform == "__WXMAC__":
 865             self.normalBoldFont = wx.Font(fontSize-1,
 866                                           wx.DEFAULT, wx.NORMAL,
 867                                           wx.NORMAL, False, "")
 868             self.normalFont = wx.Font(fontSize-2,
 869                                           wx.DEFAULT, wx.NORMAL,
 870                                       wx.NORMAL, False, "")
 871 
 872         elif wx.Platform == "__WXGTK__":
 873             self.normalBoldFont = wx.Font(fontSize-1,
 874                                           wx.DEFAULT, wx.NORMAL,
 875                                           wx.NORMAL, False, "")
 876             self.normalFont = wx.Font(fontSize-2,
 877                                       wx.DEFAULT, wx.NORMAL,
 878                                       wx.NORMAL, False, "")
 879 
 880         else:
 881             self.normalBoldFont = wx.Font(fontSize+23,
 882                                           wx.DEFAULT, wx.NORMAL,
 883                                           wx.NORMAL, False, "")
 884             self.normalFont = wx.Font(fontSize+1,
 885                                       wx.DEFAULT, wx.NORMAL,
 886                                       wx.NORMAL, False, "")
 887 
 888         dc.SetFont(self.normalFont)
 889         dc.SetFont(self.normalBoldFont)
 890 
 891         #------------
 892 
 893         # Return main image size.
 894         bw, bh = self.bitmap.GetWidth(), self.bitmap.GetHeight()
 895 
 896         # Draw text.
 897         dc.SetTextForeground("#8e8e8e")
 898         dc.SetFont(self.normalFont)
 899         date = time.strftime("%A %d %B %Y")
 900         tw, th = dc.GetTextExtent(date)
 901         dc.DrawText(date, (bw-tw)/2, 143)
 902 
 903         dc.SetTextForeground(wx.WHITE)
 904         dc.SetFont(self.normalBoldFont)
 905         hour = time.strftime("%H:%M:%S")  # "%I:%M:%S %p"
 906         tw, th = dc.GetTextExtent(hour)
 907         dc.DrawText(hour, (bw-tw)/2, 100)
 908 
 909 
 910     def OnTimer(self, event):
 911         """
 912         ...
 913         """
 914 
 915         dc = wx.BufferedDC(wx.ClientDC(self))
 916         self.Draw(dc)
 917         self.Refresh()   # Mac
 918 
 919 
 920     def OnPaint(self, event):
 921         """
 922         ...
 923         """
 924 
 925         dc = wx.BufferedPaintDC(self)
 926         dc.Clear()
 927 
 928         self.Draw(dc)
 929 
 930 #-------------------------------------------------------------------------------
 931 
 932 class MyFrame(wx.Frame):
 933     """
 934     Thanks to Robin Dunn.
 935     """
 936     def __init__(self):
 937         style = (wx.CLIP_CHILDREN | wx.CLOSE_BOX |
 938                  wx.MINIMIZE_BOX | wx.SYSTEM_MENU |
 939                  wx.NO_BORDER | wx.FRAME_SHAPED |
 940                  wx.NO_FULL_REPAINT_ON_RESIZE)
 941         wx.Frame.__init__(self, None, -1, title="", style=style)
 942 
 943         #------------
 944 
 945         # Attributes.
 946         self.SetTransparent(0)
 947         self.opacity_in = 0
 948         self.opacity_out = 250
 949         self.deltaN = -5
 950         self.hasShape = False
 951         self.delta = wx.Point(0,0)
 952 
 953         #------------
 954 
 955         # Return application name.
 956         self.app_name = wx.GetApp().GetAppName()
 957         # Return bitmaps folder.
 958         self.bitmaps_dir = wx.GetApp().GetBitmapsDir()
 959         # Return icons folder.
 960         self.icons_dir = wx.GetApp().GetIconsDir()
 961 
 962         #------------
 963 
 964         # Simplified init method.
 965         self.SetProperties()
 966         self.OnTimerIn(self)
 967         self.CreateCtrls()
 968         self.BindEvents()
 969         self.DoLayout()
 970 
 971         #------------
 972 
 973         self.CenterOnScreen(wx.BOTH)
 974 
 975         #------------
 976 
 977         self.Show(True)
 978 
 979     #---------------------------------------------------------------------------
 980 
 981     def OnTimerIn(self, evt):
 982         """
 983         Thanks to Pascal Faut.
 984         """
 985 
 986         self.timer1 = wx.Timer(self, -1)
 987         self.timer1.Start(1)
 988         self.Bind(wx.EVT_TIMER, self.AlphaCycle1, self.timer1)
 989 
 990         print("Fade-in was launched.")
 991 
 992 
 993     def OnTimerOut(self, evt):
 994         """
 995         Thanks to Pascal Faut.
 996         """
 997 
 998         self.timer2 = wx.Timer(self, -1)
 999         self.timer2.Start(1)
1000         self.Bind(wx.EVT_TIMER, self.AlphaCycle2, self.timer2)
1001 
1002         print("Fade-out was launched.")
1003 
1004 
1005     def AlphaCycle1(self, *args):
1006         """
1007         Thanks to Pascal Faut.
1008         """
1009 
1010         self.opacity_in += self.deltaN
1011         if self.opacity_in <= 0:
1012             self.deltaN = -self.deltaN
1013             self.opacity_in = 0
1014 
1015         if self.opacity_in >= 250:
1016             self.deltaN = -self.deltaN
1017             self.opacity_in = 250
1018 
1019             self.timer1.Stop()
1020 
1021         self.SetTransparent(self.opacity_in)
1022 
1023         print("Fade in = {}/255".format(self.opacity_in))
1024 
1025 
1026     def AlphaCycle2(self, *args):
1027         """
1028         Thanks to Pascal Faut.
1029         """
1030 
1031         self.opacity_out += self.deltaN
1032         if self.opacity_out >= 250:
1033             self.deltaN = -self.deltaN
1034             self.opacity_out = 250
1035 
1036             self.timer2.Stop()
1037 
1038         if self.opacity_out <= 0:
1039             self.deltaN = -self.deltaN
1040             self.opacity_out = 0
1041 
1042             wx.CallAfter(self.Destroy)
1043 
1044         self.SetTransparent(self.opacity_out)
1045 
1046         print("Fade out = {}/255".format(self.opacity_out))
1047 
1048 
1049     def SetProperties(self):
1050         """
1051         ...
1052         """
1053 
1054         self.SetTitle(self.app_name)
1055         self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
1056 
1057         frameIcon = wx.Icon(os.path.join(self.icons_dir,
1058                                          "icon_wxWidgets.ico"),
1059                             type=wx.BITMAP_TYPE_ICO)
1060         self.SetIcon(frameIcon)
1061 
1062 
1063     def CreateCtrls(self):
1064         """
1065         ...
1066         """
1067 
1068         self.panel = MyPanel(self)
1069 
1070         #------------
1071 
1072         # Load a background bitmap.
1073         self.bmp = wx.Bitmap(os.path.join(self.bitmaps_dir,
1074                                           "skin_main_1.png"),
1075                              type=wx.BITMAP_TYPE_PNG)
1076         mask = wx.Mask(self.bmp, wx.RED)
1077         self.bmp.SetMask(mask)
1078 
1079         self.SetClientSize((self.bmp.GetWidth(), self.bmp.GetHeight()))
1080 
1081         #------------
1082 
1083         if wx.Platform == "__WXGTK__":
1084             # wxGTK requires that the window be created before you can
1085             # set its shape, so delay the call to SetWindowShape until
1086             # this event.
1087             self.Bind(wx.EVT_WINDOW_CREATE, self.SetWindowShape)
1088         else:
1089             # On wxMSW and wxMac the window has
1090             # already been created, so go for it.
1091             self.SetWindowShape()
1092 
1093         # Create an accelerator table.
1094         self.accel_tbl = wx.AcceleratorTable([(wx.ACCEL_CTRL, ord('X'), wx.ID_EXIT),
1095                                               (wx.ACCEL_CTRL, ord('A'), wx.ID_ABOUT)
1096                                              ])
1097         self.SetAcceleratorTable(self.accel_tbl)
1098 
1099 
1100     def BindEvents(self):
1101         """
1102         Bind some events to an events handle.
1103         """
1104 
1105         self.panel.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick)  # View mask.
1106         self.panel.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
1107         self.panel.Bind(wx.EVT_RIGHT_UP, self.OnCloseWindow)  # Panel right clic.
1108 
1109         self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
1110         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
1111         self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
1112         self.Bind(wx.EVT_MOTION, self.OnMouseMove)
1113 
1114         self.Bind(wx.EVT_MENU, self.OnCloseWindow, id=wx.ID_EXIT)  # Ctrl+X.
1115         self.Bind(wx.EVT_MENU, self.OnAbout, id=wx.ID_ABOUT)
1116 
1117 
1118     def DoLayout(self):
1119         """
1120         ...
1121         """
1122 
1123         sizer = wx.BoxSizer(wx.VERTICAL)
1124         sizer.Add(self.panel, 1, wx.EXPAND)
1125         self.SetSizer(sizer)
1126 
1127 
1128     def OnAbout(self, event):
1129         """
1130         ...
1131         """
1132 
1133         self.dialog = MyAboutDlg(self)
1134 
1135 
1136     def SetWindowShape(self, *evt):
1137         """
1138         ...
1139         """
1140 
1141         # Use the bitmap's mask to determine the region.
1142         r = wx.Region(self.bmp)
1143         self.hasShape = self.SetShape(r)
1144 
1145 
1146     def OnEraseBackground(self, event):
1147         """
1148         ...
1149         """
1150 
1151         dc = event.GetDC()
1152         if not dc:
1153             dc = wx.ClientDC(self)
1154             rect = self.GetUpdateRegion().GetBox()
1155             dc.SetClippingRect(rect)
1156 
1157 
1158     def OnDoubleClick(self, event):
1159         """
1160         ...
1161         """
1162 
1163         if self.hasShape:
1164             self.SetShape(wx.Region())
1165             self.hasShape = False
1166         else:
1167             self.SetWindowShape()
1168 
1169 
1170     def OnLeftDown(self, event):
1171         """
1172         ...
1173         """
1174 
1175         self.CaptureMouse()
1176         x, y = self.ClientToScreen(event.GetPosition())
1177         originx, originy = self.GetPosition()
1178         dx = x - originx
1179         dy = y - originy
1180         self.delta = ((dx, dy))
1181 
1182 
1183     def OnLeftUp(self, evt):
1184         """
1185         ...
1186         """
1187 
1188         if self.HasCapture():
1189             self.ReleaseMouse()
1190 
1191 
1192     def OnMouseMove(self, event):
1193         """
1194         ...
1195         """
1196 
1197         if event.Dragging() and event.LeftIsDown():
1198             x, y = self.ClientToScreen(event.GetPosition())
1199             fp = (x - self.delta[0], y - self.delta[1])
1200             self.Move(fp)
1201 
1202 
1203     def OnIconize(self, event):
1204         """
1205         ...
1206         """
1207 
1208         self.Iconize()
1209 
1210 
1211     def OnCloseWindow(self, event):
1212         """
1213         Quit this application.
1214         """
1215 
1216         self.OnTimerOut(self)
1217 
1218         print("Exit application.")
1219 
1220 #-------------------------------------------------------------------------------
1221 
1222 class MyApp(wx.App):
1223     """
1224     Thanks to Andrea Gavana.
1225     """
1226     def OnInit(self):
1227 
1228         #------------
1229 
1230         self.locale = wx.Locale(wx.LANGUAGE_FRENCH)
1231 
1232         #------------
1233 
1234         self.SetAppName("Custom Gui")
1235 
1236         #------------
1237 
1238         self.installDir = os.path.split(os.path.abspath(sys.argv[0]))[0]
1239 
1240         #------------
1241 
1242         frame = MyFrame()
1243         self.SetTopWindow(frame)
1244         frame.Show(True)
1245 
1246         return True
1247 
1248     #---------------------------------------------------------------------------
1249 
1250     def GetInstallDir(self):
1251         """
1252         Returns the installation directory for my application.
1253         """
1254 
1255         return self.installDir
1256 
1257 
1258     def GetIconsDir(self):
1259         """
1260         Returns the icons directory for my application.
1261         """
1262 
1263         icons_dir = os.path.join(self.installDir, "icons")
1264         return icons_dir
1265 
1266 
1267     def GetBitmapsDir(self):
1268         """
1269         Returns the bitmaps directory for my application.
1270         """
1271 
1272         bitmaps_dir = os.path.join(self.installDir, "bitmaps")
1273         return bitmaps_dir
1274 
1275 #-------------------------------------------------------------------------------
1276 
1277 def main():
1278     app = MyApp(False)
1279     app.MainLoop()
1280 
1281 #-------------------------------------------------------------------------------
1282 
1283 if __name__ == "__main__" :
1284     main()


Second example

skin_main_2.png

skin_about_2.png

titlebar_2.png

   1 # sample_two.py
   2 
   3 import sys
   4 import os
   5 import platform
   6 import time
   7 import wx
   8 import wx.adv
   9 import wx.lib.fancytext as fancytext
  10 
  11 # class MyTitleBar
  12 # class MyAboutDlg
  13 # class MyPopupMenu
  14 # class MyWindow
  15 # class MyButtonBox
  16 # class MyPanel
  17 # class MyFrame
  18 # class MyApp
  19 
  20 #-------------------------------------------------------------------------------
  21 
  22 class MyTitleBar(wx.Control):
  23     """
  24     Thanks to Cody Precord.
  25     """
  26     def __init__(self, parent, label, size):
  27         super(MyTitleBar, self).__init__(parent, style=wx.BORDER_SIMPLE)
  28 
  29         #------------
  30 
  31         # Attributes.
  32         self.parent = parent
  33         self.label = label
  34         self.size = size
  35 
  36         #------------
  37 
  38         # Simplified init method.
  39         self.SetBackground()
  40         self.SetProperties(label, size)
  41         self.BindEvents()
  42 
  43     #-----------------------------------------------------------------------
  44 
  45     def SetBackground(self):
  46         """
  47         ...
  48         """
  49 
  50         self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
  51 
  52 
  53     def SetProperties(self, label, size):
  54         """
  55         ...
  56         """
  57 
  58         self.label = label
  59         self.size = size
  60 
  61         self.label_font = self.GetFont()
  62         self.label_font.SetFamily(wx.SWISS)
  63         self.label_font.SetPointSize(size)
  64         self.label_font.SetWeight(wx.BOLD)
  65         self.SetFont(self.label_font)
  66 
  67 
  68     def BindEvents(self):
  69         """
  70         Bind some events to an events handler.
  71         """
  72 
  73         self.Bind(wx.EVT_PAINT, self.OnPaint)
  74         self.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick)  # View mask.
  75         self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
  76         self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
  77 
  78 
  79     def OnLeftDown(self, event):
  80         """
  81         ...
  82         """
  83 
  84         self.GetTopLevelParent().OnLeftDown(event)
  85 
  86 
  87     def OnLeftUp(self, event):
  88         """
  89         ...
  90         """
  91 
  92         self.GetTopLevelParent().OnLeftUp(event)
  93 
  94 
  95     def OnDoubleClick(self, event):
  96         """
  97         ...
  98         """
  99 
 100         self.GetTopLevelParent().OnDoubleClick(event)
 101 
 102 
 103     def SetLabel(self, label):
 104         """
 105         ...
 106         """
 107 
 108         self.label = label
 109         self.Refresh()
 110 
 111 
 112     def DoGetBestSize(self):
 113         """
 114         ...
 115         """
 116 
 117         dc = wx.ClientDC(self)
 118         dc.SetFont(self.GetFont())
 119 
 120         textWidth, textHeight = dc.GetTextExtent(self.label)
 121         spacing = 10
 122         totalWidth = textWidth + (spacing)
 123         totalHeight = textHeight + (spacing)
 124 
 125         best = wx.Size(totalWidth, totalHeight)
 126         self.CacheBestSize(best)
 127 
 128         return best
 129 
 130 
 131     def GetLabel(self):
 132         """
 133         ...
 134         """
 135 
 136         return self.label
 137 
 138 
 139     def GetLabelColor(self):
 140         """
 141         ...
 142         """
 143 
 144         return self.foreground
 145 
 146 
 147     def GetLabelSize(self):
 148         """
 149         ...
 150         """
 151 
 152         return self.size
 153 
 154 
 155     def SetLabelColour(self, colour):
 156         """
 157         ...
 158         """
 159 
 160         self.labelColour = colour
 161 
 162 
 163     def OnPaint(self, event):
 164         """
 165         ...
 166         """
 167 
 168         dc = wx.BufferedPaintDC(self)
 169         gcdc = wx.GCDC(dc)
 170 
 171         gcdc.Clear()
 172 
 173         # Setup the GraphicsContext.
 174         gc = gcdc.GetGraphicsContext()
 175 
 176         # Get the working size we can draw in.
 177         width, height = self.GetSize()
 178 
 179         # Use the GCDC to draw the text.
 180         gcdc.GradientFillLinear((0, 0, width, height+70), "#3D3D3D",
 181                                 wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENU),
 182                                 wx.NORTH)
 183 
 184         # Get the system font.
 185         gcdc.SetFont(self.GetFont())
 186 
 187         textWidth, textHeight = gcdc.GetTextExtent(self.label)
 188         tposx, tposy = ((width/2)-(textWidth/2), (height/3)-(textHeight/3))
 189 
 190         tposx += 0
 191         tposy += 0
 192 
 193         # Set position and text color.
 194         gcdc.SetTextForeground("white")
 195         gcdc.DrawText(self.label, tposx-25, tposy+1)
 196 
 197         gcdc.SetTextForeground(self.labelColour)
 198         gcdc.DrawText(self.label, tposx-25, tposy)
 199 
 200 #-------------------------------------------------------------------------------
 201 
 202 class MyAboutDlg(wx.Frame):
 203     """
 204     Thanks to Robin Dunn.
 205     """
 206     def __init__(self, parent):
 207         style = (wx.FRAME_SHAPED | wx.NO_BORDER |
 208                  wx.CLIP_CHILDREN | wx.STAY_ON_TOP |
 209                  wx.SYSTEM_MENU | wx.CLOSE_BOX |
 210                  wx.NO_FULL_REPAINT_ON_RESIZE)
 211         wx.Frame.__init__(self,
 212                           parent,
 213                           id=-1,
 214                           title="About...",
 215                           style=style)
 216 
 217         #------------
 218 
 219         # Attributes.
 220         self.hasShape = False
 221         self.delta = wx.Point(0,0)
 222 
 223         #------------
 224 
 225         # Return application name.
 226         self.app_name = wx.GetApp().GetAppName()
 227         # Return bitmaps folder.
 228         self.bitmaps_dir = wx.GetApp().GetBitmapsDir()
 229         # Return icons folder.
 230         self.icons_dir = wx.GetApp().GetIconsDir()
 231 
 232         #------------
 233 
 234         # Simplified init method.
 235         self.SetProperties()
 236         self.CreateCtrls()
 237         self.BindEvents()
 238 
 239         #------------
 240 
 241         self.CenterOnParent(wx.BOTH)
 242         self.GetParent().Enable(False)
 243 
 244         #------------
 245 
 246         self.Show(True)
 247 
 248         #------------
 249 
 250         self.eventLoop = wx.GUIEventLoop()
 251         self.eventLoop.Run()
 252 
 253     #---------------------------------------------------------------------------
 254 
 255     def SetProperties(self):
 256         """
 257         Set the dialog properties (title, icon, transparency...).
 258         """
 259 
 260         self.SetTransparent(230)
 261 
 262         #------------
 263 
 264         frameIcon = wx.Icon(os.path.join(self.icons_dir,
 265                                          "icon_wxWidgets.ico"),
 266                             type=wx.BITMAP_TYPE_ICO)
 267         self.SetIcon(frameIcon)
 268 
 269 
 270     def CreateCtrls(self):
 271         """
 272         Make widgets for my dialog.
 273         """
 274 
 275         # Load a background bitmap.
 276         self.bmp = wx.Bitmap(os.path.join(self.bitmaps_dir,
 277                                           "skin_about.png"),
 278                              type=wx.BITMAP_TYPE_PNG)
 279         mask = wx.Mask(self.bmp, wx.RED)
 280         self.bmp.SetMask(mask)
 281 
 282         #------------
 283 
 284         self.SetClientSize((self.bmp.GetWidth(), self.bmp.GetHeight()))
 285 
 286         #------------
 287 
 288         if wx.Platform == "__WXGTK__":
 289             # wxGTK requires that the window be created before you can
 290             # set its shape, so delay the call to SetWindowShape until
 291             # this event.
 292             self.Bind(wx.EVT_WINDOW_CREATE, self.SetWindowShape)
 293         else:
 294             # On wxMSW and wxMac the window has already
 295             # been created, so go for it.
 296             self.SetWindowShape()
 297 
 298 
 299     def BindEvents(self):
 300         """
 301         Bind all the events related to my dialog.
 302         """
 303 
 304         # Bind some events to an events handler.
 305         self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
 306         self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
 307         self.Bind(wx.EVT_RIGHT_UP, self.OnCloseWindow)  # Panel right clic.
 308         self.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick)  # View mask.
 309         self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
 310         self.Bind(wx.EVT_WINDOW_CREATE, self.SetWindowShape)
 311         self.Bind(wx.EVT_MOTION, self.OnMouseMove)
 312         self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
 313         self.Bind(wx.EVT_PAINT, self.OnPaint)
 314 
 315         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
 316 
 317 
 318     def SetWindowShape(self, event=None):
 319         """
 320         ...
 321         """
 322 
 323         # Use the bitmap's mask to determine the region.
 324         r = wx.Region(self.bmp)
 325         self.hasShape = self.SetShape(r)
 326 
 327 
 328     def OnEraseBackground(self, event):
 329         """
 330         ...
 331         """
 332 
 333         dc = event.GetDC()
 334         if not dc:
 335             dc = wx.ClientDC(self)
 336             rect = self.GetUpdateRegion().GetBox()
 337             dc.SetClippingRect(rect)
 338 
 339 
 340     def OnDoubleClick(self, event):
 341         """
 342         ...
 343         """
 344 
 345         if self.hasShape:
 346             self.SetShape(wx.Region())
 347             self.hasShape = False
 348         else:
 349             self.SetWindowShape()
 350 
 351 
 352     def OnLeftDown(self, event):
 353         """
 354         ...
 355         """
 356 
 357         self.CaptureMouse()
 358         x, y = self.ClientToScreen(event.GetPosition())
 359         originx, originy = self.GetPosition()
 360         dx = x - originx
 361         dy = y - originy
 362         self.delta = ((dx, dy))
 363 
 364 
 365     def OnLeftUp(self, evt):
 366         """
 367         ...
 368         """
 369 
 370         if self.HasCapture():
 371             self.ReleaseMouse()
 372 
 373 
 374     def OnMouseMove(self, event):
 375         """
 376         ...
 377         """
 378 
 379         if event.Dragging() and event.LeftIsDown():
 380             x, y = self.ClientToScreen(event.GetPosition())
 381             fp = (x - self.delta[0], y - self.delta[1])
 382             self.Move(fp)
 383 
 384 
 385     def OnPaint(self, event):
 386         """
 387         ...
 388         """
 389 
 390         dc = wx.PaintDC(self)
 391         dc.DrawBitmap(self.bmp, 0, 0, True)
 392 
 393         #------------
 394 
 395         # These are strings.
 396         py_version = sys.version.split()[0]
 397 
 398         str1 = (('<font style="normal" family="default" color="yellow" size="10" weight="bold">'
 399                  'Programming : </font>'
 400                  '<font style="normal" family="default" color="black" size="10" weight="normal">'
 401                  'Python {}</font>').format(py_version))   # Python 3.6.5
 402 
 403         str2 = (('<font style="normal" family="default" color="red" size="10" weight="bold">'
 404                  'GUI toolkit : </font>'
 405                  '<font style="normal" family="default" color="black" size="10" weight="normal">'
 406                  'wxPython {}</font>').format(wx.VERSION_STRING))  # wxPython 4.0.2
 407 
 408         str3 = (('<font style="normal" family="default" color="brown" size="10" weight="bold">'
 409                  'Library : </font>'
 410                  '<font style="normal" family="default" color="black" size="10" weight="normal">'
 411                  '{}</font>').format(wx.GetLibraryVersionInfo().VersionString))   # wxWidgets 3.0.5
 412 
 413         str4 = (('<font style="normal" family="default" color="blue" size="10" weight="bold">'
 414                  'Operating system : </font>'
 415                  '<font style="normal" family="default" color="black" size="10" weight="normal">'
 416                  '{}</font>').format(platform.system()))   # Windows
 417 
 418         str5 = (('<font style="normal" family="default" color="white" size="9" weight="normal">'
 419                  '{}</font>').format(self.app_name))   # Custom Gui
 420 
 421         str6 = (('<font style="normal" family="default" color="dark blue" size="8" weight="normal">'
 422                  'Right clic or Esc for Exit</font>'))
 423 
 424         #------------
 425 
 426         # Return image size.
 427         bw, bh = self.bmp.GetWidth(), self.bmp.GetHeight()
 428 
 429         # Draw text.
 430         # Need width to calculate x position of str1.
 431         tw, th = fancytext.GetExtent(str1, dc)
 432         # Centered text.
 433         fancytext.RenderToDC(str1, dc, (bw-tw)/2, 30)
 434 
 435         #------------
 436 
 437         # Need width to calculate x position of str2.
 438         tw, th = fancytext.GetExtent(str2, dc)
 439         # Centered text.
 440         fancytext.RenderToDC(str2, dc, (bw-tw)/2, 50)
 441 
 442         #------------
 443 
 444         # Need width to calculate x position of str3.
 445         tw, th = fancytext.GetExtent(str3, dc)
 446         # Centered text.
 447         fancytext.RenderToDC(str3, dc, (bw-tw)/2, 70)
 448 
 449         #------------
 450 
 451         # Need width to calculate x position of str4.
 452         tw, th = fancytext.GetExtent(str4, dc)
 453         # Centered text.
 454         fancytext.RenderToDC(str4, dc, (bw-tw)/2, 90)
 455 
 456         #------------
 457 
 458         # Need width to calculate x position of str5.
 459         tw, th = fancytext.GetExtent(str5, dc)
 460         # Centered text.
 461         fancytext.RenderToDC(str5, dc, (bw-tw)/2, 130)
 462 
 463         #------------
 464 
 465         # Need width to calculate x position of str6.
 466         tw, th = fancytext.GetExtent(str6, dc)
 467         # Centered text.
 468         fancytext.RenderToDC(str6, dc, (bw-tw)/2, 195)
 469 
 470 
 471     def OnKeyUp(self, event):
 472         """
 473         ...
 474         """
 475 
 476         if event.GetKeyCode() == wx.WXK_ESCAPE:
 477             self.OnCloseWindow(event)
 478 
 479         event.Skip()
 480 
 481 
 482     def OnCloseWindow(self, event):
 483         """
 484         ...
 485         """
 486 
 487         self.GetParent().Enable(True)
 488         self.eventLoop.Exit()
 489         self.Destroy()
 490 
 491 #-------------------------------------------------------------------------------
 492 
 493 class MyPopupMenu(wx.Menu):
 494     """
 495     Thanks to Robin Dunn.
 496     """
 497     def __init__(self, parent):
 498         wx.Menu.__init__(self)
 499 
 500         #------------
 501 
 502         # Attributes.
 503         self.parent = parent
 504 
 505         #------------
 506 
 507         # Simplified init method.
 508         self.CreatePopupMenu()
 509         self.BindEvents()
 510 
 511     #---------------------------------------------------------------------------
 512 
 513     def CreatePopupMenu(self, event=None):
 514         """
 515         This method is called by the base class when it needs to popup
 516         the menu for the default EVT_RIGHT_DOWN event.  Just create
 517         the menu how you want it and return it from this function,
 518         the base class takes care of the rest.
 519         """
 520 
 521         # Returns bitmaps folder.
 522         bitmaps_dir = wx.GetApp().GetBitmapsDir()
 523 
 524         #------------
 525 
 526         bmp = wx.Bitmap(os.path.join(bitmaps_dir,
 527                                      "item_about.png"),
 528                         type=wx.BITMAP_TYPE_PNG)
 529 
 530         item = wx.MenuItem(self, id=wx.ID_ABOUT, text=" About")
 531         item.SetBitmap(bmp)
 532         self.Append(item)
 533         self.AppendSeparator()
 534 
 535         #------------
 536 
 537         bmp = wx.Bitmap(os.path.join(bitmaps_dir,
 538                                      "item_exit.png"),
 539                         type=wx.BITMAP_TYPE_PNG)
 540 
 541         if True or "__WXMSW__" in wx.PlatformInfo:
 542             font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
 543             font.SetWeight(wx.BOLD)
 544 
 545         item = wx.MenuItem(self, id=wx.ID_EXIT, text=" Exit")
 546         item.SetBitmap(bmp)
 547         item.SetFont(font)
 548         self.Append(item)
 549 
 550         return self
 551 
 552 
 553     def BindEvents(self):
 554         """
 555         Bind some events to an events handler.
 556         """
 557 
 558         # Bind the menu events to an events handler.
 559         self.Bind(wx.EVT_MENU, self.OnAbout, id=wx.ID_ABOUT)
 560         self.Bind(wx.EVT_MENU, self.OnClose, id=wx.ID_EXIT)
 561 
 562 
 563     def OnAbout(self, event):
 564         """
 565         ...
 566         """
 567 
 568         self.mainFrame = wx.GetApp().GetTopWindow()
 569         self.mainFrame.OnAbout(self)
 570 
 571         print("About icon was clicked.")
 572 
 573 
 574     def OnClose(self, event):
 575         """
 576         ...
 577         """
 578 
 579         self.mainFrame = wx.GetApp().GetTopWindow()
 580         self.mainFrame.OnTimerOut(self)
 581 
 582         print("Close icon was clicked.")
 583 
 584 #-------------------------------------------------------------------------------
 585 
 586 class MyWindow(wx.Control):
 587     """
 588     Thanks to Cody Precord.
 589     """
 590     def __init__(self, parent, label,
 591                  foreground, background,
 592                  normal, pressed=None):
 593         super(MyWindow, self).__init__(parent, -1,
 594                                        style=wx.BORDER_NONE)
 595 
 596         #------------
 597 
 598         # Attributes.
 599         self.label = label
 600         self.foreground = foreground
 601         self.background = background
 602 
 603         if wx.Platform == "__WXGTK__":
 604             self.color = "#9e9d9d"
 605 
 606         else:
 607             self.color = "#b1b1b0"
 608 
 609         self.normal = normal
 610         self.pressed = pressed
 611 
 612         self._clicked = False
 613 
 614         #------------
 615 
 616         self.region = wx.Region(normal, wx.Colour(0, 0, 0, 0))
 617 
 618         #------------
 619 
 620         # Simplified init method.
 621         self.SetProperties(label, foreground, background)
 622         self.BindEvents()
 623 
 624     #---------------------------------------------------------------------------
 625 
 626     def SetProperties(self, label, foreground, background):
 627         """
 628         ...
 629         """
 630 
 631         self.label = label
 632         self.foreground = foreground
 633         self.background = background
 634         self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
 635 
 636 
 637     def BindEvents(self):
 638         """
 639         Bind some events to an events handler.
 640         """
 641 
 642         self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
 643         self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
 644         self.Bind(wx.EVT_PAINT, self.OnPaint)
 645         self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
 646         self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDclick)
 647         self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
 648         self.Bind(wx.EVT_MOTION, self.OnMotion)
 649         self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeave)
 650         self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
 651 
 652 
 653     def SetLabel(self, label):
 654         """
 655         ...
 656         """
 657 
 658         self.label = label
 659         self.Refresh()
 660 
 661 
 662     def DoGetBestSize(self):
 663         """
 664         ...
 665         """
 666 
 667         return self.normal.GetSize()
 668 
 669 
 670     def GetLabel(self):
 671         """
 672         ...
 673         """
 674 
 675         return self.label
 676 
 677 
 678     def GetLabelColor(self):
 679         """
 680         ...
 681         """
 682 
 683         return self.foreground
 684 
 685 
 686     def Enable(self, *args, **kwargs):
 687         """
 688         ...
 689         """
 690 
 691         super(MyWindow, self).Enable(*args, **kwargs)
 692         self.Refresh()
 693 
 694 
 695     def Disable(self, *args, **kwargs):
 696         """
 697         ...
 698         """
 699 
 700         super(MyWindow, self).Disable(*args, **kwargs)
 701         self.Refresh()
 702 
 703 
 704     def PostEvent(self):
 705         """
 706         ...
 707         """
 708 
 709         event = wx.CommandEvent()
 710         event.SetEventObject(self)
 711         event.SetEventType(wx.EVT_BUTTON.typeId)
 712         wx.PostEvent(self, event)
 713 
 714 
 715     def OnSize(self, event):
 716         """
 717         ...
 718         """
 719 
 720         event.Skip()
 721         self.Refresh()
 722 
 723 
 724     def Getbackground(self):
 725         """
 726         ...
 727         """
 728 
 729         return self.background
 730 
 731 
 732     def OnPaint(self, event):
 733         """
 734         ...
 735         """
 736 
 737         dc = wx.BufferedPaintDC(self)
 738         dc.Clear()
 739         gcdc = wx.GCDC(dc)
 740 
 741         # Set the background color.
 742         if wx.Platform == "__WXGTK__":
 743             gcdc.SetBackground(wx.Brush("grey55"))
 744         else:
 745             gcdc.SetBackground(wx.Brush(self.background))
 746 
 747         gcdc.Clear()
 748 
 749         # Get the working rectangle we can draw in.
 750         rect = self.GetClientRect()
 751 
 752         # Font size and style.
 753         fontSize = self.GetFont().GetPointSize()
 754 
 755         if wx.Platform == "__WXGTK__":
 756             boldFont = wx.Font(fontSize-1, wx.DEFAULT,
 757                                wx.NORMAL, wx.NORMAL, False, "")
 758         else:
 759             boldFont = wx.Font(fontSize+2, wx.DEFAULT,
 760                                wx.NORMAL, wx.BOLD, False, "")
 761 
 762         if wx.Platform == "__WXMSW__":
 763             pen = wx.Pen(self.color, 1, wx.SOLID)
 764 
 765         else:
 766             pen = wx.Pen(self.color, 1, wx.SOLID)
 767 
 768         gcdc.SetPen(pen)
 769 
 770         x, y = self.GetSize()
 771         # x, y , width, height, radius
 772         gcdc.DrawRoundedRectangle (0, 0, 71, 25, 3)
 773 
 774         bitmap = self.normal
 775 
 776         w, h = bitmap.GetWidth(), bitmap.GetHeight()
 777 
 778         if self.clicked:
 779             bitmap = self.pressed or bitmap
 780         if not self.IsEnabled():
 781             bitmap = self.normal or bitmap
 782 
 783         # Draw a bitmap with an alpha channel.
 784         # image, x, y, transparency.
 785         dc.DrawBitmap(bitmap, 0, 0, True)
 786 
 787         if wx.Platform == "__WXGTK__":
 788             # Add the Caption.
 789             # White text - Shadow.
 790             rect = wx.Rect(rect.x, rect.y+3,
 791                            rect.width, 22)
 792 
 793         else:
 794             rect = wx.Rect(rect.x, rect.y+3,
 795                            rect.width, 20)
 796 
 797         dc.SetFont(boldFont)
 798         dc.SetTextForeground(wx.WHITE)
 799         dc.DrawLabel(self.label, rect, wx.ALIGN_CENTER)
 800 
 801         if wx.Platform == "__WXGTK__":
 802             # Add the Caption.
 803             # Black text.
 804             rect = wx.Rect(rect.x, rect.y,
 805                            rect.width, 21)
 806 
 807         else:
 808             rect = wx.Rect(rect.x, rect.y,
 809                            rect.width, 19)
 810 
 811         gcdc.SetFont(boldFont)
 812         # Get the text color.
 813         dc.SetTextForeground(self.foreground)
 814         dc.DrawLabel(self.label, rect, wx.ALIGN_CENTER)
 815 
 816 
 817     def SetClicked(self, clicked):
 818         """
 819         ...
 820         """
 821 
 822         if clicked != self._clicked:
 823             self._clicked = clicked
 824             self.Refresh()
 825 
 826 
 827     def GetClicked(self):
 828         """
 829         ...
 830         """
 831 
 832         return self._clicked
 833 
 834 
 835     clicked = property(GetClicked, SetClicked)
 836     def OnLeftDown(self, event):
 837         """
 838         ...
 839         """
 840 
 841         x, y = event.GetPosition()
 842         if self.region.Contains(x, y):
 843             self.clicked = True
 844             self.SetFocus()
 845 
 846 
 847     def OnLeftDclick(self, event):
 848         """
 849         ...
 850         """
 851 
 852         self.OnLeftDown(event)
 853 
 854 
 855     def OnLeftUp(self, event):
 856         """
 857         ...
 858         """
 859 
 860         if self.clicked:
 861             x, y = event.GetPosition()
 862             if self.region.Contains(x, y):
 863                 self.PostEvent()
 864         self.clicked = False
 865 
 866 
 867     def OnMotion(self, event):
 868         """
 869         ...
 870         """
 871 
 872         if self.clicked:
 873             x, y = event.GetPosition()
 874             if not self.region.Contains(x, y):
 875                 self.clicked = False
 876 
 877 
 878     def OnLeave(self, event):
 879         """
 880         ...
 881         """
 882 
 883         self.clicked = False
 884 
 885 
 886     def OnSetFocus(self, event):
 887         """
 888         ...
 889         """
 890 
 891         self.color = "white"
 892         self.Refresh()
 893 
 894 
 895     def OnKillFocus(self, event):
 896         """
 897         ...
 898         """
 899 
 900         if wx.Platform == "__WXGTK__":
 901             self.color = "#9e9d9d"
 902 
 903         else:
 904             self.color = "#b1b1b0"
 905 
 906         self.Refresh()
 907 
 908 
 909     def OnKeyUp(self, event):
 910         """
 911         ...
 912         """
 913 
 914         if event.GetKeyCode() == wx.WXK_SPACE:
 915             self.PostEvent()
 916             return
 917 
 918         elif event.GetKeyCode() == wx.WXK_ESCAPE:
 919             self.GetTopLevelParent().OnCloseWindow(True)
 920 
 921         event.Skip()
 922 
 923 #-------------------------------------------------------------------------------
 924 
 925 class MyButtonBox(wx.Panel):
 926     """
 927     Thanks to Cody Precord.
 928     """
 929     def __init__(self, parent, caption):
 930         super(MyButtonBox, self).__init__(parent,
 931                                            style=wx.NO_BORDER |
 932                                            wx.TAB_TRAVERSAL)
 933 
 934         #------------
 935 
 936         # Attributes.
 937         self._caption = caption
 938 
 939         #------------
 940 
 941         # Simplified init method.
 942         self.DoLayout()
 943 
 944     #---------------------------------------------------------------------------
 945 
 946     def DoLayout(self):
 947         """
 948         ...
 949         """
 950 
 951         self._csizer = wx.BoxSizer(wx.VERTICAL)
 952         msizer = wx.BoxSizer(wx.HORIZONTAL)
 953         msizer.Add(self._csizer, 0 )
 954         self.SetSizer(msizer)
 955 
 956 
 957     def DoGetBestSize(self):
 958         """
 959         ...
 960         """
 961 
 962         size = super(MyButtonBox, self).DoGetBestSize()
 963 
 964         # Compensate for wide caption labels.
 965         tw = self.GetTextExtent(self._caption)[0]
 966         size.SetWidth(max(size.width, size.height))
 967         return size
 968 
 969 
 970     def AddItem(self, item):
 971         """
 972         Add a window or sizer item to the MyButtonBox.
 973         """
 974 
 975         self._csizer.Add(item, 0 )
 976 
 977 #-------------------------------------------------------------------------------
 978 
 979 class MyPanel(wx.Panel):
 980     """
 981     Thanks to Cody Precord.
 982     """
 983     def __init__(self, parent):
 984         wx.Panel.__init__(self, parent)
 985 
 986         #------------
 987 
 988         # Return application name.
 989         self.app_name = wx.GetApp().GetAppName()
 990         # Return bitmaps folder.
 991         self.bitmaps_dir = wx.GetApp().GetBitmapsDir()
 992 
 993         #------------
 994 
 995         # Create a timer.
 996         self.timer = wx.Timer(self)
 997         self.timer.Start(1000)
 998         self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
 999 
1000         #------------
1001 
1002         # Simplified init method.
1003         self.SetProperties()
1004         self.CreateCtrls()
1005         self.BindEvents()
1006 
1007     #---------------------------------------------------------------------------
1008 
1009     def SetProperties(self):
1010         """
1011         ...
1012         """
1013 
1014         self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
1015 
1016 
1017     def CreateCtrls(self):
1018         """
1019         ...
1020         """
1021 
1022         # Load a background bitmap.
1023         self.bitmap = wx.Bitmap(os.path.join(self.bitmaps_dir,
1024                                              "skin_main.png"),
1025                                 type=wx.BITMAP_TYPE_PNG)
1026 
1027         #------------
1028 
1029         # Add titleBar.
1030         self.titleBar = MyTitleBar(self,
1031                                    label=self.app_name,
1032                                    size=10)
1033         self.titleBar.SetPosition((1, 1))
1034         self.titleBar.SetSize((258, 24))
1035         self.titleBar.SetLabelColour(wx.BLACK)
1036         self.titleBar.SetToolTip("This is a customized title bar.")
1037 
1038         #------------
1039 
1040         # Load an icon bitmap for titlebar.
1041         self.icon = wx.Bitmap(os.path.join(self.bitmaps_dir,
1042                                            "icon_app.png"),
1043                               type=wx.BITMAP_TYPE_PNG)
1044 
1045         self.ico = wx.StaticBitmap(self.titleBar, -1, self.icon)
1046         self.ico.SetPosition((5, 2))
1047         self.ico.SetToolTip("This is a customized icon.")
1048 
1049         self.ico.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
1050         self.ico.Bind(wx.EVT_LEFT_DOWN, self.OnRightDown)
1051 
1052         #------------
1053         #------------
1054 
1055         # Load a bitmap.
1056         self.logo  = wx.Bitmap(os.path.join(self.bitmaps_dir,
1057                                             "logo.png"),
1058                                type=wx.BITMAP_TYPE_PNG)
1059 
1060         #------------
1061 
1062         # Aluminium Buttons box (main).
1063         self.box1 = MyButtonBox(self, "")   # Button About.
1064         self.box2 = MyButtonBox(self, "")   # Button Quit.
1065 
1066         # Gloss Buttons box (titleBar).
1067         self.box3 = MyButtonBox(self.titleBar, "")   # Button Exit.
1068         self.box4 = MyButtonBox(self.titleBar, "")   # Button Reduce.
1069 
1070         #------------
1071 
1072         # Aluminium Buttons bitmap.
1073         bmp1 = wx.Bitmap(os.path.join(self.bitmaps_dir,
1074                                       "btn_alu_normal.png"),
1075                          type=wx.BITMAP_TYPE_PNG)
1076 
1077         bmp2 = wx.Bitmap(os.path.join(self.bitmaps_dir,
1078                                       "btn_alu_pressed.png"),
1079                          type=wx.BITMAP_TYPE_PNG)
1080 
1081         # Gloss Buttons bitmap.
1082         bmpa = wx.Bitmap(os.path.join(self.bitmaps_dir,
1083                                       "btn_gloss_exit_normal_2.png"),
1084                          type=wx.BITMAP_TYPE_PNG)
1085 
1086         bmpb = wx.Bitmap(os.path.join(self.bitmaps_dir,
1087                                       "btn_gloss_exit_selected_2.png"),
1088                          type=wx.BITMAP_TYPE_PNG)
1089 
1090 
1091         bmpc = wx.Bitmap(os.path.join(self.bitmaps_dir,
1092                                       "btn_gloss_roll_normal_2.png"),
1093                          type=wx.BITMAP_TYPE_PNG)
1094 
1095         bmpd = wx.Bitmap(os.path.join(self.bitmaps_dir,
1096                                       "btn_gloss_roll_selected_2.png"),
1097                          type=wx.BITMAP_TYPE_PNG)
1098 
1099         # Buttons panel.
1100         self.btn1 = MyWindow(self.box1, "About", "black", "#9e9d9d", bmp1, bmp2)
1101         self.btn1.SetToolTip("This is a customized aluminium button.")
1102         self.btn1.Bind(wx.EVT_BUTTON, self.OnBtnAbout)
1103         self.btn1.SetFocus() # Necessary for Linux.
1104 
1105         self.btn2 = MyWindow(self.box2, "Exit", "black", "#9e9d9d", bmp1, bmp2)
1106         self.btn2.SetToolTip("This is a customized aluminium button.")
1107         self.btn2.Bind(wx.EVT_BUTTON, self.OnBtnClose)
1108 
1109         self.btn3 = MyWindow(self.box3, "", "black", "#9e9d9d", bmpa, bmpb)
1110         self.btn3.SetToolTip("This is a customized gloss button.")
1111         self.btn3.Bind(wx.EVT_BUTTON, self.OnBtnClose)
1112 
1113         self.btn4 = MyWindow(self.box4, "", "black", "#9e9d9d", bmpc, bmpd)
1114         self.btn4.SetToolTip("This is a customized gloss button.")
1115         self.btn4.Bind(wx.EVT_BUTTON, self.OnBtnRoll)
1116 
1117         self.box1.AddItem(self.btn1)
1118         self.box2.AddItem(self.btn2)
1119         self.box3.AddItem(self.btn3)
1120         self.box4.AddItem(self.btn4)
1121 
1122         self.box1.SetPosition((20, 138))
1123         self.box1.SetSize((71, 25))
1124 
1125         self.box2.SetPosition((20, 173))
1126         self.box2.SetSize((71, 25))
1127 
1128         self.box3.SetPosition((214, 2))
1129         self.box3.SetSize((40, 19))
1130 
1131         self.box4.SetPosition((189, 2))
1132         self.box4.SetSize((25, 19))
1133 
1134 
1135     def BindEvents(self):
1136         """
1137         Bind some events to an events handler.
1138         """
1139 
1140         self.Bind(wx.EVT_PAINT, self.OnPaint)
1141         self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
1142 
1143 
1144     def OnLeftDown(self, evt):
1145         """
1146         ...
1147         """
1148 
1149         print("Left down.")
1150 
1151 
1152     def OnRightDown(self, event):
1153         """
1154         ...
1155         """
1156 
1157         self.PopupMenu(MyPopupMenu(self), event.GetPosition())
1158 
1159         print("Right down.")
1160 
1161 
1162     def OnEraseBackground(self, event):
1163         """
1164         ...
1165         """
1166 
1167         dc = event.GetDC()
1168         if not dc:
1169             dc = wx.ClientDC(self)
1170             rect = self.GetUpdateRegion().GetBox()
1171             dc.SetClippingRect(rect)
1172 
1173 
1174     def OnBtnRoll(self, event):
1175         """
1176         ...
1177         """
1178 
1179         self.GetParent().OnRoll(True)
1180 
1181         print("Roll/unRoll button was clicked.")
1182 
1183 
1184     def OnBtnAbout(self, event):
1185         """
1186         ...
1187         """
1188 
1189         self.GetParent().OnAbout(True)
1190 
1191         print("About button was clicked.")
1192 
1193 
1194     def OnBtnClose(self, event):
1195         """
1196         ...
1197         """
1198 
1199         self.GetParent().OnCloseWindow(self)
1200 
1201         print("Close button was clicked.")
1202 
1203 
1204     def Draw(self, dc):
1205         """
1206         ...
1207         """
1208 
1209         # Draw a bitmap with an alpha channel
1210         # on top of the last group.
1211         # image, x, y, transparence
1212         dc.DrawBitmap(self.bitmap, 0, 0, True)
1213 
1214         #------------
1215 
1216         fontSize = self.GetFont().GetPointSize()
1217 
1218         # wx.Font(pointSize, family, style, weight, underline, faceName)
1219         if wx.Platform == "__WXGTK__":
1220             self.titleBoldFont = wx.Font(fontSize-2,
1221                                          wx.DEFAULT, wx.NORMAL,
1222                                          wx.BOLD, False, "")
1223             self.normalBoldFont = wx.Font(fontSize+18,
1224                                           wx.DEFAULT, wx.NORMAL,
1225                                           wx.NORMAL, False, "")
1226             self.normalFont = wx.Font(fontSize-2,
1227                                       wx.DEFAULT, wx.NORMAL,
1228                                       wx.NORMAL, False, "")
1229 
1230         else:
1231             self.titleBoldFont = wx.Font(fontSize+1,
1232                                          wx.DEFAULT, wx.NORMAL,
1233                                          wx.BOLD, False, "")
1234             self.normalBoldFont = wx.Font(fontSize+23,
1235                                           wx.DEFAULT, wx.NORMAL,
1236                                           wx.NORMAL, False, "")
1237             self.normalFont = wx.Font(fontSize+1,
1238                                       wx.DEFAULT, wx.NORMAL,
1239                                       wx.NORMAL, False, "")
1240 
1241         dc.SetFont(self.normalFont)
1242         dc.SetFont(self.normalBoldFont)
1243 
1244         #------------
1245 
1246         # Draw a bitmap with an alpha channel.
1247         # image, x, y, transparence
1248         dc.DrawBitmap(self.logo, 150, 165, True)
1249 
1250         #------------
1251 
1252         # Return image size.
1253         bw, bh = self.bitmap.GetWidth(), self.bitmap.GetHeight()
1254 
1255         # Draw line.
1256         dc.SetPen(wx.Pen("#c5c4c4"))
1257         # x, y, x, y
1258         dc.DrawLine(2, 25, 258, 25)
1259 
1260         # Draw text.
1261         dc.SetTextForeground("#494848")
1262         dc.SetFont(self.normalFont)
1263         date = time.strftime("%A %d %B %Y")
1264         tw, th = dc.GetTextExtent(date)
1265         dc.DrawText(date, (bw-tw)/2, 100)
1266 
1267         dc.SetTextForeground("#e3dbdb")
1268         dc.SetFont(self.normalBoldFont)
1269         hour = time.strftime("%H:%M:%S")   # "%I:%M:%S %p"
1270         tw, th = dc.GetTextExtent(hour)
1271         dc.DrawText(hour, (bw-tw)/2, 40)
1272 
1273 
1274     def OnTimer(self, event):
1275         """
1276         ...
1277         """
1278 
1279         dc = wx.BufferedDC(wx.ClientDC(self))
1280         self.Draw(dc)
1281         self.Refresh()   # Mac
1282 
1283 
1284     def OnPaint(self, event):
1285         """
1286         ...
1287         """
1288 
1289         dc = wx.BufferedPaintDC(self)
1290         dc.Clear()
1291 
1292         self.Draw(dc)
1293 
1294 #-------------------------------------------------------------------------------
1295 
1296 class MyFrame(wx.Frame):
1297     """
1298     Thanks to Robin Dunn.
1299     """
1300     def __init__(self):
1301         style = (wx.CLIP_CHILDREN | wx.CLOSE_BOX |
1302                  wx.MINIMIZE_BOX | wx.SYSTEM_MENU |
1303                  wx.NO_BORDER | wx.FRAME_SHAPED |
1304                  wx.NO_FULL_REPAINT_ON_RESIZE)
1305         wx.Frame.__init__(self, None, -1, title="", style=style)
1306 
1307         #------------
1308 
1309         # Attributes.
1310         self.SetTransparent(0)
1311         self.opacity_in = 0
1312         self.opacity_out = 250
1313         self.deltaN = -3
1314         self.hasShape = False
1315         self.delta = wx.Point(0,0)
1316 
1317         #------------
1318 
1319         # Return application name.
1320         self.app_name = wx.GetApp().GetAppName()
1321         # Return bitmaps folder.
1322         self.bitmaps_dir = wx.GetApp().GetBitmapsDir()
1323         # Return icons folder.
1324         self.icons_dir = wx.GetApp().GetIconsDir()
1325 
1326         #------------
1327 
1328         # Simplified init method.
1329         self.SetProperties()
1330         self.OnTimerIn(self)
1331         self.CreateCtrls()
1332         self.BindEvents()
1333         self.DoLayout()
1334 
1335         #------------
1336 
1337         # Thanks to Ray Pasco.
1338         # Initialize to the current state.
1339         self.unrolledFrameClientSize_size = self.GetClientSize()
1340         self.isRolled = False
1341 
1342         #------------
1343 
1344         self.CenterOnScreen(wx.BOTH)
1345 
1346         #------------
1347 
1348         self.Show(True)
1349 
1350     #---------------------------------------------------------------------------
1351 
1352     def OnTimerIn(self, evt):
1353         """
1354         Thanks to Pascal Faut.
1355         """
1356 
1357         self.timer1 = wx.Timer(self, -1)
1358         self.timer1.Start(1)
1359