1 from __future__ import absolute_import
7 from Cura.gui import configBase
8 from Cura.gui import preview3d
9 from Cura.gui import sliceProgessPanel
10 from Cura.gui import preferencesDialog
11 from Cura.gui.util import dropTarget
12 from Cura.gui import printWindow
13 from Cura.util import profile
14 from Cura.util import version
15 from Cura.util import sliceRun
16 from Cura.util import meshLoader
18 class simpleModeWindow(configBase.configWindowBase):
19 "Main user interface window for Quickprint mode"
21 super(simpleModeWindow, self).__init__(title='Cura - Quickprint - ' + version.getVersion())
23 wx.EVT_CLOSE(self, self.OnClose)
25 self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.supportedExtensions()))
27 menubar = wx.MenuBar()
29 i = fileMenu.Append(-1, 'Load model file...\tCTRL+L')
30 self.Bind(wx.EVT_MENU, self.OnLoadModel, i)
31 i = fileMenu.Append(-1, 'Prepare print...\tCTRL+R')
32 self.Bind(wx.EVT_MENU, self.OnSlice, i)
33 i = fileMenu.Append(-1, 'Print...\tCTRL+P')
34 self.Bind(wx.EVT_MENU, self.OnPrint, i)
35 fileMenu.AppendSeparator()
36 i = fileMenu.Append(-1, 'Preferences...\tCTRL+,')
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)
142 self.SetMinSize(self.GetSize())
146 def OnPreferences(self, e):
147 prefDialog = preferencesDialog.preferencesDialog(self)
149 prefDialog.Show(True)
151 def OnLoadModel(self, e):
152 dlg=wx.FileDialog(self, "Open file to print", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
153 dlg.SetWildcard(meshLoader.wildcardFilter())
154 if dlg.ShowModal() == wx.ID_OK:
155 self.filelist = [dlg.GetPath()]
156 profile.putPreference('lastFile', ';'.join(self.filelist))
157 self.preview3d.loadModelFiles(self.filelist, True)
158 self.preview3d.setViewMode("Normal")
161 def OnDropFiles(self, filenames):
162 self.filelist = filenames
163 profile.putPreference('lastFile', ';'.join(self.filelist))
164 self.preview3d.loadModelFiles(self.filelist, True)
165 self.preview3d.setViewMode("Normal")
167 def OnSlice(self, e):
168 if len(self.filelist) < 1:
169 wx.MessageBox('You need to load a file before you can prepare it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
171 #save the current profile so we can put it back latter
172 oldProfile = profile.getGlobalProfileString()
174 put = profile.putProfileSetting
175 get = profile.getProfileSetting
177 put('layer_height', '0.2')
178 put('wall_thickness', '0.8')
179 put('solid_layer_thickness', '0.6')
180 put('fill_density', '20')
181 put('skirt_line_count', '1')
182 put('skirt_gap', '6.0')
183 put('print_speed', '50')
184 put('print_temperature', '220')
185 put('support', 'None')
186 put('retraction_enable', 'False')
187 put('retraction_min_travel', '5.0')
188 put('retraction_speed', '40.0')
189 put('retraction_amount', '4.5')
190 put('retraction_extra', '0.0')
191 put('travel_speed', '150')
192 put('max_z_speed', '3.0')
193 put('bottom_layer_speed', '25')
194 put('cool_min_layer_time', '10')
195 put('fan_enabled', 'True')
196 put('fan_layer', '1')
197 put('fan_speed', '100')
198 #put('model_scale', '1.0')
199 #put('flip_x', 'False')
200 #put('flip_y', 'False')
201 #put('flip_z', 'False')
202 #put('model_rotate_base', '0')
203 #put('model_multiply_x', '1')
204 #put('model_multiply_y', '1')
205 put('extra_base_wall_thickness', '0.0')
206 put('sequence', 'Loops > Perimeter > Infill')
207 put('force_first_layer_sequence', 'True')
208 put('infill_type', 'Line')
209 put('solid_top', 'True')
210 put('fill_overlap', '15')
211 put('support_rate', '50')
212 put('support_distance', '0.5')
213 put('joris', 'False')
214 put('cool_min_feedrate', '5')
215 put('bridge_speed', '100')
216 put('raft_margin', '5')
217 put('raft_base_material_amount', '100')
218 put('raft_interface_material_amount', '100')
219 put('bottom_thickness', '0.0')
221 if self.printSupport.GetValue():
222 put('support', 'Exterior Only')
224 nozzle_size = float(get('nozzle_size'))
225 if self.printTypeNormal.GetValue():
226 put('wall_thickness', nozzle_size * 2.0)
227 put('layer_height', '0.2')
228 put('fill_density', '20')
229 elif self.printTypeLow.GetValue():
230 put('wall_thickness', nozzle_size * 1.4)
231 put('layer_height', '0.25')
232 put('fill_density', '10')
233 put('print_speed', '80')
234 put('cool_min_layer_time', '3')
235 put('bottom_layer_speed', '40')
236 elif self.printTypeHigh.GetValue():
237 put('wall_thickness', nozzle_size * 2.0)
238 put('layer_height', '0.1')
239 put('fill_density', '30')
240 put('bottom_layer_speed', '15')
241 put('bottom_thickness', '0.2')
242 elif self.printTypeJoris.GetValue():
243 put('wall_thickness', nozzle_size * 1.5)
244 put('layer_height', '0.3')
245 put('solid_layer_thickness', '0.9')
246 put('fill_density', '0')
248 put('extra_base_wall_thickness', '15.0')
249 put('sequence', 'Infill > Loops > Perimeter')
250 put('force_first_layer_sequence', 'False')
251 put('solid_top', 'False')
252 put('support', 'None')
253 put('cool_min_layer_time', '3')
255 put('filament_diameter', self.printMaterialDiameter.GetValue())
256 if self.printMaterialPLA.GetValue():
257 put('filament_density', '1.00')
258 put('enable_raft', 'False')
259 put('skirt_line_count', '1')
260 if self.printMaterialABS.GetValue():
261 put('filament_density', '0.85')
262 put('enable_raft', 'True')
263 put('skirt_line_count', '0')
264 put('fan_layer', '1')
265 put('bottom_thickness', '0.0')
266 put('print_temperature', '260')
268 #Create a progress panel and add it to the window. The progress panel will start the Skein operation.
269 spp = sliceProgessPanel.sliceProgessPanel(self, self, self.filelist)
270 self.sizer.Add(spp, (len(self.progressPanelList)+2,0), span=(1,4), flag=wx.EXPAND)
272 newSize = self.GetSize();
273 newSize.IncBy(0, spp.GetSize().GetHeight())
274 if newSize.GetWidth() < wx.GetDisplaySize()[0]:
275 self.SetSize(newSize)
276 self.progressPanelList.append(spp)
278 #Restore the old profile.
279 profile.loadGlobalProfileFromString(oldProfile)
281 def OnPrint(self, e):
282 if len(self.filelist) < 1:
283 wx.MessageBox('You need to load a file and prepare it before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
285 if not os.path.exists(sliceRun.getExportFilename(self.filelist[0])):
286 wx.MessageBox('You need to prepare the file before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
288 printWindow.printFile(sliceRun.getExportFilename(self.filelist[0]))
290 def OnNormalSwitch(self, e):
291 from gui import mainWindow
292 profile.putPreference('startMode', 'Normal')
293 mainWindow.mainWindow()
296 def removeSliceProgress(self, spp):
297 self.progressPanelList.remove(spp)
298 newSize = self.GetSize();
299 newSize.IncBy(0, -spp.GetSize().GetHeight())
300 if newSize.GetWidth() < wx.GetDisplaySize()[0]:
301 self.SetSize(newSize)
303 self.sizer.Detach(spp)
304 for spp in self.progressPanelList:
305 self.sizer.Detach(spp)
307 for spp in self.progressPanelList:
308 self.sizer.Add(spp, (i,0), span=(1,4), flag=wx.EXPAND)
315 def OnClose(self, e):
318 def updateProfileToControls(self):
319 super(simpleModeWindow, self).updateProfileToControls()
320 self.preview3d.updateProfileToControls()