chiark / gitweb /
Move some gui utility files into a seperate location so the code gets a bit more...
[cura.git] / Cura / gui / simpleMode.py
1 from __future__ import absolute_import
2
3 import wx
4 import os
5 import webbrowser
6
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
17
18 class simpleModeWindow(configBase.configWindowBase):
19         "Main user interface window for Quickprint mode"
20         def __init__(self):
21                 super(simpleModeWindow, self).__init__(title='Cura - Quickprint - ' + version.getVersion())
22                 
23                 wx.EVT_CLOSE(self, self.OnClose)
24
25                 self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.supportedExtensions()))
26                 
27                 menubar = wx.MenuBar()
28                 fileMenu = wx.Menu()
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')
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.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('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')
220
221                 if self.printSupport.GetValue():
222                         put('support', 'Exterior Only')
223
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')
247                         put('joris', 'True')
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')
254
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')
267                 
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)
271                 self.sizer.Layout()
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)
277                 
278                 #Restore the old profile.
279                 profile.loadGlobalProfileFromString(oldProfile)
280         
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)
284                         return
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)
287                         return
288                 printWindow.printFile(sliceRun.getExportFilename(self.filelist[0]))
289
290         def OnNormalSwitch(self, e):
291                 from gui import mainWindow
292                 profile.putPreference('startMode', 'Normal')
293                 mainWindow.mainWindow()
294                 self.Close()
295
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)
302                 spp.Show(False)
303                 self.sizer.Detach(spp)
304                 for spp in self.progressPanelList:
305                         self.sizer.Detach(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