74
68
#-----------------------------------------------------------------------------#
76
class LaunchWindow(eclib.ControlBox):
70
class LaunchWindow(ed_basewin.EdBaseCtrlBox):
77
71
"""Control window for showing and running scripts"""
78
72
def __init__(self, parent):
79
eclib.ControlBox.__init__(self, parent)
73
super(LaunchWindow, self).__init__(parent)
82
76
self._log = wx.GetApp().GetLog()
83
self._mw = self.__FindMainWindow()
77
self._mw = ed_basewin.FindMainWindow(self)
84
78
self._buffer = OutputDisplay(self)
85
79
self._fnames = list()
86
self._chFiles = None # Created in __DoLayout
80
self._run = None # Created in __DoLayout
81
self._pbtn = None # Created in __DoLayout
82
self._clear = None # Created in __DoLayout
83
self._lockFile = None # Created in __DoLayout
84
self._chFiles = None # Created in __DoLayout
87
85
self._worker = None
89
87
self._isready = False
90
self._config = dict(file='', lang=0,
95
self._prefs = Profile_Get(cfgdlg.LAUNCH_PREFS, default=None)
88
self._state = dict(file='', lang=0, cfile='', clang=0, last='',
89
lastlang=0, prelang=0, largs='', lcmd='')
99
93
if not handlers.InitCustomHandlers(ed_glob.CONFIG['CACHE_DIR']):
100
94
util.Log(u"[launch][warn] failed to load launch extensions")
102
hstate = Profile_Get(LAUNCH_KEY)
103
if hstate is not None:
104
handlers.SetState(hstate)
105
if self._prefs is None:
106
Profile_Set(cfgdlg.LAUNCH_PREFS,
107
dict(autoclear=False,
109
defaultf=self._buffer.GetDefaultForeground().Get(),
110
defaultb=self._buffer.GetDefaultBackground().Get(),
111
errorf=self._buffer.GetErrorForeground().Get(),
112
errorb=self._buffer.GetErrorBackground().Get(),
113
infof=self._buffer.GetInfoForeground().Get(),
114
infob=self._buffer.GetInfoBackground().Get(),
115
warnf=self._buffer.GetWarningForeground().Get(),
116
warnb=self._buffer.GetWarningBackground().Get()))
117
self._prefs = Profile_Get(cfgdlg.LAUNCH_PREFS)
96
# Ensure preferences have been initialized
119
self._buffer.SetPrefs(self._prefs)
120
99
self.UpdateBufferColors()
121
cbuffer = self._mw.GetNotebook().GetCurrentCtrl()
100
cbuffer = GetTextBuffer(self.MainWindow)
122
101
self.SetupControlBar(cbuffer)
123
self._config['lang'] = GetLangIdFromMW(self._mw)
124
self.UpdateCurrentFiles(self._config['lang'])
125
self.SetFile(GetTextBuffer(self._mw).GetFileName())
102
self.State['lang'] = GetLangIdFromMW(self.MainWindow)
103
self.UpdateCurrentFiles(self.State['lang'])
104
self.SetFile(cbuffer.GetFileName())
127
106
# Setup filetype settings
128
107
self.RefreshControlBar()
131
110
self.Bind(wx.EVT_BUTTON, self.OnButton)
132
111
self.Bind(wx.EVT_CHOICE, self.OnChoice)
112
self.Bind(wx.EVT_CHECKBOX, self.OnCheck)
113
self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)
133
114
ed_msg.Subscribe(self.OnPageChanged, ed_msg.EDMSG_UI_NB_CHANGED)
134
115
ed_msg.Subscribe(self.OnFileOpened, ed_msg.EDMSG_FILE_OPENED)
135
116
ed_msg.Subscribe(self.OnThemeChanged, ed_msg.EDMSG_THEME_CHANGED)
136
117
ed_msg.Subscribe(self.OnLexerChange, ed_msg.EDMSG_UI_STC_LEXER)
137
ed_msg.Subscribe(self.OnConfigExit, cfgdlg.EDMSG_LAUNCH_CFG_EXIT)
118
ed_msg.Subscribe(self.OnConfigChange,
119
ed_msg.EDMSG_PROFILE_CHANGE + (handlers.CONFIG_KEY,))
138
120
ed_msg.Subscribe(self.OnRunMsg, MSG_RUN_LAUNCH)
139
121
ed_msg.Subscribe(self.OnRunLastMsg, MSG_RUN_LAST)
140
122
ed_msg.RegisterCallback(self._CanLaunch, REQUEST_ACTIVE)
141
123
ed_msg.RegisterCallback(self._CanReLaunch, REQUEST_RELAUNCH)
144
ed_msg.Unsubscribe(self.OnPageChanged)
145
ed_msg.Unsubscribe(self.OnFileOpened)
146
ed_msg.Unsubscribe(self.OnThemeChanged)
147
ed_msg.Unsubscribe(self.OnLexerChange)
148
ed_msg.Unsubscribe(self.OnConfigExit)
149
ed_msg.Unsubscribe(self.OnRunMsg)
150
ed_msg.Unsubscribe(self.OnRunLastMsg)
151
ed_msg.UnRegisterCallback(self._CanLaunch)
152
ed_msg.UnRegisterCallback(self._CanReLaunch)
153
super(LaunchWindow, self).__del__()
125
#---- Properties ----#
126
Locked = property(lambda self: self._lockFile.IsChecked())
127
MainWindow = property(lambda self: self._mw)
128
Preferences = property(lambda self: Profile_Get(handlers.CONFIG_KEY, default=None),
129
lambda self, prefs: Profile_Set(handlers.CONFIG_KEY, prefs))
130
State = property(lambda self: self._state)
132
def OnDestroy(self, evt):
134
ed_msg.Unsubscribe(self.OnPageChanged)
135
ed_msg.Unsubscribe(self.OnFileOpened)
136
ed_msg.Unsubscribe(self.OnThemeChanged)
137
ed_msg.Unsubscribe(self.OnLexerChange)
138
ed_msg.Unsubscribe(self.OnConfigChange)
139
ed_msg.Unsubscribe(self.OnRunMsg)
140
ed_msg.Unsubscribe(self.OnRunLastMsg)
141
ed_msg.UnRegisterCallback(self._CanLaunch)
142
ed_msg.UnRegisterCallback(self._CanReLaunch)
155
144
def __DoLayout(self):
156
145
"""Layout the window"""
157
#-- Setup ControlBar --#
158
ctrlbar = eclib.ControlBar(self, style=eclib.CTRLBAR_STYLE_GRADIENT)
159
if wx.Platform == '__WXGTK__':
160
ctrlbar.SetWindowStyle(eclib.CTRLBAR_STYLE_DEFAULT)
146
ctrlbar = self.CreateControlBar(wx.TOP)
163
prefbmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_PREF), wx.ART_MENU)
164
pref = eclib.PlateButton(ctrlbar, ID_SETTINGS, '', prefbmp,
165
style=eclib.PB_STYLE_NOBG)
166
pref.SetToolTipString(_("Settings"))
167
ctrlbar.AddControl(pref, wx.ALIGN_LEFT)
149
self._pbtn = self.AddPlateButton(u"", ed_glob.ID_PREF)
150
self._pbtn.SetToolTipString(_("Settings"))
170
153
ctrlbar.AddControl(wx.StaticText(ctrlbar, label=_("exec") + ":"),
182
168
ctrlbar.AddControl((5, 5), wx.ALIGN_LEFT)
183
169
ctrlbar.AddControl(wx.StaticText(ctrlbar, label=_("args") + ":"),
185
args = wx.TextCtrl(ctrlbar, ID_ARGS)
186
args.SetToolTipString(_("Script Arguments"))
187
ctrlbar.AddControl(args, wx.ALIGN_LEFT)
171
args = wx.TextCtrl(ctrlbar, ID_ARGS, size=(100,-1))
172
args.SetToolTipString(_("Arguments"))
173
ctrlbar.AddControl(args, wx.ALIGN_LEFT, 1)
190
176
ctrlbar.AddStretchSpacer()
193
rbmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_BIN_FILE), wx.ART_MENU)
194
if rbmp.IsNull() or not rbmp.IsOk():
196
run = eclib.PlateButton(ctrlbar, ID_RUN, _("Run"), rbmp,
197
style=eclib.PB_STYLE_NOBG)
198
ctrlbar.AddControl(run, wx.ALIGN_RIGHT)
201
cbmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_DELETE), wx.ART_MENU)
202
if cbmp.IsNull() or not cbmp.IsOk():
204
clear = eclib.PlateButton(ctrlbar, wx.ID_CLEAR, _("Clear"),
205
cbmp, style=eclib.PB_STYLE_NOBG)
206
ctrlbar.AddControl(clear, wx.ALIGN_RIGHT)
207
ctrlbar.SetVMargin(1, 1)
208
self.SetControlBar(ctrlbar)
179
self._run = self.AddPlateButton(_("Run"), ed_glob.ID_BIN_FILE,
181
self._clear = self.AddPlateButton(_("Clear"), ed_glob.ID_DELETE,
210
183
self.SetWindow(self._buffer)
212
def __FindMainWindow(self):
213
"""Find the mainwindow of this control
214
@return: MainWindow or None
218
"""Check if the given window is a main window"""
219
return getattr(tlw, '__name__', '') == 'MainWindow'
221
tlw = self.GetTopLevelParent()
224
elif hasattr(tlw, 'GetParent'):
225
tlw = tlw.GetParent()
231
185
def _CanLaunch(self):
232
186
"""Method to use with RegisterCallback for getting status"""
233
187
val = self.CanLaunch()
250
parent = self.GetParent()
251
return parent.GetParent().IsActive() and self._isready
204
return self.TopLevelParent.IsActive() and self._isready
253
206
def GetFile(self):
254
207
"""Get the file that is currently set to be run
255
208
@return: file path
258
return self._config['file']
211
return self.State['file']
260
213
def GetLastRun(self):
261
214
"""Get the last file that was run
262
215
@return: (fname, lang_id)
265
return (self._config['last'], self._config['lastlang'])
267
def GetMainWindow(self):
268
"""Get the mainwindow that created this instance
269
@return: reference to MainWindow
218
return (self.State['last'], self.State['lastlang'])
274
220
def OnButton(self, evt):
275
221
"""Handle events from the buttons on the control bar"""
277
if e_id == ID_SETTINGS:
222
e_obj = evt.GetEventObject()
223
if e_obj == self._pbtn:
278
224
app = wx.GetApp()
279
225
win = app.GetWindowInstance(cfgdlg.ConfigDialog)
281
config = cfgdlg.ConfigDialog(self._mw)
227
config = cfgdlg.ConfigDialog(self.MainWindow)
282
228
config.CentreOnParent()
232
elif e_obj is self._run:
287
233
# May be run or abort depending on current state
288
234
self.StartStopProcess()
289
elif e_id == wx.ID_CLEAR:
235
elif e_obj == self._clear:
290
236
self._buffer.Clear()
304
250
self._chFiles.SetToolTipString(fname)
305
251
elif e_id == ID_EXECUTABLE:
306
252
e_obj = evt.GetEventObject()
307
handler = handlers.GetHandlerById(self._config['lang'])
253
handler = handlers.GetHandlerById(self.State['lang'])
308
254
cmd = e_obj.GetStringSelection()
309
255
e_obj.SetToolTipString(handler.GetCommand(cmd))
313
def OnConfigExit(self, msg):
314
"""Update current state when the config dialog has been closed
259
def OnCheck(self, evt):
260
"""CheckBox for Lock File was clicked"""
261
e_obj = evt.GetEventObject()
262
if e_obj is self._lockFile:
264
self._chFiles.Disable()
266
self._chFiles.Enable()
267
cbuff = GetTextBuffer(self.MainWindow)
268
if isinstance(cbuff, ed_basestc.EditraBaseStc):
269
self.UpdateCurrentFiles(cbuff.GetLangId())
270
self.SetupControlBar(cbuff)
274
def OnConfigChange(self, msg):
275
"""Update current state when the configuration has been changed
315
276
@param msg: Message Object
318
279
util.Log("[Launch][info] Saving config to profile")
319
280
self.RefreshControlBar()
320
Profile_Set(LAUNCH_KEY, handlers.GetState())
281
self._buffer.UpdateWrapMode()
321
282
self.UpdateBufferColors()
323
284
@ed_msg.mwcontext
356
323
# Update regardless of whether lexer has changed or not as the buffer
357
324
# may have the lexer set before the file was saved to disk.
359
#if ftype != self._config['lang']:
360
326
self.UpdateCurrentFiles(ftype)
361
327
self.SetControlBarState(fname, ftype)
363
330
def OnPageChanged(self, msg):
364
331
"""Update the status of the currently associated file
365
332
when the page changes in the main notebook.
366
333
@param msg: Message object
369
# Only update when in the active window
370
if not self._mw.IsActive():
336
# The current mode is locked
373
340
mval = msg.GetData()
374
341
ctrl = mval[0].GetCurrentCtrl()
375
self.UpdateCurrentFiles(ctrl.GetLangId())
376
if hasattr(ctrl, 'GetFileName'):
342
if isinstance(ctrl, ed_basestc.EditraBaseStc):
343
self.UpdateCurrentFiles(ctrl.GetLangId())
377
344
self.SetupControlBar(ctrl)
346
self._log("[launch][info] Non STC object in notebook")
347
return # Doesn't implement EdStc interface
379
349
def OnRunMsg(self, msg):
380
350
"""Run or abort a launch process if this is the current
398
368
if not len(fname):
401
shelf = self._mw.GetShelf()
371
shelf = self.MainWindow.GetShelf()
402
372
self.UpdateCurrentFiles(ftype)
403
373
self.SetFile(fname)
404
374
self.RefreshControlBar()
405
375
shelf.RaiseWindow(self)
407
if self._prefs.get('autoclear'):
377
if self.Preferences.get('autoclear'):
408
378
self._buffer.Clear()
410
380
self.SetProcessRunning(True)
412
self.Run(fname, self._config['lcmd'], self._config['largs'], ftype)
382
self.Run(fname, self.State['lcmd'], self.State['largs'], ftype)
414
384
def OnThemeChanged(self, msg):
415
385
"""Update icons when the theme has been changed
416
386
@param msg: Message Object
419
ctrls = ((ID_SETTINGS, ed_glob.ID_PREF),
420
(wx.ID_CLEAR, ed_glob.ID_DELETE))
389
ctrls = ((self._pbtn, ed_glob.ID_PREF),
390
(self._clear, ed_glob.ID_DELETE))
422
ctrls += ((ID_RUN, ed_glob.ID_STOP),)
392
ctrls += ((self._run, ed_glob.ID_STOP),)
424
ctrls += ((ID_RUN, ed_glob.ID_BIN_FILE),)
394
ctrls += ((self._run, ed_glob.ID_BIN_FILE),)
426
for ctrl, art in ctrls:
427
btn = self.FindWindowById(ctrl)
396
for btn, art in ctrls:
428
397
bmp = wx.ArtProvider.GetBitmap(str(art), wx.ART_MENU)
429
398
btn.SetBitmap(bmp)
400
self.GetControlBar().Refresh()
432
402
def RefreshControlBar(self):
433
403
"""Refresh the state of the control bar based on the current config"""
434
handler = handlers.GetHandlerById(self._config['lang'])
404
handler = handlers.GetHandlerById(self.State['lang'])
435
405
cmds = handler.GetAliases()
437
407
# Get the controls
438
408
exe_ch = self.FindWindowById(ID_EXECUTABLE)
439
409
args_txt = self.FindWindowById(ID_ARGS)
440
run_btn = self.FindWindowById(ID_RUN)
443
411
csel = exe_ch.GetStringSelection()
444
412
exe_ch.SetItems(cmds)
446
415
exe_ch.SetToolTipString(handler.GetCommand(cmds[0]))
448
util.Log("[Launch][info] Found commands %s" % str(cmds))
449
if handler.GetName() != handlers.DEFAULT_HANDLER and len(self.GetFile()):
450
for ctrl in (exe_ch, args_txt, run_btn, self._chFiles):
417
util.Log("[Launch][info] Found commands %s" % repr(cmds))
418
if handler.GetName() != handlers.DEFAULT_HANDLER and \
419
ncmds > 0 and len(self.GetFile()):
420
for ctrl in (exe_ch, args_txt, self._run,
421
self._chFiles, self._lockFile):
452
424
self._isready = True
426
self._chFiles.Enable(False)
454
if self._config['lang'] == self._config['prelang'] and len(csel):
428
if self.State['lang'] == self.State['prelang'] and len(csel):
455
429
exe_ch.SetStringSelection(csel)
457
431
csel = handler.GetDefault()
498
472
def StartStopProcess(self):
499
473
"""Run or abort the context of the current process if possible"""
500
if self._prefs.get('autoclear'):
474
if self.Preferences.get('autoclear', False):
501
475
self._buffer.Clear()
477
# Check Auto-save preferences
479
if self.Preferences.get('autosaveall', False):
480
self.MainWindow.SaveAllBuffers()
481
elif self.Preferences.get('autosave', False):
482
self.MainWindow.SaveCurrentBuffer()
484
# Start or stop the process
503
485
self.SetProcessRunning(not self._busy)
505
487
util.Log("[Launch][info] Starting process")
506
handler = handlers.GetHandlerById(self._config['lang'])
488
handler = handlers.GetHandlerById(self.State['lang'])
507
489
cmd = self.FindWindowById(ID_EXECUTABLE).GetStringSelection()
508
self._config['lcmd'] = cmd
490
self.State['lcmd'] = cmd
509
491
cmd = handler.GetCommand(cmd)
510
492
args = self.FindWindowById(ID_ARGS).GetValue().split()
511
self._config['largs'] = args
512
self.Run(self._config['file'], cmd, args, self._config['lang'])
493
self.State['largs'] = args
494
self.Run(self.State['file'], cmd, args, self.State['lang'])
514
496
util.Log("[Launch][info] Aborting process")
515
497
self._worker.Abort()
516
498
self._worker = None
539
521
@keyword running: Is a process running or not
542
rbtn = self.FindWindowById(ID_RUN)
543
524
self._busy = running
545
self._config['last'] = self._config['file']
546
self._config['lastlang'] = self._config['lang']
547
self._config['cfile'] = self._config['file']
548
self._config['clang'] = self._config['lang']
526
self.State['last'] = self.State['file']
527
self.State['lastlang'] = self.State['lang']
528
self.State['cfile'] = self.State['file']
529
self.State['clang'] = self.State['lang']
549
530
abort = wx.ArtProvider.GetBitmap(str(ed_glob.ID_STOP), wx.ART_MENU)
550
531
if abort.IsNull() or not abort.IsOk():
551
532
abort = wx.ArtProvider.GetBitmap(wx.ART_ERROR,
552
533
wx.ART_MENU, (16, 16))
553
rbtn.SetBitmap(abort)
554
rbtn.SetLabel(_("Abort"))
534
self._run.SetBitmap(abort)
535
self._run.SetLabel(_("Abort"))
556
537
rbmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_BIN_FILE), wx.ART_MENU)
557
538
if rbmp.IsNull() or not rbmp.IsOk():
560
rbtn.SetLabel(_("Run"))
540
self._run.SetBitmap(rbmp)
541
self._run.SetLabel(_("Run"))
561
542
# If the buffer was changed while this was running we should
562
543
# update to the new buffer now that it has stopped.
563
self.SetFile(self._config['cfile'])
564
self.SetLangId(self._config['clang'])
544
self.SetFile(self.State['cfile'])
545
self.SetLangId(self.State['clang'])
565
546
self.RefreshControlBar()
567
548
self.GetControlBar().Layout()
570
551
def SetupControlBar(self, ctrl):
571
552
"""Set the state of the controlbar based data found in the buffer
580
561
def SetControlBarState(self, fname, lang_id):
581
562
# Don't update the bars status if the buffer is busy
582
563
if self._buffer.IsRunning():
583
self._config['cfile'] = fname
584
self._config['clang'] = lang_id
564
self.State['cfile'] = fname
565
self.State['clang'] = lang_id
587
self.SetLangId(lang_id)
569
self.SetLangId(lang_id)
589
# Refresh the control bars view
590
self.RefreshControlBar()
571
# Refresh the control bars view
572
self.RefreshControlBar()
592
574
def UpdateBufferColors(self):
593
575
"""Update the buffers colors"""
595
577
for color in ('defaultf', 'defaultb', 'errorf', 'errorb',
596
578
'infof', 'infob', 'warnf', 'warnb'):
597
val = self._prefs.get(color, None)
579
val = self.Preferences.get(color, None)
598
580
if val is not None:
599
581
colors[color] = wx.Colour(*val)
637
619
eclib.ProcessBufferMixin.__init__(self)
640
self._mw = parent.GetMainWindow()
622
self._mw = parent.MainWindow
645
626
font = Profile_Get('FONT1', 'font', wx.Font(11, wx.FONTFAMILY_MODERN,
646
627
wx.FONTSTYLE_NORMAL,
647
628
wx.FONTWEIGHT_NORMAL))
648
629
self.SetFont(font)
630
self.UpdateWrapMode()
632
Preferences = property(lambda self: Profile_Get(handlers.CONFIG_KEY, default=dict()),
633
lambda self, prefs: Profile_Set(handlers.CONFIG_KEY, prefs))
650
635
def ApplyStyles(self, start, txt):
651
636
"""Apply any desired output formatting to the text in
704
690
def DoProcessExit(self, code=0):
705
691
"""Do all that is needed to be done after a process has exited"""
706
self.AppendUpdate(">>> %s: %d%s" % (_("Exit Code"), code, os.linesep))
692
# Peek in the queue to see the last line before the exit line
693
queue = self.GetUpdateQueue()
698
line = self.GetLine(self.GetLineCount() - 1)
699
if line.endswith('\n') or line.endswith('\r'):
701
final_line = u">>> %s: %d%s" % (_("Exit Code"), code, os.linesep)
702
# Add an extra line feed if necessary to make sure the final line
703
# is output on a new line.
705
final_line = os.linesep + final_line
706
self.AppendUpdate(final_line)
708
708
self.GetParent().SetProcessRunning(False)