infobar.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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(
  32. win, dc, wx.Rect(size), wx.TITLEBAR_BUTTON_CLOSE, flags
  33. )
  34. dc.SelectObject(wx.NullBitmap)
  35. else:
  36. bmp = wx.ArtProvider.GetBitmap(wx.ART_CLOSE, wx.ART_BUTTON)
  37. return bmp
  38. IB.GetCloseButtonBitmap = GetCloseButtonBitmap
  39. class InfoBar(IB.InfoBar):
  40. """A customized and specialized info bar to used by default"""
  41. def __init__(self, parent):
  42. IB.InfoBar.__init__(self, parent)
  43. self.button_ids = []
  44. # color according to OS
  45. if sys.platform == "win32":
  46. bgcolor = wx.SYS_COLOUR_INFOBK
  47. fgcolor = wx.SYS_COLOUR_INFOTEXT
  48. else:
  49. bgcolor = wx.SYS_COLOUR_HIGHLIGHT
  50. fgcolor = wx.SYS_COLOUR_HIGHLIGHTTEXT
  51. # set background and foreground color and remove alpha
  52. self._background_color = wx.SystemSettings.GetColour(bgcolor).Get(False)
  53. self._foreground_color = wx.SystemSettings.GetColour(fgcolor).Get(False)
  54. self.SetBackgroundColour(self._background_color)
  55. self.SetForegroundColour(self._foreground_color)
  56. self._text.SetBackgroundColour(self._background_color)
  57. self._text.SetForegroundColour(self._foreground_color)
  58. self._button.SetBackgroundColour(self._background_color)
  59. # layout
  60. self._unInitLayout()
  61. sizer = wx.BoxSizer(wx.VERTICAL)
  62. subSizerText = wx.BoxSizer(wx.HORIZONTAL)
  63. self.subSizerButtons = wx.BoxSizer(wx.HORIZONTAL)
  64. subSizerText.Add(self._icon, wx.SizerFlags().Centre().Border())
  65. subSizerText.Add(self._text, 1, wx.ALIGN_CENTER_VERTICAL)
  66. self.subSizerButtons.AddStretchSpacer()
  67. self.subSizerButtons.Add(self._button, wx.SizerFlags().Centre().Border())
  68. sizer.Add(subSizerText, wx.SizerFlags().Expand())
  69. sizer.Add(self.subSizerButtons, wx.SizerFlags().Expand())
  70. self.SetSizer(sizer)
  71. def _unInitLayout(self):
  72. sizer = self.GetSizer()
  73. children = sizer.GetChildren()
  74. for i in reversed(range(len(children))):
  75. if children[i].IsSpacer():
  76. sizer.Remove(i)
  77. else:
  78. sizer.Detach(i)
  79. def ShowMessage(self, message, icon, buttons=None):
  80. """Show message with buttons (optional).
  81. Buttons are list of tuples (label, handler)"""
  82. self.Hide()
  83. self.RemoveButtons()
  84. if buttons:
  85. self.SetButtons(buttons)
  86. super().ShowMessage(message, icon)
  87. def AddButton(self, btnid, label):
  88. """
  89. Adds a button to be shown in the info bar.
  90. """
  91. sizer = self.GetSizer()
  92. assert sizer is not None, "Sizer must be created first"
  93. # user-added buttons replace the standard close button so remove it if we
  94. # hadn't done it yet
  95. if sizer.Detach(self._button):
  96. self._button.Hide()
  97. button = wx.Button(self, btnid, label)
  98. button.SetBackgroundColour(self._background_color)
  99. button.SetForegroundColour(self._foreground_color)
  100. if wx.Platform == "__WXMAC__":
  101. # smaller buttons look better in the(narrow)info bar under OS X
  102. button.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
  103. num_items = self.subSizerButtons.GetItemCount()
  104. if num_items == 1:
  105. self.subSizerButtons.Add(button, wx.SizerFlags().Centre().Border())
  106. self.subSizerButtons.Add(self._button, wx.SizerFlags().Centre().Border())
  107. self._button.Show()
  108. else:
  109. self.subSizerButtons.Insert(
  110. num_items - 1, button, wx.SizerFlags().Centre().Border()
  111. )
  112. if self.IsShown():
  113. self.UpdateParent()
  114. def SetButtons(self, buttons):
  115. """
  116. Sets buttons for notification.
  117. Parameter *buttons* is a list of tuples (button_name, event)
  118. """
  119. for button_name, evt_handler in buttons:
  120. button_id = wx.NewId()
  121. self.button_ids.append(button_id)
  122. self.AddButton(button_id, button_name)
  123. self.Bind(wx.EVT_BUTTON, evt_handler, id=button_id)
  124. def RemoveButtons(self):
  125. """
  126. Removes buttons from info bar.
  127. """
  128. items = self.subSizerButtons.GetChildren()
  129. for item in reversed(items):
  130. if not item.IsSpacer():
  131. window = item.GetWindow()
  132. if window.GetId() in self.button_ids:
  133. self.subSizerButtons.Detach(window)
  134. window.Destroy()