1 from __future__ import absolute_import
4 import wx, os, platform, types, webbrowser
6 from gui import configBase
7 from gui import preview3d
8 from gui import sliceProgessPanel
9 from gui import preferencesDialog
10 from gui import configWizard
11 from gui import firmwareInstall
12 from gui import dropTarget
13 from gui import printWindow
15 from util import validators
16 from util import profile
17 from util import version
18 from util import sliceRun
19 from util import meshLoader
21 class simpleModeWindow(configBase.configWindowBase):
22 "Main user interface window for Quickprint mode"
24 super(simpleModeWindow, self).__init__(title='Cura - Quickprint - ' + version.getVersion())
26 wx.EVT_CLOSE(self, self.OnClose)
27 #self.SetIcon(icon.getMainIcon())
29 self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.supportedExtensions()))
31 menubar = wx.MenuBar()
33 i = fileMenu.Append(-1, 'Load model file...')
34 self.Bind(wx.EVT_MENU, self.OnLoadModel, i)
35 fileMenu.AppendSeparator()
36 i = fileMenu.Append(-1, 'Preferences...')
37 self.Bind(wx.EVT_MENU, self.OnPreferences, i)
38 fileMenu.AppendSeparator()
39 i = fileMenu.Append(wx.ID_EXIT, 'Quit')
40 self.Bind(wx.EVT_MENU, self.OnQuit, i)
41 menubar.Append(fileMenu, '&File')
44 i = toolsMenu.Append(-1, 'Switch to Normal mode...')
45 self.Bind(wx.EVT_MENU, self.OnNormalSwitch, i)
46 menubar.Append(toolsMenu, 'Normal mode')
49 i = helpMenu.Append(-1, 'Online documentation...')
50 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://daid.github.com/Cura'), i)
51 i = helpMenu.Append(-1, 'Report a problem...')
52 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/daid/Cura/issues'), i)
53 menubar.Append(helpMenu, 'Help')
54 self.SetMenuBar(menubar)
56 if profile.getPreference('lastFile') != '':
57 self.filelist = profile.getPreference('lastFile').split(';')
58 self.SetTitle('Cura - %s - %s' % (version.getVersion(), self.filelist[-1]))
61 self.progressPanelList = []
64 self.preview3d = preview3d.previewPanel(self)
66 configPanel = wx.Panel(self)
67 printTypePanel = wx.Panel(configPanel)
68 self.printTypeNormal = wx.RadioButton(printTypePanel, -1, 'Normal quality print', style=wx.RB_GROUP)
69 self.printTypeLow = wx.RadioButton(printTypePanel, -1, 'Fast low quality print')
70 self.printTypeHigh = wx.RadioButton(printTypePanel, -1, 'High quality print')
71 self.printTypeJoris = wx.RadioButton(printTypePanel, -1, 'Thin walled cup or vase')
73 printMaterialPanel = wx.Panel(configPanel)
74 self.printMaterialPLA = wx.RadioButton(printMaterialPanel, -1, 'PLA', style=wx.RB_GROUP)
75 self.printMaterialABS = wx.RadioButton(printMaterialPanel, -1, 'ABS')
76 self.printMaterialDiameter = wx.TextCtrl(printMaterialPanel, -1, profile.getProfileSetting('filament_diameter'))
78 self.printSupport = wx.CheckBox(configPanel, -1, 'Print support structure')
80 sizer = wx.GridBagSizer()
81 configPanel.SetSizer(sizer)
83 sb = wx.StaticBox(printTypePanel, label="Select a print type:")
84 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
85 boxsizer.Add(self.printTypeNormal)
86 boxsizer.Add(self.printTypeLow)
87 boxsizer.Add(self.printTypeHigh)
88 boxsizer.Add(self.printTypeJoris)
89 printTypePanel.SetSizer(wx.BoxSizer(wx.VERTICAL))
90 printTypePanel.GetSizer().Add(boxsizer, flag=wx.EXPAND)
91 sizer.Add(printTypePanel, (0,0), flag=wx.EXPAND)
93 sb = wx.StaticBox(printMaterialPanel, label="Material:")
94 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
95 boxsizer.Add(self.printMaterialPLA)
96 boxsizer.Add(self.printMaterialABS)
97 boxsizer.Add(wx.StaticText(printMaterialPanel, -1, 'Diameter:'))
98 boxsizer.Add(self.printMaterialDiameter)
99 printMaterialPanel.SetSizer(wx.BoxSizer(wx.VERTICAL))
100 printMaterialPanel.GetSizer().Add(boxsizer, flag=wx.EXPAND)
101 sizer.Add(printMaterialPanel, (1,0), flag=wx.EXPAND)
103 sb = wx.StaticBox(configPanel, label="Other:")
104 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
105 boxsizer.Add(self.printSupport)
106 sizer.Add(boxsizer, (2,0), flag=wx.EXPAND)
108 # load and slice buttons.
109 loadButton = wx.Button(self, -1, '&Load Model')
110 sliceButton = wx.Button(self, -1, 'P&repare print')
111 printButton = wx.Button(self, -1, '&Print')
112 self.Bind(wx.EVT_BUTTON, self.OnLoadModel, loadButton)
113 self.Bind(wx.EVT_BUTTON, self.OnSlice, sliceButton)
114 self.Bind(wx.EVT_BUTTON, self.OnPrint, printButton)
115 #Also bind double clicking the 3D preview to load an STL file.
116 self.preview3d.glCanvas.Bind(wx.EVT_LEFT_DCLICK, self.OnLoadModel, self.preview3d.glCanvas)
118 #Main sizer, to position the preview window, buttons and tab control
119 sizer = wx.GridBagSizer()
121 sizer.Add(configPanel, (0,0), span=(1,1), flag=wx.EXPAND)
122 sizer.Add(self.preview3d, (0,1), span=(1,3), flag=wx.EXPAND)
123 sizer.AddGrowableCol(2)
124 sizer.AddGrowableRow(0)
125 sizer.Add(loadButton, (1,1), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
126 sizer.Add(sliceButton, (1,2), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
127 sizer.Add(printButton, (1,3), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
130 if len(self.filelist) > 0:
131 self.preview3d.loadModelFiles(self.filelist)
133 self.SetBackgroundColour(configPanel.GetBackgroundColour())
135 self.updateProfileToControls()
137 self.printTypeNormal.SetValue(True)
138 self.printMaterialPLA.SetValue(True)
140 self.SetAcceleratorTable(wx.AcceleratorTable([(wx.ACCEL_CTRL, ord('L'), loadButton.GetId()),
141 (wx.ACCEL_CTRL, ord('R'), sliceButton.GetId()),
142 (wx.ACCEL_CTRL, ord('P'), printButton.GetId())
147 self.SetMinSize(self.GetSize())
151 def OnPreferences(self, e):
152 prefDialog = preferencesDialog.preferencesDialog(self)
154 prefDialog.Show(True)
156 def OnLoadModel(self, e):
157 dlg=wx.FileDialog(self, "Open file to print", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
158 dlg.SetWildcard(meshLoader.wildcardFilter())
159 if dlg.ShowModal() == wx.ID_OK:
160 self.filelist = [dlg.GetPath()]
161 profile.putPreference('lastFile', ';'.join(self.filelist))
162 self.preview3d.loadModelFiles(self.filelist, True)
163 self.preview3d.setViewMode("Normal")
166 def OnDropFiles(self, filenames):
167 self.filelist = filenames
168 profile.putPreference('lastFile', ';'.join(self.filelist))
169 self.preview3d.loadModelFiles(self.filelist, True)
170 self.preview3d.setViewMode("Normal")
172 def OnSlice(self, e):
173 if len(self.filelist) < 1:
174 wx.MessageBox('You need to load a file before you can prepare it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
176 #save the current profile so we can put it back latter
177 oldProfile = profile.getGlobalProfileString()
179 put = profile.putProfileSetting
180 get = profile.getProfileSetting
182 put('layer_height', '0.2')
183 put('wall_thickness', '0.8')
184 put('solid_layer_thickness', '0.6')
185 put('fill_density', '20')
186 put('skirt_line_count', '1')
187 put('skirt_gap', '6.0')
188 put('print_speed', '50')
189 put('print_temperature', '220')
190 put('support', 'None')
191 #put('machine_center_x', '100')
192 #put('machine_center_y', '100')
193 put('retraction_enable', 'False')
194 put('retraction_min_travel', '5.0')
195 put('retraction_speed', '40.0')
196 put('retraction_amount', '4.5')
197 put('retraction_extra', '0.0')
198 put('travel_speed', '150')
199 put('max_z_speed', '3.0')
200 put('bottom_layer_speed', '25')
201 put('cool_min_layer_time', '10')
202 put('fan_enabled', 'True')
203 put('fan_layer', '1')
204 put('fan_speed', '100')
205 #put('model_scale', '1.0')
206 #put('flip_x', 'False')
207 #put('flip_y', 'False')
208 #put('flip_z', 'False')
209 #put('model_rotate_base', '0')
210 #put('model_multiply_x', '1')
211 #put('model_multiply_y', '1')
212 put('extra_base_wall_thickness', '0.0')
213 put('sequence', 'Loops > Perimeter > Infill')
214 put('force_first_layer_sequence', 'True')
215 put('infill_type', 'Line')
216 put('solid_top', 'True')
217 put('fill_overlap', '15')
218 put('support_rate', '50')
219 put('support_distance', '0.5')
220 put('joris', 'False')
221 put('cool_min_feedrate', '5')
222 put('bridge_speed', '100')
223 put('raft_margin', '5')
224 put('raft_base_material_amount', '100')
225 put('raft_interface_material_amount', '100')
226 put('bottom_thickness', '0.0')
228 if self.printSupport.GetValue():
229 put('support', 'Exterior Only')
231 nozzle_size = float(get('nozzle_size'))
232 if self.printTypeNormal.GetValue():
233 put('wall_thickness', nozzle_size * 2.0)
234 put('layer_height', '0.2')
235 put('fill_density', '20')
236 elif self.printTypeLow.GetValue():
237 put('wall_thickness', nozzle_size * 1.4)
238 put('layer_height', '0.25')
239 put('fill_density', '10')
240 put('print_speed', '80')
241 put('cool_min_layer_time', '3')
242 put('bottom_layer_speed', '40')
243 elif self.printTypeHigh.GetValue():
244 put('wall_thickness', nozzle_size * 2.0)
245 put('layer_height', '0.1')
246 put('fill_density', '30')
247 put('bottom_layer_speed', '15')
248 put('bottom_thickness', '0.2')
249 elif self.printTypeJoris.GetValue():
250 put('wall_thickness', nozzle_size * 1.5)
251 put('layer_height', '0.3')
252 put('solid_layer_thickness', '0.9')
253 put('fill_density', '0')
255 put('extra_base_wall_thickness', '15.0')
256 put('sequence', 'Infill > Loops > Perimeter')
257 put('force_first_layer_sequence', 'False')
258 put('solid_top', 'False')
259 put('support', 'None')
260 put('cool_min_layer_time', '3')
262 put('filament_diameter', self.printMaterialDiameter.GetValue())
263 if self.printMaterialPLA.GetValue():
264 put('filament_density', '1.00')
265 put('enable_raft', 'False')
266 put('skirt_line_count', '1')
267 if self.printMaterialABS.GetValue():
268 put('filament_density', '0.85')
269 put('enable_raft', 'True')
270 put('skirt_line_count', '0')
271 put('fan_layer', '1')
272 put('bottom_thickness', '0.0')
273 put('print_temperature', '260')
275 #Create a progress panel and add it to the window. The progress panel will start the Skein operation.
276 spp = sliceProgessPanel.sliceProgessPanel(self, self, self.filelist)
277 self.sizer.Add(spp, (len(self.progressPanelList)+2,0), span=(1,4), flag=wx.EXPAND)
279 newSize = self.GetSize();
280 newSize.IncBy(0, spp.GetSize().GetHeight())
281 if newSize.GetWidth() < wx.GetDisplaySize()[0]:
282 self.SetSize(newSize)
283 self.progressPanelList.append(spp)
285 #Restore the old profile.
286 profile.loadGlobalProfileFromString(oldProfile)
288 def OnPrint(self, e):
289 if len(self.filelist) < 1:
290 wx.MessageBox('You need to load a file and prepare it before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
292 if not os.path.exists(sliceRun.getExportFilename(self.filelist[0])):
293 wx.MessageBox('You need to prepare the file before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
295 printWindow.printFile(sliceRun.getExportFilename(self.filelist[0]))
297 def OnNormalSwitch(self, e):
298 from gui import mainWindow
299 profile.putPreference('startMode', 'Normal')
300 mainWindow.mainWindow()
303 def removeSliceProgress(self, spp):
304 self.progressPanelList.remove(spp)
305 newSize = self.GetSize();
306 newSize.IncBy(0, -spp.GetSize().GetHeight())
307 if newSize.GetWidth() < wx.GetDisplaySize()[0]:
308 self.SetSize(newSize)
310 self.sizer.Detach(spp)
311 for spp in self.progressPanelList:
312 self.sizer.Detach(spp)
314 for spp in self.progressPanelList:
315 self.sizer.Add(spp, (i,0), span=(1,4), flag=wx.EXPAND)
322 def OnClose(self, e):
325 def updateProfileToControls(self):
326 super(simpleModeWindow, self).updateProfileToControls()
327 self.preview3d.updateProfileToControls()