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