X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a47c63ba5155586616d0a5e4d92f446ed512f0cb..047c5f3e6d3afae0655200158fa5d2d913038007:/wxPython/wx/py/shell.py diff --git a/wxPython/wx/py/shell.py b/wxPython/wx/py/shell.py index 2232fd59b0..ec8d7f4dae 100644 --- a/wxPython/wx/py/shell.py +++ b/wxPython/wx/py/shell.py @@ -31,7 +31,7 @@ NAVKEYS = (wx.WXK_END, wx.WXK_LEFT, wx.WXK_RIGHT, wx.WXK_UP, wx.WXK_DOWN, wx.WXK_PRIOR, wx.WXK_NEXT) -class ShellFrame(frame.Frame): +class ShellFrame(frame.Frame, frame.ShellFrameMixin): """Frame containing the shell component.""" name = 'Shell Frame' @@ -40,19 +40,31 @@ class ShellFrame(frame.Frame): def __init__(self, parent=None, id=-1, title='PyShell', pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, locals=None, - InterpClass=None, *args, **kwds): + InterpClass=None, + config=None, dataDir=None, + *args, **kwds): """Create ShellFrame instance.""" frame.Frame.__init__(self, parent, id, title, pos, size, style) + frame.ShellFrameMixin.__init__(self, config, dataDir) + + if size == wx.DefaultSize: + self.SetSize((750, 525)) + intro = 'PyShell %s - The Flakiest Python Shell' % VERSION - intro += '\nSponsored by Orbtech - ' + \ - 'Your source for Python programming expertise.' self.SetStatusText(intro.replace('\n', ', ')) self.shell = Shell(parent=self, id=-1, introText=intro, locals=locals, InterpClass=InterpClass, + startupScript=self.startupScript, + execStartupScript=self.execStartupScript, *args, **kwds) + # Override the shell so that status messages go to the status bar. self.shell.setStatusText = self.SetStatusText + self.shell.SetFocus() + self.LoadSettings() + + def OnClose(self, event): """Event handler for closing.""" # This isn't working the way I want, but I'll leave it for now. @@ -60,6 +72,7 @@ class ShellFrame(frame.Frame): if event.CanVeto(): event.Veto(True) else: + self.SaveSettings() self.shell.destroy() self.Destroy() @@ -72,30 +85,43 @@ class ShellFrame(frame.Frame): 'the other half is still in the oven.\n\n' + \ 'Shell Revision: %s\n' % self.shell.revision + \ 'Interpreter Revision: %s\n\n' % self.shell.interp.revision + \ + 'Platform: %s\n' % sys.platform + \ 'Python Version: %s\n' % sys.version.split()[0] + \ 'wxPython Version: %s\n' % wx.VERSION_STRING + \ - 'Platform: %s\n' % sys.platform + ('\t(%s)\n' % ", ".join(wx.PlatformInfo[1:])) dialog = wx.MessageDialog(self, text, title, wx.OK | wx.ICON_INFORMATION) dialog.ShowModal() dialog.Destroy() -class ShellFacade: - """Simplified interface to all shell-related functionality. + def OnHelp(self, event): + """Show a help dialog.""" + frame.ShellFrameMixin.OnHelp(self, event) - This is a semi-transparent facade, in that all attributes of other - are accessible, even though only some are visible to the user.""" - name = 'Shell Interface' - revision = __revision__ + def LoadSettings(self): + if self.config is not None: + frame.ShellFrameMixin.LoadSettings(self) + frame.Frame.LoadSettings(self, self.config) + self.shell.LoadSettings(self.config) - def __init__(self, other): - """Create a ShellFacade instance.""" - d = self.__dict__ - d['other'] = other - d['helpText'] = \ -""" + def SaveSettings(self, force=False): + if self.config is not None: + frame.ShellFrameMixin.SaveSettings(self) + if self.autoSaveSettings or force: + frame.Frame.SaveSettings(self, self.config) + self.shell.SaveSettings(self.config) + + def DoSaveSettings(self): + if self.config is not None: + self.SaveSettings(force=True) + self.config.Flush() + + + + +HELP_TEXT = """\ * Key bindings: Home Go to the beginning of the command or line. Shift+Home Select to the beginning of the command or line. @@ -103,6 +129,7 @@ Shift+End Select to the end of the line. End Go to the end of the line. Ctrl+C Copy selected text, removing prompts. Ctrl+Shift+C Copy selected text, retaining prompts. +Alt+C Copy to the clipboard, including prefixed prompts. Ctrl+X Cut selected text. Ctrl+V Paste from clipboard. Ctrl+Shift+V Paste and run multiple commands from clipboard. @@ -118,8 +145,31 @@ Ctrl+Enter Insert new line into multiline command. Ctrl+] Increase font size. Ctrl+[ Decrease font size. Ctrl+= Default font size. +Ctrl-Space Show Auto Completion. +Ctrl-Alt-Space Show Call Tip. +Shift+Enter Complete Text from History. +Ctrl+F Search +F3 Search next +Ctrl+H "hide" lines containing selection / "unhide" +F12 on/off "free-edit" mode """ +class ShellFacade: + """Simplified interface to all shell-related functionality. + + This is a semi-transparent facade, in that all attributes of other + are accessible, even though only some are visible to the user.""" + + name = 'Shell Interface' + revision = __revision__ + + def __init__(self, other): + """Create a ShellFacade instance.""" + d = self.__dict__ + d['other'] = other + d['helpText'] = HELP_TEXT + d['this'] = other.this + def help(self): """Display some useful information about how to use the shell.""" self.write(self.helpText) @@ -150,6 +200,7 @@ Ctrl+= Default font size. 'autoCompleteIncludeDouble', 'autoCompleteIncludeMagic', 'autoCompleteIncludeSingle', + 'callTipInsert', 'clear', 'pause', 'prompt', @@ -166,6 +217,7 @@ Ctrl+= Default font size. return list + class Shell(editwindow.EditWindow): """Shell based on StyledTextCtrl.""" @@ -174,26 +226,32 @@ class Shell(editwindow.EditWindow): def __init__(self, parent, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.CLIP_CHILDREN, - introText='', locals=None, InterpClass=None, *args, **kwds): + introText='', locals=None, InterpClass=None, + startupScript=None, execStartupScript=True, + *args, **kwds): """Create Shell instance.""" editwindow.EditWindow.__init__(self, parent, id, pos, size, style) self.wrap() if locals is None: import __main__ locals = __main__.__dict__ + # Grab these so they can be restored by self.redirect* methods. self.stdin = sys.stdin self.stdout = sys.stdout self.stderr = sys.stderr + # Import a default interpreter class if one isn't provided. if InterpClass == None: from interpreter import Interpreter else: Interpreter = InterpClass + # Create a replacement for stdin. self.reader = PseudoFileIn(self.readline, self.readlines) self.reader.input = '' self.reader.isreading = False + # Set up the interpreter. self.interp = Interpreter(locals=locals, rawin=self.raw_input, @@ -201,15 +259,20 @@ class Shell(editwindow.EditWindow): stdout=PseudoFileOut(self.writeOut), stderr=PseudoFileErr(self.writeErr), *args, **kwds) + # Set up the buffer. self.buffer = Buffer() + # Find out for which keycodes the interpreter will autocomplete. self.autoCompleteKeys = self.interp.getAutoCompleteKeys() + # Keep track of the last non-continuation prompt positions. self.promptPosStart = 0 self.promptPosEnd = 0 + # Keep track of multi-line commands. self.more = False + # Create the command history. Commands are added into the # front of the list (ie. at index 0) as they are entered. # self.historyIndex is the current position in the history; it @@ -219,23 +282,51 @@ class Shell(editwindow.EditWindow): # command, not in the history. self.history = [] self.historyIndex = -1 + + #seb add mode for "free edit" + self.noteMode = 0 + self.MarkerDefine(0,stc.STC_MARK_ROUNDRECT) # marker for hidden + self.searchTxt = "" + # Assign handlers for keyboard events. - wx.EVT_CHAR(self, self.OnChar) - wx.EVT_KEY_DOWN(self, self.OnKeyDown) + self.Bind(wx.EVT_CHAR, self.OnChar) + self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) + # Assign handler for idle time. self.waiting = False - wx.EVT_IDLE(self, self.OnIdle) + self.Bind(wx.EVT_IDLE, self.OnIdle) + # Display the introductory banner information. self.showIntro(introText) + # Assign some pseudo keywords to the interpreter's namespace. self.setBuiltinKeywords() + # Add 'shell' to the interpreter's local namespace. self.setLocalShell() + + ## NOTE: See note at bottom of this file... + ## #seb: File drag and drop + ## self.SetDropTarget( FileDropTarget(self) ) + # Do this last so the user has complete control over their # environment. They can override anything they want. - self.execStartupScript(self.interp.startupScript) + if execStartupScript: + if startupScript is None: + startupScript = os.environ.get('PYTHONSTARTUP') + self.execStartupScript(startupScript) + else: + self.prompt() + wx.CallAfter(self.ScrollToLine, 0) + + def clearHistory(self): + self.history = [] + self.historyIndex = -1 + dispatcher.send(signal="Shell.clearHistory") + + def destroy(self): del self.interp @@ -252,46 +343,50 @@ class Shell(editwindow.EditWindow): def showIntro(self, text=''): """Display introductory text in the shell.""" if text: - if not text.endswith(os.linesep): - text += os.linesep self.write(text) try: - self.write(self.interp.introText) + if self.interp.introText: + if text and not text.endswith(os.linesep): + self.write(os.linesep) + self.write(self.interp.introText) except AttributeError: pass def setBuiltinKeywords(self): """Create pseudo keywords as part of builtins. - This sets `close`, `exit` and `quit` to a helpful string. + This sets "close", "exit" and "quit" to a helpful string. """ import __builtin__ __builtin__.close = __builtin__.exit = __builtin__.quit = \ 'Click on the close button to leave the application.' + def quit(self): """Quit the application.""" - # XXX Good enough for now but later we want to send a close event. - # In the close event handler we can make sure they want to # quit. Other applications, like PythonCard, may choose to # hide rather than quit so we should just post the event and # let the surrounding app decide what it wants to do. self.write('Click on the close button to leave the application.') + def setLocalShell(self): """Add 'shell' to locals as reference to ShellFacade instance.""" self.interp.locals['shell'] = ShellFacade(other=self) + def execStartupScript(self, startupScript): """Execute the user's PYTHONSTARTUP script if they have one.""" if startupScript and os.path.isfile(startupScript): text = 'Startup script executed: ' + startupScript self.push('print %r; execfile(%r)' % (text, startupScript)) + self.interp.startupScript = startupScript else: self.push('') + def about(self): """Display information about Py.""" text = """ @@ -301,26 +396,33 @@ Py Shell Revision: %s Py Interpreter Revision: %s Python Version: %s wxPython Version: %s +wxPython PlatformInfo: %s Platform: %s""" % \ (__author__, VERSION, self.revision, self.interp.revision, - sys.version.split()[0], wx.VERSION_STRING, sys.platform) + sys.version.split()[0], wx.VERSION_STRING, str(wx.PlatformInfo), + sys.platform) self.write(text.strip()) + def OnChar(self, event): """Keypress event handler. Only receives an event if OnKeyDown calls event.Skip() for the corresponding event.""" + if self.noteMode: + event.Skip() + return + # Prevent modification of previously submitted # commands/responses. if not self.CanEdit(): return - key = event.KeyCode() + key = event.GetKeyCode() currpos = self.GetCurrentPos() stoppos = self.promptPosEnd # Return (Enter) needs to be ignored in this handler. - if key == wx.WXK_RETURN: + if key in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]: pass elif key in self.autoCompleteKeys: # Usually the dot (period) key activates auto completion. @@ -342,19 +444,21 @@ Platform: %s""" % \ self.ReplaceSelection('') command = self.GetTextRange(stoppos, currpos) + '(' self.write('(') - self.autoCallTipShow(command) + self.autoCallTipShow(command, self.GetCurrentPos() == self.GetTextLength()) else: # Allow the normal event handling to take place. event.Skip() + def OnKeyDown(self, event): """Key down event handler.""" - key = event.KeyCode() + key = event.GetKeyCode() # If the auto-complete window is up let it do its thing. if self.AutoCompActive(): event.Skip() return + # Prevent modification of previously submitted # commands/responses. controlDown = event.ControlDown() @@ -363,54 +467,122 @@ Platform: %s""" % \ currpos = self.GetCurrentPos() endpos = self.GetTextLength() selecting = self.GetSelectionStart() != self.GetSelectionEnd() + + if controlDown and shiftDown and key in (ord('F'), ord('f')): + li = self.GetCurrentLine() + m = self.MarkerGet(li) + if m & 1<<0: + startP = self.PositionFromLine(li) + self.MarkerDelete(li, 0) + maxli = self.GetLineCount() + li += 1 # li stayed visible as header-line + li0 = li + while li self.promptPosEnd: event.Skip() + # Only allow these keys after the latest prompt. elif key in (wx.WXK_TAB, wx.WXK_DELETE): if self.CanEdit(): event.Skip() + # Don't toggle between insert mode and overwrite mode. elif key == wx.WXK_INSERT: pass + # Don't allow line deletion. elif controlDown and key in (ord('L'), ord('l')): pass + # Don't allow line transposition. elif controlDown and key in (ord('T'), ord('t')): pass + # Basic navigation keys should work anywhere. elif key in NAVKEYS: event.Skip() + # Protect the readonly portion of the shell. elif not self.CanEdit(): pass + else: event.Skip() + + def OnShowCompHistory(self): + """Show possible autocompletion Words from already typed words.""" + + #copy from history + his = self.history[:] + + #put together in one string + joined = " ".join (his) + import re + + #sort out only "good" words + newlist = re.split("[ \.\[\]=}(\)\,0-9\"]", joined) + + #length > 1 (mix out "trash") + thlist = [] + for i in newlist: + if len (i) > 1: + thlist.append (i) + + #unique (no duplicate words + #oneliner from german python forum => unique list + unlist = [thlist[i] for i in xrange(len(thlist)) if thlist[i] not in thlist[:i]] + + #sort lowercase + unlist.sort(lambda a, b: cmp(a.lower(), b.lower())) + + #this is more convenient, isn't it? + self.AutoCompSetIgnoreCase(True) + + #join again together in a string + stringlist = " ".join(unlist) + + #pos von 0 noch ausrechnen + + #how big is the offset? + cpos = self.GetCurrentPos() - 1 + while chr (self.GetCharAt (cpos)).isalnum(): + cpos -= 1 + + #the most important part + self.AutoCompShow(self.GetCurrentPos() - cpos -1, stringlist) + + def clearCommand(self): """Delete the current, unexecuted command.""" startpos = self.promptPosEnd @@ -588,6 +824,7 @@ Platform: %s""" % \ self.write(os.linesep) else: self.push(command) + wx.FutureCall(1, self.EnsureCaretVisible) # Or replace the current command with the other command. else: # If the line contains a command (even an invalid one). @@ -664,9 +901,10 @@ Platform: %s""" % \ text = text[ps2size:] return text - def push(self, command): + def push(self, command, silent = False): """Send command to the interpreter for execution.""" - self.write(os.linesep) + if not silent: + self.write(os.linesep) busy = wx.BusyCursor() self.waiting = True self.more = self.interp.push(command) @@ -674,7 +912,8 @@ Platform: %s""" % \ del busy if not self.more: self.addHistory(command.rstrip()) - self.prompt() + if not silent: + self.prompt() def addHistory(self, command): """Add command to the command history.""" @@ -685,6 +924,7 @@ Platform: %s""" % \ if command != '' \ and (len(self.history) == 0 or command != self.history[0]): self.history.insert(0, command) + dispatcher.send(signal="Shell.addHistory", command=command) def write(self, text): """Display text in the shell. @@ -816,7 +1056,7 @@ Platform: %s""" % \ finally: file.close() - def autoCompleteShow(self, command): + def autoCompleteShow(self, command, offset = 0): """Display auto-completion popup list.""" self.AutoCompSetAutoHide(self.autoCompleteAutoHide) self.AutoCompSetIgnoreCase(self.autoCompleteCaseInsensitive) @@ -826,19 +1066,19 @@ Platform: %s""" % \ includeDouble=self.autoCompleteIncludeDouble) if list: options = ' '.join(list) - offset = 0 + #offset = 0 self.AutoCompShow(offset, options) - def autoCallTipShow(self, command): + def autoCallTipShow(self, command, insertcalltip = True, forceCallTip = False): """Display argument spec and docstring in a popup window.""" if self.CallTipActive(): self.CallTipCancel() (name, argspec, tip) = self.interp.getCallTip(command) if tip: dispatcher.send(signal='Shell.calltip', sender=self, calltip=tip) - if not self.autoCallTip: + if not self.autoCallTip and not forceCallTip: return - if argspec: + if argspec and insertcalltip and self.callTipInsert: startpos = self.GetCurrentPos() self.write(argspec + ')') endpos = self.GetCurrentPos() @@ -851,6 +1091,53 @@ Platform: %s""" % \ # fallback. tippos = max(tippos, fallback) self.CallTipShow(tippos, tip) + + def OnCallTipAutoCompleteManually (self, shiftDown): + """AutoComplete and Calltips manually.""" + if self.AutoCompActive(): + self.AutoCompCancel() + currpos = self.GetCurrentPos() + stoppos = self.promptPosEnd + + cpos = currpos + #go back until '.' is found + pointavailpos = -1 + while cpos >= stoppos: + if self.GetCharAt(cpos) == ord ('.'): + pointavailpos = cpos + break + cpos -= 1 + + #word from non whitespace until '.' + if pointavailpos != -1: + #look backward for first whitespace char + textbehind = self.GetTextRange (pointavailpos + 1, currpos) + pointavailpos += 1 + + if not shiftDown: + #call AutoComplete + stoppos = self.promptPosEnd + textbefore = self.GetTextRange(stoppos, pointavailpos) + self.autoCompleteShow(textbefore, len (textbehind)) + else: + #call CallTips + cpos = pointavailpos + begpos = -1 + while cpos > stoppos: + if chr(self.GetCharAt(cpos)).isspace(): + begpos = cpos + break + cpos -= 1 + if begpos == -1: + begpos = cpos + ctips = self.GetTextRange (begpos, currpos) + ctindex = ctips.find ('(') + if ctindex != -1 and not self.CallTipActive(): + #insert calltip, if current pos is '(', otherwise show it only + self.autoCallTipShow(ctips[:ctindex + 1], + self.GetCharAt(currpos - 1) == ord('(') and self.GetCurrentPos() == self.GetTextLength(), + True) + def writeOut(self, text): """Replacement for stdout.""" @@ -973,52 +1260,64 @@ Platform: %s""" % \ self.write(command) wx.TheClipboard.Close() + def PasteAndRun(self): """Replace selection with clipboard contents, run commands.""" + text = '' if wx.TheClipboard.Open(): - ps1 = str(sys.ps1) - ps2 = str(sys.ps2) if wx.TheClipboard.IsSupported(wx.DataFormat(wx.DF_TEXT)): data = wx.TextDataObject() if wx.TheClipboard.GetData(data): - endpos = self.GetTextLength() - self.SetCurrentPos(endpos) - startpos = self.promptPosEnd - self.SetSelection(startpos, endpos) - self.ReplaceSelection('') text = data.GetText() - text = text.lstrip() - text = self.fixLineEndings(text) - text = self.lstripPrompt(text) - text = text.replace(os.linesep + ps1, '\n') - text = text.replace(os.linesep + ps2, '\n') - text = text.replace(os.linesep, '\n') - lines = text.split('\n') - commands = [] - command = '' - for line in lines: - if line.strip() == ps2.strip(): - # If we are pasting from something like a - # web page that drops the trailing space - # from the ps2 prompt of a blank line. - line = '' - if line.strip() != '' and line.lstrip() == line: - # New command. - if command: - # Add the previous command to the list. - commands.append(command) - # Start a new command, which may be multiline. - command = line - else: - # Multiline command. Add to the command. - command += '\n' - command += line - commands.append(command) - for command in commands: - command = command.replace('\n', os.linesep + ps2) - self.write(command) - self.processLine() wx.TheClipboard.Close() + if text: + self.Execute(text) + + + def Execute(self, text): + """Replace selection with text and run commands.""" + ps1 = str(sys.ps1) + ps2 = str(sys.ps2) + endpos = self.GetTextLength() + self.SetCurrentPos(endpos) + startpos = self.promptPosEnd + self.SetSelection(startpos, endpos) + self.ReplaceSelection('') + text = text.lstrip() + text = self.fixLineEndings(text) + text = self.lstripPrompt(text) + text = text.replace(os.linesep + ps1, '\n') + text = text.replace(os.linesep + ps2, '\n') + text = text.replace(os.linesep, '\n') + lines = text.split('\n') + commands = [] + command = '' + for line in lines: + if line.strip() == ps2.strip(): + # If we are pasting from something like a + # web page that drops the trailing space + # from the ps2 prompt of a blank line. + line = '' + lstrip = line.lstrip() + if line.strip() != '' and lstrip == line and \ + lstrip[:4] not in ['else','elif'] and \ + lstrip[:6] != 'except': + # New command. + if command: + # Add the previous command to the list. + commands.append(command) + # Start a new command, which may be multiline. + command = line + else: + # Multiline command. Add to the command. + command += '\n' + command += line + commands.append(command) + for command in commands: + command = command.replace('\n', os.linesep + ps2) + self.write(command) + self.processLine() + def wrap(self, wrap=True): """Sets whether text is word wrapped.""" @@ -1033,3 +1332,101 @@ Platform: %s""" % \ This number of points is added to the size of all fonts. It may be positive to magnify or negative to reduce.""" self.SetZoom(points) + + + + def LoadSettings(self, config): + self.autoComplete = config.ReadBool('Options/AutoComplete', True) + self.autoCompleteIncludeMagic = config.ReadBool('Options/AutoCompleteIncludeMagic', True) + self.autoCompleteIncludeSingle = config.ReadBool('Options/AutoCompleteIncludeSingle', True) + self.autoCompleteIncludeDouble = config.ReadBool('Options/AutoCompleteIncludeDouble', True) + + self.autoCallTip = config.ReadBool('Options/AutoCallTip', True) + self.callTipInsert = config.ReadBool('Options/CallTipInsert', True) + self.SetWrapMode(config.ReadBool('View/WrapMode', True)) + + useAA = config.ReadBool('Options/UseAntiAliasing', self.GetUseAntiAliasing()) + self.SetUseAntiAliasing(useAA) + self.lineNumbers = config.ReadBool('View/ShowLineNumbers', True) + self.setDisplayLineNumbers (self.lineNumbers) + zoom = config.ReadInt('View/Zoom/Shell', -99) + if zoom != -99: + self.SetZoom(zoom) + + + + def SaveSettings(self, config): + config.WriteBool('Options/AutoComplete', self.autoComplete) + config.WriteBool('Options/AutoCompleteIncludeMagic', self.autoCompleteIncludeMagic) + config.WriteBool('Options/AutoCompleteIncludeSingle', self.autoCompleteIncludeSingle) + config.WriteBool('Options/AutoCompleteIncludeDouble', self.autoCompleteIncludeDouble) + config.WriteBool('Options/AutoCallTip', self.autoCallTip) + config.WriteBool('Options/CallTipInsert', self.callTipInsert) + config.WriteBool('Options/UseAntiAliasing', self.GetUseAntiAliasing()) + config.WriteBool('View/WrapMode', self.GetWrapMode()) + config.WriteBool('View/ShowLineNumbers', self.lineNumbers) + config.WriteInt('View/Zoom/Shell', self.GetZoom()) + + + +## NOTE: The DnD of file names is disabled until I can figure out how +## best to still allow DnD of text. + + +## #seb : File drag and drop +## class FileDropTarget(wx.FileDropTarget): +## def __init__(self, obj): +## wx.FileDropTarget.__init__(self) +## self.obj = obj +## def OnDropFiles(self, x, y, filenames): +## if len(filenames) == 1: +## txt = 'r\"%s\"' % filenames[0] +## else: +## txt = '( ' +## for f in filenames: +## txt += 'r\"%s\" , ' % f +## txt += ')' +## self.obj.AppendText(txt) +## pos = self.obj.GetCurrentPos() +## self.obj.SetCurrentPos( pos ) +## self.obj.SetSelection( pos, pos ) + + + +## class TextAndFileDropTarget(wx.DropTarget): +## def __init__(self, shell): +## wx.DropTarget.__init__(self) +## self.shell = shell +## self.compdo = wx.DataObjectComposite() +## self.textdo = wx.TextDataObject() +## self.filedo = wx.FileDataObject() +## self.compdo.Add(self.textdo) +## self.compdo.Add(self.filedo, True) + +## self.SetDataObject(self.compdo) + +## def OnDrop(self, x, y): +## return True + +## def OnData(self, x, y, result): +## self.GetData() +## if self.textdo.GetTextLength() > 1: +## text = self.textdo.GetText() +## # *** Do somethign with the dragged text here... +## self.textdo.SetText('') +## else: +## filenames = str(self.filename.GetFilenames()) +## if len(filenames) == 1: +## txt = 'r\"%s\"' % filenames[0] +## else: +## txt = '( ' +## for f in filenames: +## txt += 'r\"%s\" , ' % f +## txt += ')' +## self.shell.AppendText(txt) +## pos = self.shell.GetCurrentPos() +## self.shell.SetCurrentPos( pos ) +## self.shell.SetSelection( pos, pos ) + +## return result +