chiark / gitweb /
Add shortcut keys for load/slice/print.
[cura.git] / Cura / gui / simpleMode.py
1 from __future__ import absolute_import
2 import __init__
3
4 import wx, os, platform, types, webbrowser
5
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
14 from gui import icon
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
20
21 class simpleModeWindow(configBase.configWindowBase):
22         "Main user interface window for Quickprint mode"
23         def __init__(self):
24                 super(simpleModeWindow, self).__init__(title='Cura - Quickprint - ' + version.getVersion())
25                 
26                 wx.EVT_CLOSE(self, self.OnClose)
27                 #self.SetIcon(icon.getMainIcon())
28
29                 self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.supportedExtensions()))
30                 
31                 menubar = wx.MenuBar()
32                 fileMenu = wx.Menu()
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')
42                 
43                 toolsMenu = wx.Menu()
44                 i = toolsMenu.Append(-1, 'Switch to Normal mode...')
45                 self.Bind(wx.EVT_MENU, self.OnNormalSwitch, i)
46                 menubar.Append(toolsMenu, 'Normal mode')
47                 
48                 helpMenu = wx.Menu()
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)
55                 
56                 if profile.getPreference('lastFile') != '':
57                         self.filelist = profile.getPreference('lastFile').split(';')
58                         self.SetTitle('Cura - %s - %s' % (version.getVersion(), self.filelist[-1]))
59                 else:
60                         self.filelist = []
61                 self.progressPanelList = []
62
63                 #Preview window
64                 self.preview3d = preview3d.previewPanel(self)
65
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')
72
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'))
77                 
78                 self.printSupport = wx.CheckBox(configPanel, -1, 'Print support structure')
79                 
80                 sizer = wx.GridBagSizer()
81                 configPanel.SetSizer(sizer)
82
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)
92
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)
102
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)
107
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)
117
118                 #Main sizer, to position the preview window, buttons and tab control
119                 sizer = wx.GridBagSizer()
120                 self.SetSizer(sizer)
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)
128                 self.sizer = sizer
129
130                 if len(self.filelist) > 0:
131                         self.preview3d.loadModelFiles(self.filelist)
132
133                 self.SetBackgroundColour(configPanel.GetBackgroundColour())
134
135                 self.updateProfileToControls()
136
137                 self.printTypeNormal.SetValue(True)
138                 self.printMaterialPLA.SetValue(True)
139
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())
143                                                                                                          ]))
144
145                 self.Fit()
146                 self.preview3d.Fit()
147                 self.SetMinSize(self.GetSize())
148                 self.Centre()
149                 self.Show(True)
150         
151         def OnPreferences(self, e):
152                 prefDialog = preferencesDialog.preferencesDialog(self)
153                 prefDialog.Centre()
154                 prefDialog.Show(True)
155
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")
164                 dlg.Destroy()
165
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")
171         
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)
175                         return
176                 #save the current profile so we can put it back latter
177                 oldProfile = profile.getGlobalProfileString()
178                 
179                 put = profile.putProfileSetting
180                 get = profile.getProfileSetting
181
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')
227
228                 if self.printSupport.GetValue():
229                         put('support', 'Exterior Only')
230
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')
254                         put('joris', 'True')
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')
261
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')
274                 
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)
278                 self.sizer.Layout()
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)
284                 
285                 #Restore the old profile.
286                 profile.loadGlobalProfileFromString(oldProfile)
287         
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)
291                         return
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)
294                         return
295                 printWindow.printFile(sliceRun.getExportFilename(self.filelist[0]))
296
297         def OnNormalSwitch(self, e):
298                 from gui import mainWindow
299                 profile.putPreference('startMode', 'Normal')
300                 mainWindow.mainWindow()
301                 self.Close()
302
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)
309                 spp.Show(False)
310                 self.sizer.Detach(spp)
311                 for spp in self.progressPanelList:
312                         self.sizer.Detach(spp)
313                 i = 2
314                 for spp in self.progressPanelList:
315                         self.sizer.Add(spp, (i,0), span=(1,4), flag=wx.EXPAND)
316                         i += 1
317                 self.sizer.Layout()
318
319         def OnQuit(self, e):
320                 self.Close()
321         
322         def OnClose(self, e):
323                 self.Destroy()
324
325         def updateProfileToControls(self):
326                 super(simpleModeWindow, self).updateProfileToControls()
327                 self.preview3d.updateProfileToControls()
328