+ pass
+ else:
+ if not filename:
+ filename = "<string>"
+ line = line.strip()
+ self.traceback.append( (filename, lineno, "", line) )
+ excValue = msg
+ try:
+ self.exception_details = str(excValue)
+ except:
+ self.exception_details = "<unprintable %s object>" & type(excValue).__name__
+
+ del exc_info
+
+ def __str__(self):
+ ret = "Type %s \n \
+ Traceback: %s \n \
+ Details : %s" % ( str(self.exception_type), str(self.traceback), self.exception_details )
+ return ret
+
+#---------------------------------------------------------------------------
+
+class DemoErrorPanel(wx.Panel):
+ """Panel put into the demo tab when the demo fails to run due to errors"""
+
+ def __init__(self, parent, codePanel, demoError, log):
+ wx.Panel.__init__(self, parent, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
+ self.codePanel = codePanel
+ self.nb = parent
+ self.log = log
+
+ self.box = wx.BoxSizer(wx.VERTICAL)
+
+ # Main Label
+ self.box.Add(wx.StaticText(self, -1, "An error has occurred while trying to run the demo")
+ , 0, wx.ALIGN_CENTER | wx.TOP, 10)
+
+ # Exception Information
+ boxInfo = wx.StaticBox(self, -1, "Exception Info" )
+ boxInfoSizer = wx.StaticBoxSizer(boxInfo, wx.VERTICAL ) # Used to center the grid within the box
+ boxInfoGrid = wx.FlexGridSizer(0, 2, 0, 0)
+ textFlags = wx.ALIGN_RIGHT | wx.LEFT | wx.RIGHT | wx.TOP
+ boxInfoGrid.Add(wx.StaticText(self, -1, "Type: "), 0, textFlags, 5 )
+ boxInfoGrid.Add(wx.StaticText(self, -1, str(demoError.exception_type)) , 0, textFlags, 5 )
+ boxInfoGrid.Add(wx.StaticText(self, -1, "Details: ") , 0, textFlags, 5 )
+ boxInfoGrid.Add(wx.StaticText(self, -1, demoError.exception_details) , 0, textFlags, 5 )
+ boxInfoSizer.Add(boxInfoGrid, 0, wx.ALIGN_CENTRE | wx.ALL, 5 )
+ self.box.Add(boxInfoSizer, 0, wx.ALIGN_CENTER | wx.ALL, 5)
+
+ # Set up the traceback list
+ # This one automatically resizes last column to take up remaining space
+ from ListCtrl import TestListCtrl
+ self.list = TestListCtrl(self, -1, style=wx.LC_REPORT | wx.SUNKEN_BORDER)
+ self.list.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick)
+ self.list.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
+ self.list.InsertColumn(0, "Filename")
+ self.list.InsertColumn(1, "Line", wx.LIST_FORMAT_RIGHT)
+ self.list.InsertColumn(2, "Function")
+ self.list.InsertColumn(3, "Code")
+ self.InsertTraceback(self.list, demoError.traceback)
+ self.list.SetColumnWidth(0, wx.LIST_AUTOSIZE)
+ self.list.SetColumnWidth(2, wx.LIST_AUTOSIZE)
+ self.box.Add(wx.StaticText(self, -1, "Traceback:")
+ , 0, wx.ALIGN_CENTER | wx.TOP, 5)
+ self.box.Add(self.list, 1, wx.GROW | wx.ALIGN_CENTER | wx.ALL, 5)
+ self.box.Add(wx.StaticText(self, -1, "Entries from the demo module are shown in blue\n"
+ + "Double-click on them to go to the offending line")
+ , 0, wx.ALIGN_CENTER | wx.BOTTOM, 5)
+
+ self.box.Fit(self)
+ self.SetSizer(self.box)
+
+
+ def InsertTraceback(self, list, traceback):
+ #Add the traceback data
+ for x in range(len(traceback)):
+ data = traceback[x]
+ list.InsertStringItem(x, os.path.basename(data[0])) # Filename
+ list.SetStringItem(x, 1, str(data[1])) # Line
+ list.SetStringItem(x, 2, str(data[2])) # Function
+ list.SetStringItem(x, 3, str(data[3])) # Code
+
+ # Check whether this entry is from the demo module
+ if data[0] == "<original>" or data[0] == "<modified>": # FIXME: make more generalised
+ self.list.SetItemData(x, int(data[1])) # Store line number for easy access
+ # Give it a blue colour
+ item = self.list.GetItem(x)
+ item.SetTextColour(wx.BLUE)
+ self.list.SetItem(item)
+ else:
+ self.list.SetItemData(x, -1) # Editor can't jump into this one's code
+
+
+ def OnItemSelected(self, event):
+ # This occurs before OnDoubleClick and can be used to set the
+ # currentItem. OnDoubleClick doesn't get a wxListEvent....
+ self.currentItem = event.m_itemIndex
+ event.Skip()
+
+
+ def OnDoubleClick(self, event):
+ # If double-clicking on a demo's entry, jump to the line number
+ line = self.list.GetItemData(self.currentItem)
+ if line != -1:
+ self.nb.SetSelection(1) # Switch to the code viewer tab
+ wx.CallAfter(self.codePanel.JumpToLine, line-1, True)
+ event.Skip()
+
+
+#---------------------------------------------------------------------------
+
+class DemoTaskBarIcon(wx.TaskBarIcon):
+ TBMENU_RESTORE = wx.NewId()
+ TBMENU_CLOSE = wx.NewId()
+ TBMENU_CHANGE = wx.NewId()
+ TBMENU_REMOVE = wx.NewId()
+
+ def __init__(self, frame):
+ wx.TaskBarIcon.__init__(self)
+ self.frame = frame
+
+ # Set the image
+ icon = self.MakeIcon(images.getWXPdemoImage())
+ self.SetIcon(icon, "wxPython Demo")
+ self.imgidx = 1
+
+ # bind some events
+ self.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarActivate)
+ self.Bind(wx.EVT_MENU, self.OnTaskBarActivate, id=self.TBMENU_RESTORE)
+ self.Bind(wx.EVT_MENU, self.OnTaskBarClose, id=self.TBMENU_CLOSE)
+ self.Bind(wx.EVT_MENU, self.OnTaskBarChange, id=self.TBMENU_CHANGE)
+ self.Bind(wx.EVT_MENU, self.OnTaskBarRemove, id=self.TBMENU_REMOVE)
+
+
+ def CreatePopupMenu(self):
+ """
+ This method is called by the base class when it needs to popup
+ the menu for the default EVT_RIGHT_DOWN event. Just create
+ the menu how you want it and return it from this function,
+ the base class takes care of the rest.
+ """
+ menu = wx.Menu()
+ menu.Append(self.TBMENU_RESTORE, "Restore wxPython Demo")
+ menu.Append(self.TBMENU_CLOSE, "Close wxPython Demo")
+ menu.AppendSeparator()
+ menu.Append(self.TBMENU_CHANGE, "Change the TB Icon")
+ menu.Append(self.TBMENU_REMOVE, "Remove the TB Icon")
+ return menu
+
+
+ def MakeIcon(self, img):
+ """
+ The various platforms have different requirements for the
+ icon size...
+ """
+ if "wxMSW" in wx.PlatformInfo:
+ img = img.Scale(16, 16)
+ elif "wxGTK" in wx.PlatformInfo:
+ img = img.Scale(22, 22)
+ # wxMac can be any size upto 128x128, so leave the source img alone....
+ icon = wx.IconFromBitmap(img.ConvertToBitmap() )
+ return icon
+
+
+ def OnTaskBarActivate(self, evt):
+ if self.frame.IsIconized():
+ self.frame.Iconize(False)
+ if not self.frame.IsShown():
+ self.frame.Show(True)
+ self.frame.Raise()
+
+
+ def OnTaskBarClose(self, evt):
+ self.frame.Close()
+
+
+ def OnTaskBarChange(self, evt):
+ names = [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
+ name = names[self.imgidx]
+
+ getFunc = getattr(images, "get%sImage" % name)
+ self.imgidx += 1
+ if self.imgidx >= len(names):
+ self.imgidx = 0
+
+ icon = self.MakeIcon(getFunc())
+ self.SetIcon(icon, "This is a new icon: " + name)
+
+
+ def OnTaskBarRemove(self, evt):
+ self.RemoveIcon()
+
+
+#---------------------------------------------------------------------------
+class wxPythonDemo(wx.Frame):
+ overviewText = "wxPython Overview"
+
+ def __init__(self, parent, title):
+ wx.Frame.__init__(self, parent, -1, title, size = (970, 720),
+ style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)
+
+ self.SetMinSize((640,480))
+
+ self.mgr = wx.aui.AuiManager()
+ self.mgr.SetManagedWindow(self)
+
+ self.loaded = False
+ self.cwd = os.getcwd()
+ self.curOverview = ""
+ self.demoPage = None
+ self.codePage = None
+ self.shell = None
+ self.firstTime = True
+ self.finddlg = None
+
+ icon = images.getWXPdemoIcon()
+ self.SetIcon(icon)
+
+ try:
+ self.tbicon = DemoTaskBarIcon(self)
+ except:
+ self.tbicon = None
+
+ self.otherWin = None
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+ self.Bind(wx.EVT_ICONIZE, self.OnIconfiy)
+ self.Bind(wx.EVT_MAXIMIZE, self.OnMaximize)
+
+ self.Centre(wx.BOTH)
+ self.CreateStatusBar(1, wx.ST_SIZEGRIP)
+
+ self.dying = False
+ self.skipLoad = False
+
+ def EmptyHandler(evt): pass
+
+ self.ReadConfigurationFile()
+
+ # Create a Notebook
+ self.nb = wx.Notebook(self, -1, style=wx.CLIP_CHILDREN)
+ imgList = wx.ImageList(16, 16)
+ for png in ["overview", "code", "demo"]:
+ bmp = images.catalog[png].getBitmap()
+ imgList.Add(bmp)
+ self.nb.AssignImageList(imgList)
+
+ self.BuildMenuBar()
+
+ self.finddata = wx.FindReplaceData()
+ self.finddata.SetFlags(wx.FR_DOWN)
+
+ # Create a TreeCtrl
+ leftPanel = wx.Panel(self, style=wx.TAB_TRAVERSAL|wx.CLIP_CHILDREN)
+ self.treeMap = {}
+ self.searchItems = {}
+
+ self.tree = wxPythonDemoTree(leftPanel)
+
+ self.filter = wx.SearchCtrl(leftPanel, style=wx.TE_PROCESS_ENTER)
+ self.filter.ShowCancelButton(True)
+ self.filter.Bind(wx.EVT_TEXT, self.RecreateTree)
+ self.filter.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN,
+ lambda e: self.filter.SetValue(''))
+ self.filter.Bind(wx.EVT_TEXT_ENTER, self.OnSearch)
+
+ searchMenu = wx.Menu()
+ item = searchMenu.AppendRadioItem(-1, "Sample Name")
+ self.Bind(wx.EVT_MENU, self.OnSearchMenu, item)
+ item = searchMenu.AppendRadioItem(-1, "Sample Content")
+ self.Bind(wx.EVT_MENU, self.OnSearchMenu, item)
+ self.filter.SetMenu(searchMenu)
+
+ self.RecreateTree()
+ self.tree.SetExpansionState(self.expansionState)
+ self.tree.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnItemExpanded)
+ self.tree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed)
+ self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged)
+ self.tree.Bind(wx.EVT_LEFT_DOWN, self.OnTreeLeftDown)
+
+ # Set up a wx.html.HtmlWindow on the Overview Notebook page
+ # we put it in a panel first because there seems to be a
+ # refresh bug of some sort (wxGTK) when it is directly in
+ # the notebook...
+
+ if 0: # the old way
+ self.ovr = wx.html.HtmlWindow(self.nb, -1, size=(400, 400))
+ self.nb.AddPage(self.ovr, self.overviewText, imageId=0)
+
+ else: # hopefully I can remove this hacky code soon, see SF bug #216861
+ panel = wx.Panel(self.nb, -1, style=wx.CLIP_CHILDREN)
+ self.ovr = wx.html.HtmlWindow(panel, -1, size=(400, 400))
+ self.nb.AddPage(panel, self.overviewText, imageId=0)
+
+ def OnOvrSize(evt, ovr=self.ovr):
+ ovr.SetSize(evt.GetSize())
+ panel.Bind(wx.EVT_SIZE, OnOvrSize)
+ panel.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
+
+ if "gtk2" in wx.PlatformInfo:
+ self.ovr.SetStandardFonts()
+ self.SetOverview(self.overviewText, mainOverview)
+
+
+ # Set up a log window
+ self.log = wx.TextCtrl(self, -1,
+ style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
+ if wx.Platform == "__WXMAC__":
+ self.log.MacCheckSpelling(False)
+
+ # Set the wxWindows log target to be this textctrl
+ #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
+
+ # But instead of the above we want to show how to use our own wx.Log class
+ wx.Log_SetActiveTarget(MyLog(self.log))
+
+ # for serious debugging
+ #wx.Log_SetActiveTarget(wx.LogStderr())
+ #wx.Log_SetTraceMask(wx.TraceMessages)
+
+ self.Bind(wx.EVT_ACTIVATE, self.OnActivate)
+ wx.GetApp().Bind(wx.EVT_ACTIVATE_APP, self.OnAppActivate)
+
+ # add the windows to the splitter and split it.
+ leftBox = wx.BoxSizer(wx.VERTICAL)
+ leftBox.Add(self.tree, 1, wx.EXPAND)
+ leftBox.Add(wx.StaticText(leftPanel, label = "Filter Demos:"), 0, wx.TOP|wx.LEFT, 5)
+ leftBox.Add(self.filter, 0, wx.EXPAND|wx.ALL, 5)
+ leftPanel.SetSizer(leftBox)
+
+ # select initial items
+ self.nb.SetSelection(0)
+ self.tree.SelectItem(self.root)
+
+ # Load 'Main' module
+ self.LoadDemo(self.overviewText)
+ self.loaded = True
+
+ # select some other initial module?
+ if len(sys.argv) > 1:
+ arg = sys.argv[1]
+ if arg.endswith('.py'):
+ arg = arg[:-3]
+ selectedDemo = self.treeMap.get(arg, None)