printrun-src/printrun/gui/__init__.py

changeset 15
0bbb006204fc
child 46
cce0af6351f0
equal deleted inserted replaced
14:51bf56ba3c10 15:0bbb006204fc
1 # This file is part of the Printrun suite.
2 #
3 # Printrun is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation, either version 3 of the License, or
6 # (at your option) any later version.
7 #
8 # Printrun is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
15
16 import logging
17
18 try:
19 import wx
20 except:
21 logging.error(_("WX is not installed. This program requires WX to run."))
22 raise
23
24 from printrun.utils import install_locale
25 install_locale('pronterface')
26
27 from .controls import ControlsSizer, add_extra_controls
28 from .viz import VizPane
29 from .log import LogPane
30 from .toolbar import MainToolbar
31
32 class ToggleablePane(wx.BoxSizer):
33
34 def __init__(self, root, label, parentpanel, parentsizers):
35 super(ToggleablePane, self).__init__(wx.HORIZONTAL)
36 if not parentpanel: parentpanel = root.panel
37 self.root = root
38 self.visible = True
39 self.parentpanel = parentpanel
40 self.parentsizers = parentsizers
41 self.panepanel = root.newPanel(parentpanel)
42 self.button = wx.Button(parentpanel, -1, label, size = (22, 18), style = wx.BU_EXACTFIT)
43 self.button.Bind(wx.EVT_BUTTON, self.toggle)
44
45 def toggle(self, event):
46 if self.visible:
47 self.Hide(self.panepanel)
48 self.on_hide()
49 else:
50 self.Show(self.panepanel)
51 self.on_show()
52 self.visible = not self.visible
53 self.button.SetLabel(">" if self.button.GetLabel() == "<" else "<")
54
55 class LeftPaneToggleable(ToggleablePane):
56 def __init__(self, root, parentpanel, parentsizers):
57 super(LeftPaneToggleable, self).__init__(root, "<", parentpanel, parentsizers)
58 self.Add(self.panepanel, 0, wx.EXPAND)
59 self.Add(self.button, 0)
60
61 def set_sizer(self, sizer):
62 self.panepanel.SetSizer(sizer)
63
64 def on_show(self):
65 for sizer in self.parentsizers:
66 sizer.Layout()
67
68 def on_hide(self):
69 for sizer in self.parentsizers:
70 # Expand right splitterwindow
71 if isinstance(sizer, wx.SplitterWindow):
72 if sizer.shrinked:
73 button_width = self.button.GetSize()[0]
74 sizer.SetSashPosition(sizer.GetSize()[0] - button_width)
75 else:
76 sizer.Layout()
77
78 class LogPaneToggleable(ToggleablePane):
79 def __init__(self, root, parentpanel, parentsizers):
80 super(LogPaneToggleable, self).__init__(root, ">", parentpanel, parentsizers)
81 self.Add(self.button, 0)
82 pane = LogPane(root, self.panepanel)
83 self.panepanel.SetSizer(pane)
84 self.Add(self.panepanel, 1, wx.EXPAND)
85 self.splitter = self.parentpanel.GetParent()
86
87 def on_show(self):
88 self.splitter.shrinked = False
89 self.splitter.SetSashPosition(self.splitter.GetSize()[0] - self.orig_width)
90 self.splitter.SetMinimumPaneSize(self.orig_min_size)
91 self.splitter.SetSashGravity(self.orig_gravity)
92 if hasattr(self.splitter, "SetSashSize"): self.splitter.SetSashSize(self.orig_sash_size)
93 if hasattr(self.splitter, "SetSashInvisible"): self.splitter.SetSashInvisible(False)
94 for sizer in self.parentsizers:
95 sizer.Layout()
96
97 def on_hide(self):
98 self.splitter.shrinked = True
99 self.orig_width = self.splitter.GetSize()[0] - self.splitter.GetSashPosition()
100 button_width = self.button.GetSize()[0]
101 self.orig_min_size = self.splitter.GetMinimumPaneSize()
102 self.orig_gravity = self.splitter.GetSashGravity()
103 self.splitter.SetMinimumPaneSize(button_width)
104 self.splitter.SetSashGravity(1)
105 self.splitter.SetSashPosition(self.splitter.GetSize()[0] - button_width)
106 if hasattr(self.splitter, "SetSashSize"):
107 self.orig_sash_size = self.splitter.GetSashSize()
108 self.splitter.SetSashSize(0)
109 if hasattr(self.splitter, "SetSashInvisible"): self.splitter.SetSashInvisible(True)
110 for sizer in self.parentsizers:
111 sizer.Layout()
112
113 class MainWindow(wx.Frame):
114
115 def __init__(self, *args, **kwargs):
116 super(MainWindow, self).__init__(*args, **kwargs)
117 # this list will contain all controls that should be only enabled
118 # when we're connected to a printer
119 self.panel = wx.Panel(self, -1)
120 self.reset_ui()
121 self.statefulControls = []
122
123 def reset_ui(self):
124 self.panels = []
125 self.printerControls = []
126
127 def newPanel(self, parent, add_to_list = True):
128 panel = wx.Panel(parent)
129 self.registerPanel(panel, add_to_list)
130 return panel
131
132 def registerPanel(self, panel, add_to_list = True):
133 panel.SetBackgroundColour(self.bgcolor)
134 if add_to_list: self.panels.append(panel)
135
136 def createTabbedGui(self):
137 self.notesizer = wx.BoxSizer(wx.VERTICAL)
138 self.notebook = wx.Notebook(self.panel)
139 self.notebook.SetBackgroundColour(self.bgcolor)
140 page1panel = self.newPanel(self.notebook)
141 page2panel = self.newPanel(self.notebook)
142 self.mainsizer_page1 = wx.BoxSizer(wx.VERTICAL)
143 page1panel1 = self.newPanel(page1panel)
144 page1panel2 = self.newPanel(page1panel)
145 self.toolbarsizer = MainToolbar(self, page1panel1, use_wrapsizer = True)
146 page1panel1.SetSizer(self.toolbarsizer)
147 self.mainsizer_page1.Add(page1panel1, 0, wx.EXPAND)
148 self.lowersizer = wx.BoxSizer(wx.HORIZONTAL)
149 page1panel2.SetSizer(self.lowersizer)
150 leftsizer = wx.BoxSizer(wx.VERTICAL)
151 controls_sizer = ControlsSizer(self, page1panel2, True)
152 leftsizer.Add(controls_sizer, 1, wx.ALIGN_CENTER)
153 rightsizer = wx.BoxSizer(wx.VERTICAL)
154 extracontrols = wx.GridBagSizer()
155 add_extra_controls(extracontrols, self, page1panel2, controls_sizer.extra_buttons)
156 rightsizer.AddStretchSpacer()
157 rightsizer.Add(extracontrols, 0, wx.ALIGN_CENTER)
158 self.lowersizer.Add(leftsizer, 0, wx.ALIGN_CENTER | wx.RIGHT, border = 10)
159 self.lowersizer.Add(rightsizer, 1, wx.ALIGN_CENTER)
160 self.mainsizer_page1.Add(page1panel2, 1)
161 self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
162 self.splitterwindow = wx.SplitterWindow(page2panel, style = wx.SP_3D)
163 page2sizer1 = wx.BoxSizer(wx.HORIZONTAL)
164 page2panel1 = self.newPanel(self.splitterwindow)
165 page2sizer2 = wx.BoxSizer(wx.HORIZONTAL)
166 page2panel2 = self.newPanel(self.splitterwindow)
167 vizpane = VizPane(self, page2panel1)
168 page2sizer1.Add(vizpane, 1, wx.EXPAND)
169 page2sizer2.Add(LogPane(self, page2panel2), 1, wx.EXPAND)
170 page2panel1.SetSizer(page2sizer1)
171 page2panel2.SetSizer(page2sizer2)
172 self.splitterwindow.SetMinimumPaneSize(1)
173 self.splitterwindow.SetSashGravity(0.5)
174 self.splitterwindow.SplitVertically(page2panel1, page2panel2,
175 self.settings.last_sash_position)
176 self.mainsizer.Add(self.splitterwindow, 1, wx.EXPAND)
177 page1panel.SetSizer(self.mainsizer_page1)
178 page2panel.SetSizer(self.mainsizer)
179 self.notesizer.Add(self.notebook, 1, wx.EXPAND)
180 self.notebook.AddPage(page1panel, _("Commands"))
181 self.notebook.AddPage(page2panel, _("Status"))
182 if self.settings.uimode == _("Tabbed with platers"):
183 from printrun.stlplater import StlPlaterPanel
184 from printrun.gcodeplater import GcodePlaterPanel
185 page3panel = StlPlaterPanel(parent = self.notebook,
186 callback = self.platecb,
187 build_dimensions = self.build_dimensions_list,
188 circular_platform = self.settings.circular_bed,
189 simarrange_path = self.settings.simarrange_path,
190 antialias_samples = int(self.settings.antialias3dsamples))
191 page4panel = GcodePlaterPanel(parent = self.notebook,
192 callback = self.platecb,
193 build_dimensions = self.build_dimensions_list,
194 circular_platform = self.settings.circular_bed,
195 antialias_samples = int(self.settings.antialias3dsamples))
196 self.registerPanel(page3panel)
197 self.registerPanel(page4panel)
198 self.notebook.AddPage(page3panel, _("Plater"))
199 self.notebook.AddPage(page4panel, _("G-Code Plater"))
200 self.panel.SetSizer(self.notesizer)
201 self.panel.Bind(wx.EVT_MOUSE_EVENTS, self.editbutton)
202 self.Bind(wx.EVT_CLOSE, self.kill)
203
204 # Custom buttons
205 if wx.VERSION > (2, 9): self.cbuttonssizer = wx.WrapSizer(wx.HORIZONTAL)
206 else: self.cbuttonssizer = wx.GridBagSizer()
207 self.cbuttonssizer = wx.GridBagSizer()
208 self.centerpanel = self.newPanel(page1panel2)
209 self.centerpanel.SetSizer(self.cbuttonssizer)
210 rightsizer.Add(self.centerpanel, 0, wx.ALIGN_CENTER)
211 rightsizer.AddStretchSpacer()
212
213 self.panel.SetSizerAndFit(self.notesizer)
214
215 self.cbuttons_reload()
216 minsize = self.lowersizer.GetMinSize() # lower pane
217 minsize[1] = self.notebook.GetSize()[1]
218 self.SetMinSize(self.ClientToWindowSize(minsize)) # client to window
219 self.Fit()
220
221 def createGui(self, compact = False, mini = False):
222 self.mainsizer = wx.BoxSizer(wx.VERTICAL)
223 self.lowersizer = wx.BoxSizer(wx.HORIZONTAL)
224 upperpanel = self.newPanel(self.panel, False)
225 self.toolbarsizer = MainToolbar(self, upperpanel)
226 lowerpanel = self.newPanel(self.panel)
227 upperpanel.SetSizer(self.toolbarsizer)
228 lowerpanel.SetSizer(self.lowersizer)
229 leftpanel = self.newPanel(lowerpanel)
230 left_pane = LeftPaneToggleable(self, leftpanel, [self.lowersizer])
231 leftpanel.SetSizer(left_pane)
232 left_real_panel = left_pane.panepanel
233 controls_panel = self.newPanel(left_real_panel)
234 controls_sizer = ControlsSizer(self, controls_panel, mini_mode = mini)
235 controls_panel.SetSizer(controls_sizer)
236 left_sizer = wx.BoxSizer(wx.VERTICAL)
237 left_sizer.Add(controls_panel, 1, wx.EXPAND)
238 left_pane.set_sizer(left_sizer)
239 self.lowersizer.Add(leftpanel, 0, wx.EXPAND)
240 if not compact: # Use a splitterwindow to group viz and log
241 rightpanel = self.newPanel(lowerpanel)
242 rightsizer = wx.BoxSizer(wx.VERTICAL)
243 rightpanel.SetSizer(rightsizer)
244 self.splitterwindow = wx.SplitterWindow(rightpanel, style = wx.SP_3D)
245 self.splitterwindow.SetMinimumPaneSize(150)
246 self.splitterwindow.SetSashGravity(0.8)
247 rightsizer.Add(self.splitterwindow, 1, wx.EXPAND)
248 vizpanel = self.newPanel(self.splitterwindow)
249 logpanel = self.newPanel(self.splitterwindow)
250 self.splitterwindow.SplitVertically(vizpanel, logpanel,
251 self.settings.last_sash_position)
252 self.splitterwindow.shrinked = False
253 else:
254 vizpanel = self.newPanel(lowerpanel)
255 logpanel = self.newPanel(left_real_panel)
256 viz_pane = VizPane(self, vizpanel)
257 # Custom buttons
258 if wx.VERSION > (2, 9): self.cbuttonssizer = wx.WrapSizer(wx.HORIZONTAL)
259 else: self.cbuttonssizer = wx.GridBagSizer()
260 self.centerpanel = self.newPanel(vizpanel)
261 self.centerpanel.SetSizer(self.cbuttonssizer)
262 viz_pane.Add(self.centerpanel, 0, flag = wx.ALIGN_CENTER)
263 vizpanel.SetSizer(viz_pane)
264 if compact:
265 log_pane = LogPane(self, logpanel)
266 else:
267 log_pane = LogPaneToggleable(self, logpanel, [self.lowersizer])
268 left_pane.parentsizers.append(self.splitterwindow)
269 logpanel.SetSizer(log_pane)
270 if not compact:
271 self.lowersizer.Add(rightpanel, 1, wx.EXPAND)
272 else:
273 left_sizer.Add(logpanel, 1, wx.EXPAND)
274 self.lowersizer.Add(vizpanel, 1, wx.EXPAND)
275 self.mainsizer.Add(upperpanel, 0, wx.EXPAND)
276 self.mainsizer.Add(lowerpanel, 1, wx.EXPAND)
277 self.panel.SetSizer(self.mainsizer)
278 self.panel.Bind(wx.EVT_MOUSE_EVENTS, self.editbutton)
279 self.Bind(wx.EVT_CLOSE, self.kill)
280
281 self.mainsizer.Layout()
282 # This prevents resizing below a reasonnable value
283 # We sum the lowersizer (left pane / viz / log) min size
284 # the toolbar height and the statusbar/menubar sizes
285 minsize = [0, 0]
286 minsize[0] = self.lowersizer.GetMinSize()[0] # lower pane
287 minsize[1] = max(viz_pane.GetMinSize()[1], controls_sizer.GetMinSize()[1])
288 minsize[1] += self.toolbarsizer.GetMinSize()[1] # toolbar height
289 displaysize = wx.DisplaySize()
290 minsize[0] = min(minsize[0], displaysize[0])
291 minsize[1] = min(minsize[1], displaysize[1])
292 self.SetMinSize(self.ClientToWindowSize(minsize)) # client to window
293
294 self.cbuttons_reload()
295
296 def gui_set_connected(self):
297 self.xyb.enable()
298 self.zb.enable()
299 for control in self.printerControls:
300 control.Enable()
301
302 def gui_set_disconnected(self):
303 self.printbtn.Disable()
304 self.pausebtn.Disable()
305 self.recoverbtn.Disable()
306 for control in self.printerControls:
307 control.Disable()
308 self.xyb.disable()
309 self.zb.disable()

mercurial