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...\tCTRL+L')
34 self.Bind(wx.EVT_MENU, self.OnLoadModel, i)
35 i = fileMenu.Append(-1, 'Prepare print...\tCTRL+R')
36 self.Bind(wx.EVT_MENU, self.OnSlice, i)
37 i = fileMenu.Append(-1, 'Print...\tCTRL+P')
38 self.Bind(wx.EVT_MENU, self.OnPrint, i)
39 fileMenu.AppendSeparator()
40 i = fileMenu.Append(-1, 'Preferences...\tCTRL+,')
41 self.Bind(wx.EVT_MENU, self.OnPreferences, i)
42 fileMenu.AppendSeparator()
43 i = fileMenu.Append(wx.ID_EXIT, 'Quit')
44 self.Bind(wx.EVT_MENU, self.OnQuit, i)
45 menubar.Append(fileMenu, '&File')
48 i = toolsMenu.Append(-1, 'Switch to Normal mode...')
49 self.Bind(wx.EVT_MENU, self.OnNormalSwitch, i)
50 menubar.Append(toolsMenu, 'Normal mode')
53 i = helpMenu.Append(-1, 'Online documentation...')
54 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://daid.github.com/Cura'), i)
55 i = helpMenu.Append(-1, 'Report a problem...')
56 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/daid/Cura/issues'), i)
57 menubar.Append(helpMenu, 'Help')
58 self.SetMenuBar(menubar)
60 if profile.getPreference('lastFile') != '':
61 self.filelist = profile.getPreference('lastFile').split(';')
62 self.SetTitle('Cura - %s - %s' % (version.getVersion(), self.filelist[-1]))
65 self.progressPanelList = []
68 self.preview3d = preview3d.previewPanel(self)
70 configPanel = wx.Panel(self)
71 printTypePanel = wx.Panel(configPanel)
72 self.printTypeNormal = wx.RadioButton(printTypePanel, -1, 'Normal quality print', style=wx.RB_GROUP)
73 self.printTypeLow = wx.RadioButton(printTypePanel, -1, 'Fast low quality print')
74 self.printTypeHigh = wx.RadioButton(printTypePanel, -1, 'High quality print')
75 self.printTypeJoris = wx.RadioButton(printTypePanel, -1, 'Thin walled cup or vase')
77 printMaterialPanel = wx.Panel(configPanel)
78 self.printMaterialPLA = wx.RadioButton(printMaterialPanel, -1, 'PLA', style=wx.RB_GROUP)
79 self.printMaterialABS = wx.RadioButton(printMaterialPanel, -1, 'ABS')
80 self.printMaterialDiameter = wx.TextCtrl(printMaterialPanel, -1, profile.getProfileSetting('filament_diameter'))
82 self.printSupport = wx.CheckBox(configPanel, -1, 'Print support structure')
84 sizer = wx.GridBagSizer()
85 configPanel.SetSizer(sizer)
87 sb = wx.StaticBox(printTypePanel, label="Select a print type:")
88 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
89 boxsizer.Add(self.printTypeNormal)
90 boxsizer.Add(self.printTypeLow)
91 boxsizer.Add(self.printTypeHigh)
92 boxsizer.Add(self.printTypeJoris)
93 printTypePanel.SetSizer(wx.BoxSizer(wx.VERTICAL))
94 printTypePanel.GetSizer().Add(boxsizer, flag=wx.EXPAND)
95 sizer.Add(printTypePanel, (0,0), flag=wx.EXPAND)
97 sb = wx.StaticBox(printMaterialPanel, label="Material:")
98 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
99 boxsizer.Add(self.printMaterialPLA)
100 boxsizer.Add(self.printMaterialABS)
101 boxsizer.Add(wx.StaticText(printMaterialPanel, -1, 'Diameter:'))
102 boxsizer.Add(self.printMaterialDiameter)
103 printMaterialPanel.SetSizer(wx.BoxSizer(wx.VERTICAL))
104 printMaterialPanel.GetSizer().Add(boxsizer, flag=wx.EXPAND)
105 sizer.Add(printMaterialPanel, (1,0), flag=wx.EXPAND)
107 sb = wx.StaticBox(configPanel, label="Other:")
108 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
109 boxsizer.Add(self.printSupport)
110 sizer.Add(boxsizer, (2,0), flag=wx.EXPAND)
112 # load and slice buttons.
113 loadButton = wx.Button(self, -1, '&Load model')
114 sliceButton = wx.Button(self, -1, 'P&repare print')
115 printButton = wx.Button(self, -1, '&Print')
116 self.Bind(wx.EVT_BUTTON, self.OnLoadModel, loadButton)
117 self.Bind(wx.EVT_BUTTON, self.OnSlice, sliceButton)
118 self.Bind(wx.EVT_BUTTON, self.OnPrint, printButton)
119 #Also bind double clicking the 3D preview to load an STL file.
120 self.preview3d.glCanvas.Bind(wx.EVT_LEFT_DCLICK, self.OnLoadModel, self.preview3d.glCanvas)
122 #Main sizer, to position the preview window, buttons and tab control
123 sizer = wx.GridBagSizer()
125 sizer.Add(configPanel, (0,0), span=(1,1), flag=wx.EXPAND)
126 sizer.Add(self.preview3d, (0,1), span=(1,3), flag=wx.EXPAND)
127 sizer.AddGrowableCol(2)
128 sizer.AddGrowableRow(0)
129 sizer.Add(loadButton, (1,1), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
130 sizer.Add(sliceButton, (1,2), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
131 sizer.Add(printButton, (1,3), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
134 if len(self.filelist) > 0:
135 self.preview3d.loadModelFiles(self.filelist)
137 self.SetBackgroundColour(configPanel.GetBackgroundColour())
139 self.updateProfileToControls()
141 self.printTypeNormal.SetValue(True)
142 self.printMaterialPLA.SetValue(True)
146 self.SetMinSize(self.GetSize())
150 def OnPreferences(self, e):
151 prefDialog = preferencesDialog.preferencesDialog(self)
153 prefDialog.Show(True)
155 def OnLoadModel(self, e):
156 dlg=wx.FileDialog(self, "Open file to print", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
157 dlg.SetWildcard(meshLoader.wildcardFilter())
158 if dlg.ShowModal() == wx.ID_OK:
159 self.filelist = [dlg.GetPath()]
160 profile.putPreference('lastFile', ';'.join(self.filelist))
161 self.preview3d.loadModelFiles(self.filelist, True)
162 self.preview3d.setViewMode("Normal")
165 def OnDropFiles(self, filenames):
166 self.filelist = filenames
167 profile.putPreference('lastFile', ';'.join(self.filelist))
168 self.preview3d.loadModelFiles(self.filelist, True)
169 self.preview3d.setViewMode("Normal")
171 def OnSlice(self, e):
172 if len(self.filelist) < 1:
173 wx.MessageBox('You need to load a file before you can prepare it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
175 #save the current profile so we can put it back latter
176 oldProfile = profile.getGlobalProfileString()
178 put = profile.putProfileSetting
179 get = profile.getProfileSetting
181 put('layer_height', '0.2')
182 put('wall_thickness', '0.8')
183 put('solid_layer_thickness', '0.6')
184 put('fill_density', '20')
185 put('skirt_line_count', '1')
186 put('skirt_gap', '6.0')
187 put('print_speed', '50')
188 put('print_temperature', '220')
189 put('support', 'None')
190 put('retraction_enable', 'False')
191 put('retraction_min_travel', '5.0')
192 put('retraction_speed', '40.0')
193 put('retraction_amount', '4.5')
194 put('retraction_extra', '0.0')
195 put('travel_speed', '150')
196 put('max_z_speed', '3.0')
197 put('bottom_layer_speed', '25')
198 put('cool_min_layer_time', '10')
199 put('fan_enabled', 'True')
200 put('fan_layer', '1')
201 put('fan_speed', '100')
202 #put('model_scale', '1.0')
203 #put('flip_x', 'False')
204 #put('flip_y', 'False')
205 #put('flip_z', 'False')
206 #put('model_rotate_base', '0')
207 #put('model_multiply_x', '1')
208 #put('model_multiply_y', '1')
209 put('extra_base_wall_thickness', '0.0')
210 put('sequence', 'Loops > Perimeter > Infill')
211 put('force_first_layer_sequence', 'True')
212 put('infill_type', 'Line')
213 put('solid_top', 'True')
214 put('fill_overlap', '15')
215 put('support_rate', '50')
216 put('support_distance', '0.5')
217 put('joris', 'False')
218 put('cool_min_feedrate', '5')
219 put('bridge_speed', '100')
220 put('raft_margin', '5')
221 put('raft_base_material_amount', '100')
222 put('raft_interface_material_amount', '100')
223 put('bottom_thickness', '0.0')
225 if self.printSupport.GetValue():
226 put('support', 'Exterior Only')
228 nozzle_size = float(get('nozzle_size'))
229 if self.printTypeNormal.GetValue():
230 put('wall_thickness', nozzle_size * 2.0)
231 put('layer_height', '0.2')
232 put('fill_density', '20')
233 elif self.printTypeLow.GetValue():
234 put('wall_thickness', nozzle_size * 1.4)
235 put('layer_height', '0.25')
236 put('fill_density', '10')
237 put('print_speed', '80')
238 put('cool_min_layer_time', '3')
239 put('bottom_layer_speed', '40')
240 elif self.printTypeHigh.GetValue():
241 put('wall_thickness', nozzle_size * 2.0)
242 put('layer_height', '0.1')
243 put('fill_density', '30')
244 put('bottom_layer_speed', '15')
245 put('bottom_thickness', '0.2')
246 elif self.printTypeJoris.GetValue():
247 put('wall_thickness', nozzle_size * 1.5)
248 put('layer_height', '0.3')
249 put('solid_layer_thickness', '0.9')
250 put('fill_density', '0')
252 put('extra_base_wall_thickness', '15.0')
253 put('sequence', 'Infill > Loops > Perimeter')
254 put('force_first_layer_sequence', 'False')
255 put('solid_top', 'False')
256 put('support', 'None')
257 put('cool_min_layer_time', '3')
259 put('filament_diameter', self.printMaterialDiameter.GetValue())
260 if self.printMaterialPLA.GetValue():
261 put('filament_density', '1.00')
262 put('enable_raft', 'False')
263 put('skirt_line_count', '1')
264 if self.printMaterialABS.GetValue():
265 put('filament_density', '0.85')
266 put('enable_raft', 'True')
267 put('skirt_line_count', '0')
268 put('fan_layer', '1')
269 put('bottom_thickness', '0.0')
270 put('print_temperature', '260')
272 #Create a progress panel and add it to the window. The progress panel will start the Skein operation.
273 spp = sliceProgessPanel.sliceProgessPanel(self, self, self.filelist)
274 self.sizer.Add(spp, (len(self.progressPanelList)+2,0), span=(1,4), flag=wx.EXPAND)
276 newSize = self.GetSize();
277 newSize.IncBy(0, spp.GetSize().GetHeight())
278 if newSize.GetWidth() < wx.GetDisplaySize()[0]:
279 self.SetSize(newSize)
280 self.progressPanelList.append(spp)
282 #Restore the old profile.
283 profile.loadGlobalProfileFromString(oldProfile)
285 def OnPrint(self, e):
286 if len(self.filelist) < 1:
287 wx.MessageBox('You need to load a file and prepare it before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
289 if not os.path.exists(sliceRun.getExportFilename(self.filelist[0])):
290 wx.MessageBox('You need to prepare the file before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
292 printWindow.printFile(sliceRun.getExportFilename(self.filelist[0]))
294 def OnNormalSwitch(self, e):
295 from gui import mainWindow
296 profile.putPreference('startMode', 'Normal')
297 mainWindow.mainWindow()
300 def removeSliceProgress(self, spp):
301 self.progressPanelList.remove(spp)
302 newSize = self.GetSize();
303 newSize.IncBy(0, -spp.GetSize().GetHeight())
304 if newSize.GetWidth() < wx.GetDisplaySize()[0]:
305 self.SetSize(newSize)
307 self.sizer.Detach(spp)
308 for spp in self.progressPanelList:
309 self.sizer.Detach(spp)
311 for spp in self.progressPanelList:
312 self.sizer.Add(spp, (i,0), span=(1,4), flag=wx.EXPAND)
319 def OnClose(self, e):
322 def updateProfileToControls(self):
323 super(simpleModeWindow, self).updateProfileToControls()
324 self.preview3d.updateProfileToControls()