You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

242 lines
7.3 KiB

  1. import time
  2. from gooey.gui.widgets import widget_pack
  3. __author__ = 'Chris'
  4. import wx
  5. from gooey.gui import styling
  6. class BaseGuiComponent(object):
  7. def __init__(self, data, widget_pack):
  8. self.data = data
  9. # parent
  10. self.panel = None
  11. # Widgets
  12. self.title = None
  13. self.help_msg = None
  14. # Internal WidgetPack
  15. self.widget_pack = widget_pack
  16. # used to throttle resizing (to avoid widget jiggle)
  17. # TODO: figure out anti-jiggle technology
  18. # self.last_update = time.time()
  19. # self.event_stack = []
  20. def build(self, parent):
  21. return self.do_layout(parent)
  22. def do_layout(self, parent):
  23. self.panel = wx.Panel(parent)
  24. self.title = self.createTitle(self.panel)
  25. self.help_msg = self.createHelpMsgWidget(self.panel)
  26. self.help_msg.SetMinSize((0, -1))
  27. core_widget_set = self.widget_pack.build(self.panel, self.data)
  28. vertical_container = wx.BoxSizer(wx.VERTICAL)
  29. vertical_container.Add(self.title)
  30. vertical_container.AddSpacer(2)
  31. if self.help_msg.GetLabelText():
  32. vertical_container.Add(self.help_msg, 1, wx.EXPAND)
  33. vertical_container.AddSpacer(2)
  34. else:
  35. vertical_container.AddStretchSpacer(1)
  36. vertical_container.Add(core_widget_set, 0, wx.EXPAND)
  37. self.panel.SetSizer(vertical_container)
  38. self.panel.Bind(wx.EVT_SIZE, self.onResize)
  39. return self.panel
  40. def createHelpMsgWidget(self, parent):
  41. label_text = (self.formatExtendedHelpMsg(self.data)
  42. if self.data['nargs']
  43. else self.data['help'])
  44. base_text = wx.StaticText(parent, label=label_text or '')
  45. styling.MakeDarkGrey(base_text)
  46. return base_text
  47. def createTitle(self, parent):
  48. text = wx.StaticText(parent, label=self.data['display_name'].title())
  49. styling.MakeBold(text)
  50. return text
  51. def formatExtendedHelpMsg(self, data):
  52. base_text = data.get('help_msg', '')
  53. nargs = data['nargs']
  54. if isinstance(nargs, int):
  55. return '{base}\n(Note: exactly {nargs} arguments are required)'.format(base=base_text, nargs=nargs)
  56. elif nargs == '+':
  57. return '{base}\n(Note: at least 1 or more arguments are required)'.format(base=base_text)
  58. return base_text
  59. def onResize(self, evt):
  60. # handle internal widgets
  61. self.panel.Freeze()
  62. self._onResize(evt)
  63. # propagate event to child widgets
  64. self.widget_pack.onResize(evt)
  65. evt.Skip()
  66. self.panel.Thaw()
  67. def _onResize(self, evt):
  68. if not self.help_msg:
  69. return
  70. self.panel.Size = evt.GetSize()
  71. container_width, _ = self.panel.Size
  72. text_width, _ = self.help_msg.Size
  73. if text_width != container_width:
  74. self.help_msg.SetLabel(self.help_msg.GetLabelText().replace('\n', ' '))
  75. self.help_msg.Wrap(container_width)
  76. evt.Skip()
  77. def GetValue(self):
  78. return self.widget_pack.getValue()
  79. def _GetWidget(self):
  80. # used only for unittesting
  81. return self.widget_pack.widget
  82. class CheckBox(BaseGuiComponent):
  83. def __init__(self, data, widget_pack=None):
  84. BaseGuiComponent.__init__(self, data, widget_pack)
  85. self.widget = None
  86. # data
  87. self.option_strings = data['commands'][0]
  88. def build(self, parent):
  89. return self.do_layout(parent)
  90. def do_layout(self, parent):
  91. self.panel = wx.Panel(parent)
  92. self.widget = wx.CheckBox(self.panel)
  93. self.title = self.createTitle(self.panel)
  94. self.help_msg = self.createHelpMsgWidget(self.panel)
  95. self.help_msg.SetMinSize((0, -1))
  96. vertical_container = wx.BoxSizer(wx.VERTICAL)
  97. vertical_container.Add(self.title)
  98. horizontal_sizer = wx.BoxSizer(wx.HORIZONTAL)
  99. horizontal_sizer.Add(self.widget, 0, wx.EXPAND | wx.RIGHT, 10)
  100. horizontal_sizer.Add(self.help_msg, 1, wx.EXPAND)
  101. vertical_container.Add(horizontal_sizer, 0, wx.EXPAND)
  102. self.panel.SetSizer(vertical_container)
  103. self.panel.Bind(wx.EVT_SIZE, self.onResize)
  104. return self.panel
  105. def onSetter(self, evt):
  106. self.getValue()
  107. def onResize(self, evt):
  108. msg = self.help_msg
  109. container_width, _ = self.panel.Size
  110. text_width, _ = msg.Size
  111. if text_width != container_width:
  112. msg.SetLabel(msg.GetLabelText().replace('\n', ' '))
  113. msg.Wrap(container_width)
  114. evt.Skip()
  115. def GetValue(self):
  116. return self.option_strings if self.widget.GetValue() else ''
  117. def _GetWidget(self):
  118. return self.widget
  119. class RadioGroup(object):
  120. def __init__(self, data):
  121. self.panel = None
  122. self.data = data
  123. self.radio_buttons = []
  124. self.option_stings = []
  125. self.help_msgs = []
  126. self.btn_names = []
  127. def build(self, parent):
  128. return self.do_layout(parent)
  129. def do_layout(self, parent):
  130. self.panel = wx.Panel(parent)
  131. self.radio_buttons = [wx.RadioButton(self.panel, -1) for _ in self.data]
  132. self.btn_names = [wx.StaticText(self.panel, label=btn_data['display_name'].title()) for btn_data in self.data]
  133. self.help_msgs = [wx.StaticText(self.panel, label=btn_data['help'].title()) for btn_data in self.data]
  134. self.option_stings = [btn_data['commands'] for btn_data in self.data]
  135. # box = wx.StaticBox(self.panel, -1, label=self.data['group_name'])
  136. box = wx.StaticBox(self.panel, -1, label='Set Verbosity Level')
  137. vertical_container = wx.StaticBoxSizer(box, wx.VERTICAL)
  138. for button, name, help in zip(self.radio_buttons, self.btn_names, self.help_msgs):
  139. hbox = wx.BoxSizer(wx.HORIZONTAL)
  140. hbox.Add(button, 0, wx.ALIGN_TOP | wx.ALIGN_LEFT)
  141. hbox.Add(name, 0, wx.LEFT, 10)
  142. vertical_container.Add(hbox, 0, wx.EXPAND)
  143. vertical_container.Add(help, 1, wx.EXPAND | wx.LEFT, 25)
  144. vertical_container.AddSpacer(5)
  145. # self.panel.Bind(wx.EVT_RADIOBUTTON, self.onSetter, button)
  146. self.panel.SetSizer(vertical_container)
  147. self.panel.Bind(wx.EVT_SIZE, self.onResize)
  148. return self.panel
  149. def onSetter(self, evt):
  150. self.getValue()
  151. def onResize(self, evt):
  152. msg = self.help_msgs[0]
  153. container_width, _ = self.panel.Size
  154. text_width, _ = msg.Size
  155. if text_width != container_width:
  156. msg.SetLabel(msg.GetLabelText().replace('\n', ' '))
  157. msg.Wrap(container_width)
  158. evt.Skip()
  159. def GetValue(self):
  160. vals = [button.GetValue() for button in self.radio_buttons]
  161. # print self.option_stings[vals.index(True)]
  162. try:
  163. opts = self.option_stings[vals.index(True)][0]
  164. except:
  165. return ''
  166. def _GetWidget(self):
  167. return self.radio_buttons
  168. FileChooser = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.FileChooserPayload())
  169. MultiFileChooser = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.MultiFileSaverPayload())
  170. DirChooser = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.DirChooserPayload())
  171. FileSaver = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.FileSaverPayload())
  172. DateChooser = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.DateChooserPayload())
  173. TextField = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.TextInputPayload())
  174. Dropdown = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.DropdownPayload())
  175. Counter = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.CounterPayload())