chiark / gitweb /
Fix the bug where you can not select a material and a profile with MacOS 10.8
[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(self.filelist[-1] + ' - Cura - ' + version.getVersion())
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, 'Prepare 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.Fit()
141                 self.preview3d.Fit()
142                 self.SetMinSize(self.GetSize())
143                 self.Centre()
144                 self.Show(True)
145         
146         def OnPreferences(self, e):
147                 prefDialog = preferencesDialog.preferencesDialog(self)
148                 prefDialog.Centre()
149                 prefDialog.Show(True)
150
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")
159                 dlg.Destroy()
160
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")
166         
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)
170                         return
171                 #save the current profile so we can put it back latter
172                 oldProfile = profile.getGlobalProfileString()
173                 
174                 put = profile.putProfileSetting
175                 get = profile.getProfileSetting
176
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('machine_center_x', '100')
187                 #put('machine_center_y', '100')
188                 put('retraction_enable', 'False')
189                 put('retraction_min_travel', '5.0')
190                 put('retraction_speed', '40.0')
191                 put('retraction_amount', '4.5')
192                 put('retraction_extra', '0.0')
193                 put('travel_speed', '150')
194                 put('max_z_speed', '3.0')
195                 put('bottom_layer_speed', '25')
196                 put('cool_min_layer_time', '10')
197                 put('fan_enabled', 'True')
198                 put('fan_layer', '1')
199                 put('fan_speed', '100')
200                 #put('model_scale', '1.0')
201                 #put('flip_x', 'False')
202                 #put('flip_y', 'False')
203                 #put('flip_z', 'False')
204                 #put('model_rotate_base', '0')
205                 #put('model_multiply_x', '1')
206                 #put('model_multiply_y', '1')
207                 put('extra_base_wall_thickness', '0.0')
208                 put('sequence', 'Loops > Perimeter > Infill')
209                 put('force_first_layer_sequence', 'True')
210                 put('infill_type', 'Line')
211                 put('solid_top', 'True')
212                 put('fill_overlap', '15')
213                 put('support_rate', '50')
214                 put('support_distance', '0.5')
215                 put('joris', 'False')
216                 put('cool_min_feedrate', '5')
217                 put('bridge_speed', '100')
218                 put('raft_margin', '5')
219                 put('raft_base_material_amount', '100')
220                 put('raft_interface_material_amount', '100')
221                 put('bottom_thickness', '0.0')
222
223                 if self.printSupport.GetValue():
224                         put('support', 'Exterior Only')
225
226                 nozzle_size = float(get('nozzle_size'))
227                 if self.printTypeNormal.GetValue():
228                         put('wall_thickness', nozzle_size * 2.0)
229                         put('layer_height', '0.2')
230                         put('fill_density', '20')
231                 elif self.printTypeLow.GetValue():
232                         put('wall_thickness', nozzle_size * 1.4)
233                         put('layer_height', '0.25')
234                         put('fill_density', '10')
235                         put('print_speed', '80')
236                         put('cool_min_layer_time', '3')
237                         put('bottom_layer_speed', '40')
238                 elif self.printTypeHigh.GetValue():
239                         put('wall_thickness', nozzle_size * 2.0)
240                         put('layer_height', '0.1')
241                         put('fill_density', '30')
242                         put('bottom_layer_speed', '15')
243                         put('bottom_thickness', '0.2')
244                 elif self.printTypeJoris.GetValue():
245                         put('wall_thickness', nozzle_size * 1.5)
246                         put('layer_height', '0.3')
247                         put('solid_layer_thickness', '0.9')
248                         put('fill_density', '0')
249                         put('joris', 'True')
250                         put('extra_base_wall_thickness', '15.0')
251                         put('sequence', 'Infill > Loops > Perimeter')
252                         put('force_first_layer_sequence', 'False')
253                         put('solid_top', 'False')
254                         put('support', 'None')
255                         put('cool_min_layer_time', '3')
256
257                 put('filament_diameter', self.printMaterialDiameter.GetValue())
258                 if self.printMaterialPLA.GetValue():
259                         put('filament_density', '1.00')
260                         put('enable_raft', 'False')
261                         put('skirt_line_count', '1')
262                 if self.printMaterialABS.GetValue():
263                         put('filament_density', '0.85')
264                         put('enable_raft', 'True')
265                         put('skirt_line_count', '0')
266                         put('fan_layer', '1')
267                         put('bottom_thickness', '0.0')
268                         put('print_temperature', '260')
269                 
270                 #Create a progress panel and add it to the window. The progress panel will start the Skein operation.
271                 spp = sliceProgessPanel.sliceProgessPanel(self, self, self.filelist)
272                 self.sizer.Add(spp, (len(self.progressPanelList)+2,0), span=(1,4), flag=wx.EXPAND)
273                 self.sizer.Layout()
274                 newSize = self.GetSize();
275                 newSize.IncBy(0, spp.GetSize().GetHeight())
276                 self.SetSize(newSize)
277                 self.progressPanelList.append(spp)
278                 
279                 #Restore the old profile.
280                 profile.loadGlobalProfileFromString(oldProfile)
281         
282         def OnPrint(self, e):
283                 if len(self.filelist) < 1:
284                         wx.MessageBox('You need to load a file and prepare it before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
285                         return
286                 if not os.path.exists(sliceRun.getExportFilename(self.filelist[0])):
287                         wx.MessageBox('You need to prepare the file before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
288                         return
289                 printWindow.printFile(sliceRun.getExportFilename(self.filelist[0]))
290
291         def OnNormalSwitch(self, e):
292                 from gui import mainWindow
293                 profile.putPreference('startMode', 'Normal')
294                 mainWindow.mainWindow()
295                 self.Close()
296
297         def removeSliceProgress(self, spp):
298                 self.progressPanelList.remove(spp)
299                 newSize = self.GetSize();
300                 newSize.IncBy(0, -spp.GetSize().GetHeight())
301                 self.SetSize(newSize)
302                 self.sizer.Remove(spp)
303                 spp.Destroy()
304                 for spp in self.progressPanelList:
305                         self.sizer.Remove(spp)
306                 i = 2
307                 for spp in self.progressPanelList:
308                         self.sizer.Add(spp, (i,0), span=(1,4), flag=wx.EXPAND)
309                         i += 1
310                 self.sizer.Layout()
311
312         def OnQuit(self, e):
313                 self.Close()
314         
315         def OnClose(self, e):
316                 self.Destroy()
317
318         def updateProfileToControls(self):
319                 super(simpleModeWindow, self).updateProfileToControls()
320                 self.preview3d.updateProfileToControls()
321