chiark / gitweb /
Various fixes to improve button layout on MacOS.
[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                 self.printTypeNormal = wx.RadioButton(configPanel, -1, 'Normal quality print', style=wx.RB_GROUP)
68                 self.printTypeLow = wx.RadioButton(configPanel, -1, 'Fast low quality print')
69                 self.printTypeHigh = wx.RadioButton(configPanel, -1, 'High quality print')
70                 self.printTypeJoris = wx.RadioButton(configPanel, -1, 'Thin walled cup or vase')
71
72                 self.printMaterialPLA = wx.RadioButton(configPanel, -1, 'PLA', style=wx.RB_GROUP)
73                 self.printMaterialABS = wx.RadioButton(configPanel, -1, 'ABS')
74                 self.printMaterialDiameter = wx.TextCtrl(configPanel, -1, profile.getProfileSetting('filament_diameter'))
75                 
76                 self.printSupport = wx.CheckBox(configPanel, -1, 'Print support structure')
77                 
78                 sizer = wx.GridBagSizer()
79                 configPanel.SetSizer(sizer)
80
81                 sb = wx.StaticBox(configPanel, label="Select a print type:")
82                 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
83                 boxsizer.Add(self.printTypeNormal)
84                 boxsizer.Add(self.printTypeLow)
85                 boxsizer.Add(self.printTypeHigh)
86                 boxsizer.Add(self.printTypeJoris)
87                 sizer.Add(boxsizer, (0,0), flag=wx.EXPAND)
88
89                 sb = wx.StaticBox(configPanel, label="Material:")
90                 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
91                 boxsizer.Add(self.printMaterialPLA)
92                 boxsizer.Add(self.printMaterialABS)
93                 boxsizer.Add(wx.StaticText(configPanel, -1, 'Diameter:'))
94                 boxsizer.Add(self.printMaterialDiameter)
95                 sizer.Add(boxsizer, (1,0), flag=wx.EXPAND)
96
97                 sb = wx.StaticBox(configPanel, label="Other:")
98                 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
99                 boxsizer.Add(self.printSupport)
100                 sizer.Add(boxsizer, (2,0), flag=wx.EXPAND)
101
102                 # load and slice buttons.
103                 loadButton = wx.Button(self, -1, 'Load Model')
104                 sliceButton = wx.Button(self, -1, 'Prepare print')
105                 printButton = wx.Button(self, -1, 'Print')
106                 self.Bind(wx.EVT_BUTTON, self.OnLoadModel, loadButton)
107                 self.Bind(wx.EVT_BUTTON, self.OnSlice, sliceButton)
108                 self.Bind(wx.EVT_BUTTON, self.OnPrint, printButton)
109                 #Also bind double clicking the 3D preview to load an STL file.
110                 self.preview3d.glCanvas.Bind(wx.EVT_LEFT_DCLICK, self.OnLoadModel, self.preview3d.glCanvas)
111
112                 #Main sizer, to position the preview window, buttons and tab control
113                 sizer = wx.GridBagSizer()
114                 self.SetSizer(sizer)
115                 sizer.Add(configPanel, (0,0), span=(1,1), flag=wx.EXPAND)
116                 sizer.Add(self.preview3d, (0,1), span=(1,3), flag=wx.EXPAND)
117                 sizer.AddGrowableCol(2)
118                 sizer.AddGrowableRow(0)
119                 sizer.Add(loadButton, (1,1), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
120                 sizer.Add(sliceButton, (1,2), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
121                 sizer.Add(printButton, (1,3), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
122                 self.sizer = sizer
123
124                 if len(self.filelist) > 0:
125                         self.preview3d.loadModelFiles(self.filelist)
126
127                 self.updateProfileToControls()
128
129                 self.printTypeNormal.SetValue(True)
130                 self.printMaterialPLA.SetValue(True)
131
132                 self.Fit()
133                 self.SetMinSize(self.GetSize())
134                 self.Centre()
135                 self.Show(True)
136         
137         def OnPreferences(self, e):
138                 prefDialog = preferencesDialog.preferencesDialog(self)
139                 prefDialog.Centre()
140                 prefDialog.Show(True)
141
142         def OnLoadModel(self, e):
143                 dlg=wx.FileDialog(self, "Open file to print", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
144                 dlg.SetWildcard(meshLoader.wildcardFilter())
145                 if dlg.ShowModal() == wx.ID_OK:
146                         self.filelist = [dlg.GetPath()]
147                         profile.putPreference('lastFile', ';'.join(self.filelist))
148                         self.preview3d.loadModelFiles(self.filelist, True)
149                         self.preview3d.setViewMode("Normal")
150                 dlg.Destroy()
151
152         def OnDropFiles(self, filenames):
153                 self.filelist = filenames
154                 profile.putPreference('lastFile', ';'.join(self.filelist))
155                 self.preview3d.loadModelFiles(self.filelist, True)
156                 self.preview3d.setViewMode("Normal")
157         
158         def OnSlice(self, e):
159                 if len(self.filelist) < 1:
160                         wx.MessageBox('You need to load a file before you can prepare it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
161                         return
162                 #save the current profile so we can put it back latter
163                 oldProfile = profile.getGlobalProfileString()
164                 
165                 put = profile.putProfileSetting
166                 get = profile.getProfileSetting
167
168                 put('layer_height', '0.2')
169                 put('wall_thickness', '0.8')
170                 put('solid_layer_thickness', '0.6')
171                 put('fill_density', '20')
172                 put('skirt_line_count', '1')
173                 put('skirt_gap', '6.0')
174                 put('print_speed', '50')
175                 put('print_temperature', '220')
176                 put('support', 'None')
177                 #put('machine_center_x', '100')
178                 #put('machine_center_y', '100')
179                 put('retraction_enable', 'False')
180                 put('retraction_min_travel', '5.0')
181                 put('retraction_speed', '40.0')
182                 put('retraction_amount', '4.5')
183                 put('retraction_extra', '0.0')
184                 put('travel_speed', '150')
185                 put('max_z_speed', '3.0')
186                 put('bottom_layer_speed', '25')
187                 put('cool_min_layer_time', '10')
188                 put('fan_enabled', 'True')
189                 put('fan_layer', '1')
190                 put('fan_speed', '100')
191                 #put('model_scale', '1.0')
192                 #put('flip_x', 'False')
193                 #put('flip_y', 'False')
194                 #put('flip_z', 'False')
195                 #put('model_rotate_base', '0')
196                 #put('model_multiply_x', '1')
197                 #put('model_multiply_y', '1')
198                 put('extra_base_wall_thickness', '0.0')
199                 put('sequence', 'Loops > Perimeter > Infill')
200                 put('force_first_layer_sequence', 'True')
201                 put('infill_type', 'Line')
202                 put('solid_top', 'True')
203                 put('fill_overlap', '15')
204                 put('support_rate', '50')
205                 put('support_distance', '0.5')
206                 put('joris', 'False')
207                 put('cool_min_feedrate', '5')
208                 put('bridge_speed', '100')
209                 put('raft_margin', '5')
210                 put('raft_base_material_amount', '100')
211                 put('raft_interface_material_amount', '100')
212                 put('bottom_thickness', '0.0')
213
214                 if self.printSupport.GetValue():
215                         put('support', 'Exterior Only')
216
217                 nozzle_size = float(get('nozzle_size'))
218                 if self.printTypeNormal.GetValue():
219                         put('wall_thickness', nozzle_size * 2.0)
220                         put('layer_height', '0.2')
221                         put('fill_density', '20')
222                 elif self.printTypeLow.GetValue():
223                         put('wall_thickness', nozzle_size * 1.4)
224                         put('layer_height', '0.25')
225                         put('fill_density', '10')
226                         put('print_speed', '80')
227                         put('cool_min_layer_time', '3')
228                         put('bottom_layer_speed', '40')
229                 elif self.printTypeHigh.GetValue():
230                         put('wall_thickness', nozzle_size * 2.0)
231                         put('layer_height', '0.1')
232                         put('fill_density', '30')
233                         put('bottom_layer_speed', '15')
234                         put('bottom_thickness', '0.2')
235                 elif self.printTypeJoris.GetValue():
236                         put('wall_thickness', nozzle_size * 1.5)
237                         put('layer_height', '0.3')
238                         put('solid_layer_thickness', '0.9')
239                         put('fill_density', '0')
240                         put('joris', 'True')
241                         put('extra_base_wall_thickness', '15.0')
242                         put('sequence', 'Infill > Loops > Perimeter')
243                         put('force_first_layer_sequence', 'False')
244                         put('solid_top', 'False')
245                         put('support', 'None')
246                         put('cool_min_layer_time', '3')
247
248                 put('filament_diameter', self.printMaterialDiameter.GetValue())
249                 if self.printMaterialPLA.GetValue():
250                         put('filament_density', '1.00')
251                         put('enable_raft', 'False')
252                         put('skirt_line_count', '1')
253                 if self.printMaterialABS.GetValue():
254                         put('filament_density', '0.85')
255                         put('enable_raft', 'True')
256                         put('skirt_line_count', '0')
257                         put('fan_layer', '1')
258                         put('bottom_thickness', '0.0')
259                         put('print_temperature', '260')
260                 
261                 #Create a progress panel and add it to the window. The progress panel will start the Skein operation.
262                 spp = sliceProgessPanel.sliceProgessPanel(self, self, self.filelist)
263                 self.sizer.Add(spp, (len(self.progressPanelList)+2,0), span=(1,4), flag=wx.EXPAND)
264                 self.sizer.Layout()
265                 newSize = self.GetSize();
266                 newSize.IncBy(0, spp.GetSize().GetHeight())
267                 self.SetSize(newSize)
268                 self.progressPanelList.append(spp)
269                 
270                 #Restore the old profile.
271                 profile.loadGlobalProfileFromString(oldProfile)
272         
273         def OnPrint(self, e):
274                 if len(self.filelist) < 1:
275                         wx.MessageBox('You need to load a file and prepare it before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
276                         return
277                 if not os.path.exists(sliceRun.getExportFilename(self.filelist[0])):
278                         wx.MessageBox('You need to prepare the file before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
279                         return
280                 printWindow.printFile(sliceRun.getExportFilename(self.filelist[0]))
281
282         def OnNormalSwitch(self, e):
283                 from gui import mainWindow
284                 profile.putPreference('startMode', 'Normal')
285                 mainWindow.mainWindow()
286                 self.Close()
287
288         def removeSliceProgress(self, spp):
289                 self.progressPanelList.remove(spp)
290                 newSize = self.GetSize();
291                 newSize.IncBy(0, -spp.GetSize().GetHeight())
292                 self.SetSize(newSize)
293                 self.sizer.Remove(spp)
294                 spp.Destroy()
295                 for spp in self.progressPanelList:
296                         self.sizer.Remove(spp)
297                 i = 2
298                 for spp in self.progressPanelList:
299                         self.sizer.Add(spp, (i,0), span=(1,4), flag=wx.EXPAND)
300                         i += 1
301                 self.sizer.Layout()
302
303         def OnQuit(self, e):
304                 self.Close()
305         
306         def OnClose(self, e):
307                 self.Destroy()
308
309         def updateProfileToControls(self):
310                 super(simpleModeWindow, self).updateProfileToControls()
311                 self.preview3d.updateProfileToControls()
312