infobar.py 5.1 KB

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