infobar.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. """
  2. @package gui_core.infobar
  3. @brief Wrapper around wx.InfoBar
  4. Classes:
  5. - gui_core::InfoBar
  6. (C) 2020 by the GRASS Development Team
  7. This program is free software under the GNU General Public License
  8. (>=v2). Read the file COPYING that comes with GRASS for details.
  9. @author Linda Kladivova
  10. @author Anna Petrasova <kratochanna gmail.com>
  11. @author Vaclav Petras <wenzeslaus gmail.com>
  12. """
  13. import sys
  14. import wx
  15. import wx.aui
  16. try:
  17. import wx.lib.agw.infobar as IB
  18. except ImportError:
  19. import wx.lib.infobar as IB
  20. def GetCloseButtonBitmap(win, size, colBg, flags=0):
  21. """Workaround for missing DrawTitleBarBitmap method
  22. of wx.RendererNative in certain wx versions.
  23. See https://github.com/wxWidgets/Phoenix/issues/1425."""
  24. renderer = wx.RendererNative.Get()
  25. if hasattr(renderer, 'DrawTitleBarBitmap'):
  26. bmp = wx.Bitmap(*size)
  27. dc = wx.MemoryDC()
  28. dc.SelectObject(bmp)
  29. dc.SetBackground(wx.Brush(colBg))
  30. dc.Clear()
  31. wx.RendererNative.Get().DrawTitleBarBitmap(win, dc, wx.Rect(size), wx.TITLEBAR_BUTTON_CLOSE, flags)
  32. dc.SelectObject(wx.NullBitmap)
  33. else:
  34. bmp = wx.ArtProvider.GetBitmap(wx.ART_CLOSE, wx.ART_BUTTON)
  35. return bmp
  36. IB.GetCloseButtonBitmap = GetCloseButtonBitmap
  37. class InfoBar(IB.InfoBar):
  38. """A customized and specialized info bar to used by default"""
  39. def __init__(self, parent):
  40. IB.InfoBar.__init__(self, parent)
  41. self.button_ids = []
  42. # color according to OS
  43. if sys.platform == "win32":
  44. bgcolor = wx.SYS_COLOUR_INFOBK
  45. fgcolor = wx.SYS_COLOUR_INFOTEXT
  46. else:
  47. bgcolor = wx.SYS_COLOUR_HIGHLIGHT
  48. fgcolor = wx.SYS_COLOUR_HIGHLIGHTTEXT
  49. # set background and foreground color and remove alpha
  50. self._background_color = wx.SystemSettings.GetColour(bgcolor).Get(False)
  51. self._foreground_color = wx.SystemSettings.GetColour(fgcolor).Get(False)
  52. self.SetBackgroundColour(self._background_color)
  53. self.SetForegroundColour(self._foreground_color)
  54. self._text.SetBackgroundColour(self._background_color)
  55. self._text.SetForegroundColour(self._foreground_color)
  56. self._button.SetBackgroundColour(self._background_color)
  57. # layout
  58. self._unInitLayout()
  59. sizer = wx.BoxSizer(wx.VERTICAL)
  60. subSizerText = wx.BoxSizer(wx.HORIZONTAL)
  61. self.subSizerButtons = wx.BoxSizer(wx.HORIZONTAL)
  62. subSizerText.Add(self._icon, wx.SizerFlags().Centre().Border())
  63. subSizerText.Add(self._text, 1, wx.ALIGN_CENTER_VERTICAL)
  64. self.subSizerButtons.AddStretchSpacer()
  65. self.subSizerButtons.Add(self._button, wx.SizerFlags().Centre().Border())
  66. sizer.Add(subSizerText, wx.SizerFlags().Expand())
  67. sizer.Add(self.subSizerButtons, wx.SizerFlags().Expand())
  68. self.SetSizer(sizer)
  69. def _unInitLayout(self):
  70. sizer = self.GetSizer()
  71. children = sizer.GetChildren()
  72. for i in reversed(range(len(children))):
  73. if children[i].IsSpacer():
  74. sizer.Remove(i)
  75. else:
  76. sizer.Detach(i)
  77. def ShowMessage(self, message, icon, buttons=None):
  78. """Show message with buttons (optional).
  79. Buttons are list of tuples (label, handler)"""
  80. self.Hide()
  81. self.RemoveButtons()
  82. if buttons:
  83. self.SetButtons(buttons)
  84. super().ShowMessage(message, icon)
  85. def AddButton(self, btnid, label):
  86. """
  87. Adds a button to be shown in the info bar.
  88. """
  89. sizer = self.GetSizer()
  90. assert sizer is not None, "Sizer must be created first"
  91. # user-added buttons replace the standard close button so remove it if we
  92. # hadn't done it yet
  93. if sizer.Detach(self._button):
  94. self._button.Hide()
  95. button = wx.Button(self, btnid, label)
  96. button.SetBackgroundColour(self._background_color)
  97. button.SetForegroundColour(self._foreground_color)
  98. if wx.Platform == '__WXMAC__':
  99. # smaller buttons look better in the(narrow)info bar under OS X
  100. button.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
  101. num_items = self.subSizerButtons.GetItemCount()
  102. if num_items == 1:
  103. self.subSizerButtons.Add(button, wx.SizerFlags().Centre().Border())
  104. self.subSizerButtons.Add(self._button, wx.SizerFlags().Centre().Border())
  105. self._button.Show()
  106. else:
  107. self.subSizerButtons.Insert(num_items - 1, button, wx.SizerFlags().Centre().Border())
  108. if self.IsShown():
  109. self.UpdateParent()
  110. def SetButtons(self, buttons):
  111. """
  112. Sets buttons for notification.
  113. Parameter *buttons* is a list of tuples (button_name, event)
  114. """
  115. for button_name, evt_handler in buttons:
  116. button_id = wx.NewId()
  117. self.button_ids.append(button_id)
  118. self.AddButton(button_id, button_name)
  119. self.Bind(wx.EVT_BUTTON, evt_handler, id=button_id)
  120. def RemoveButtons(self):
  121. """
  122. Removes buttons from info bar.
  123. """
  124. items = self.subSizerButtons.GetChildren()
  125. for item in reversed(items):
  126. if not item.IsSpacer():
  127. window = item.GetWindow()
  128. if window.GetId() in self.button_ids:
  129. self.subSizerButtons.Detach(window)
  130. window.Destroy()