dabodemo Commit
Revision 438
Date: 2006-10-31 08:28:17 -0800 (Tue, 31 Oct 2006)
Author: ed

Changed:
U   trunk/DaboDemo/DaboDemo-code.py
U   trunk/DaboDemo/DaboDemo.cdxml
U   trunk/DaboDemo/Modules.py

Log:
OK, I've got the whole 'modified code' thing working now. You can edit the code 
in any sample, and save that code. When you go to the demo page, the result of 
your modifications will be visible. You can switch between the original and 
modified at any time. It is written to disk, so the modifications persist 
between sessions.

I also implemented the DemoErrorPanel, which will display if the modified code 
contains any errors. It will display the traceback information, and let you 
jump back to the 'offending' line. This was pretty much lifted straight from 
the wxPython demo, but re-written to 100% Dabo code.


Diff:
Modified: trunk/DaboDemo/DaboDemo-code.py
===================================================================
--- trunk/DaboDemo/DaboDemo-code.py     2006-10-30 22:18:27 UTC (rev 437)
+++ trunk/DaboDemo/DaboDemo-code.py     2006-10-31 16:28:17 UTC (rev 438)
@@ -3,12 +3,11 @@
 ###            'Dabo Code ID: XXXX', 
 ### as these are needed to link the code to the objects.
 
-## *!* ## Dabo Code ID: dPageFrame-dPage
-def showDemoPage(self):
-       self.SelectedPageNumber = 2
+## *!* ## Dabo Code ID: dHtmlBox-dPage
+def afterInit(self):
+       self.HTML = """<h1 align="center">Dabo Demonstration</h1>"""
 
 
-
 ## *!* ## Dabo Code ID: dEditBox-dPanel
 def clear(self, evt=None):
        self.Value = ""
@@ -21,22 +20,32 @@
 
 
 
-## *!* ## Dabo Code ID: dHtmlBox-dPage
-def afterInit(self):
-       self.HTML = """<h1 align="center">Dabo Demonstration</h1>"""
-#      self.Value = _("Dabo Demonstration")
-#      self.Alignment = "Center"
-#      self.FontSize = 32
-#      self.FontBold = True
-
-
-
 ## *!* ## Dabo Code ID: dEditor-dPage
 def onContentChanged(self, evt):
        self.Form.editorChanged()
 
 
 
+## *!* ## Dabo Code ID: dButton-dPage-409
+def onHit(self, evt):
+       # Delete modified code
+       self.Form.deleteModCode()
+
+
+
+## *!* ## Dabo Code ID: dButton-dPage
+def onHit(self, evt):
+       # Save modified code
+       self.Form.saveModCode()
+
+
+
+## *!* ## Dabo Code ID: dPageFrame-dPage
+def showDemoPage(self):
+       self.SelectedPageNumber = 2
+
+
+
 ## *!* ## Dabo Code ID: dRadioList-dPage
 def afterInit(self):
        self.reset(False)
@@ -63,8 +72,23 @@
 import os
 import sys
 from Modules import DemoModules
+from Modules import DemoError
+from Modules import DemoErrorPanel
 from dabo.dLocalize import _
 
+def _getActiveCode(self):
+       try:
+               ret = self.demoModules.getActive()
+       except StandardError, e:
+               ret = 0
+       return ret
+       
+def _setActiveCode(self, val):
+       self.demoModules.setActive(val)
+       self.loadDemo()
+       self.loadDemoSource()
+       self.radMod.Value = val
+
 def afterInitAll(self):
        pth = os.path.abspath(os.path.join(os.getcwd(), "samples"))
        if pth not in sys.path:
@@ -95,21 +119,32 @@
                        sn._obj = demos[mc][sc]
        tree.expandAll()
 
+def deleteModCode(self):
+       self.demoModules.deleteModified()
+       self.ActiveCode = 0
+
 def editorChanged(self):
        self.saveModButton.Enabled = self.codeEditor.Modified
 
 def loadDemo(self):
-       pnlClass = self.demoModules.getActive().TestPanel
        dpnl = self.demoPanel
        sz = dpnl.Sizer
        for kid in dpnl.Children:
                sz.remove(kid, True)
-       pnl = pnlClass(dpnl)
+       try:
+               pnl = self.demoModules.getActive().TestPanel(dpnl)
+       except:
+               pnl = DemoErrorPanel(dpnl)
+               err = DemoError(sys.exc_info())
+               pnl.setErrorInfo(self.codePage, err)
+
        sz.append1x(pnl)
        if self.displayFrame.SelectedPageNumber == 0:
                # Switch to the demo
                self.demoPageFrame.showDemoPage()
+       self.demoPanel.layout()
 
+
 def loadDemoSource(self):
        dm = self.demoModules
        self.codeEditor.Value = dm.getSource()
@@ -123,12 +158,17 @@
        self.log.scrollToEnd()
        self.log.ShowPosition(self.log.GetLastPosition())
 
+def saveModCode(self):
+       self.demoModules.saveMod(self.codeEditor.Value)
+       self.ActiveCode = 1
+       self.demoModules.updateFile()
+       self.radMod.reset(self.codeEditor.Modified)
+
 def setOverview(self):
        module = self.demoModules.getActive()
        ov = module.overview
        self.moduleOverview.HTML = ov
 
-
 def treeSelection(self):
        try:
                sel = self.tree.Selection._obj
@@ -142,3 +182,9 @@
                ok = False
        self.displayFrame.showContents(ok)
 
+
+def showCode(self, line=-1):
+       self.codeEditor.showContainingPage()
+       if line is not None:
+               self.codeEditor.LineNumber = line
+               
\ No newline at end of file

Modified: trunk/DaboDemo/DaboDemo.cdxml
===================================================================
--- trunk/DaboDemo/DaboDemo.cdxml       2006-10-30 22:18:27 UTC (rev 437)
+++ trunk/DaboDemo/DaboDemo.cdxml       2006-10-31 16:28:17 UTC (rev 438)
@@ -1,5 +1,17 @@
 <?xml version="1.0" encoding="utf-8" standalone="no"?>
-<dForm code-ID="dForm-top" Name="DaboDemoForm" Caption="Dabo: A Demonstration" 
Top="179" Height="668" Width="841" designerClass="DesForm" UseSizers="True" 
Left="392">
+<dForm code-ID="dForm-top" Name="DaboDemoForm" Caption="Dabo: A Demonstration" 
Top="79" Height="666" Width="906" designerClass="DesForm" UseSizers="True" 
Left="68">
+       <properties>
+               <ActiveCode>
+                       <comment>Zero for Original; 1 for modified</comment>
+                       <defaultValue>0</defaultValue>
+                       <deller>None</deller>
+                       <getter>_getActiveCode</getter>
+                       <propName>ActiveCode</propName>
+                       <defaultType>integer</defaultType>
+                       <setter>_setActiveCode</setter>
+               </ActiveCode>
+       </properties>
+
        <dSizer SlotCount="1" designerClass="LayoutSizer" 
Orientation="Vertical">
                <dSplitter SashPosition="201" sizerInfo="{'BorderSides': 
['All'], 'Proportion': 1, 'HAlign': 'Center', 'VAlign': 'Middle', 'Border': 0, 
'Expand': True}" designerClass="controlMix" Split="True" Orientation="Vertical">
                        <dPanel designerClass="MixedSplitterPanel" 
Name="dPanel2">
@@ -15,7 +27,7 @@
                                                                
<dPageFrameNoTabs RegID="displayFrame" code-ID="dPageFrameNoTabs-dPanel" 
sizerInfo="{'BorderSides': ['All'], 'Proportion': 1, 'HAlign': 'Center', 
'VAlign': 'Middle', 'Border': 0, 'Expand': True}" designerClass="controlMix" 
PageCount="2">
                                                                        <dPage 
Caption="" designerClass="controlMix" Name="dPage">
                                                                                
<dSizer SlotCount="1" designerClass="LayoutSizer" Orientation="Vertical">
-                                                                               
        <dHtmlBox RegID="mainOverview" code-ID="dHtmlBox-dPage"  
designerClass="controlMix" sizerInfo="{'BorderSides': ['All'], 'Proportion': 1, 
'HAlign': 'Left', 'VAlign': 'Top', 'Border': 0, 'Expand': True}"></dHtmlBox>
+                                                                               
        <dHtmlBox RegID="mainOverview" code-ID="dHtmlBox-dPage" 
sizerInfo="{'BorderSides': ['All'], 'Proportion': 1, 'HAlign': 'Left', 
'VAlign': 'Top', 'Border': 0, 'Expand': True}" 
designerClass="controlMix"></dHtmlBox>
                                                                                
</dSizer>
                                                                        </dPage>
                                                                        <dPage 
Caption="" designerClass="controlMix" Name="dPage1">
@@ -23,17 +35,17 @@
                                                                                
        <dPageFrame RegID="demoPageFrame" code-ID="dPageFrame-dPage" 
sizerInfo="{'BorderSides': ['All'], 'Proportion': 1, 'HAlign': 'Center', 
'VAlign': 'Middle', 'Border': 0, 'Expand': True}" designerClass="controlMix" 
PageCount="3">
                                                                                
                <dPage Caption="Overview" designerClass="controlMix" 
Name="dPage">
                                                                                
                        <dSizer SlotCount="1" designerClass="LayoutSizer" 
Orientation="Vertical">
-                                                                               
                                <dHtmlBox RegID="moduleOverview" 
designerClass="controlMix" sizerInfo="{'BorderSides': ['All'], 'Proportion': 1, 
'HAlign': 'Left', 'VAlign': 'Top', 'Border': 0, 'Expand': True}"></dHtmlBox>
+                                                                               
                                <dHtmlBox RegID="moduleOverview" 
sizerInfo="{'BorderSides': ['All'], 'Proportion': 1, 'HAlign': 'Left', 
'VAlign': 'Top', 'Border': 0, 'Expand': True}" 
designerClass="controlMix"></dHtmlBox>
                                                                                
                        </dSizer>
                                                                                
                </dPage>
-                                                                               
                <dPage Caption="Demo Code" designerClass="controlMix" 
Name="dPage1">
+                                                                               
                <dPage Caption="Demo Code" designerClass="controlMix" 
Name="dPage1" RegID="codePage">
                                                                                
                        <dSizer SlotCount="2" designerClass="LayoutSizer" 
Orientation="Vertical">
                                                                                
                                <dSizer SlotCount="5" 
sizerInfo="{'BorderSides': ['All'], 'Proportion': 0, 'HAlign': 'Left', 
'VAlign': 'Top', 'Border': 0, 'Expand': True}" designerClass="LayoutSizer" 
Orientation="Horizontal">
                                                                                
                                        <dLabel Caption="Active Version:" 
sizerInfo="{'BorderSides': ['All'], 'Proportion': 0, 'HAlign': 'Left', 
'VAlign': 'Middle', 'Border': 5, 'Expand': False}" 
designerClass="controlMix"></dLabel>
-                                                                               
                                        <dRadioList code-ID="dRadioList-dPage" 
sizerInfo="{'BorderSides': ['All'], 'Proportion': 0, 'HAlign': 'Left', 
'VAlign': 'Middle', 'Border': 0, 'Expand': False}" Orientation="Horizontal" 
Value="Original" Choices="[u&apos;Original&apos;, u&apos;Modified&apos;]" 
Caption="" designerClass="controlMix" ShowBox="False" 
RegID="radMod"></dRadioList>
+                                                                               
                                        <dRadioList code-ID="dRadioList-dPage" 
sizerInfo="{'BorderSides': ['All'], 'Proportion': 0, 'HAlign': 'Left', 
'VAlign': 'Middle', 'Border': 0, 'Expand': False}" ValueMode="position" 
Orientation="Horizontal" Value="0" Choices="[u&apos;Original&apos;, 
u&apos;Modified&apos;]" Caption="" DataSource="self.Form" 
designerClass="controlMix" ShowBox="False" RegID="radMod" 
DataField="ActiveCode"></dRadioList>
                                                                                
                                        <dPanel Spacing="12" 
sizerInfo="{'BorderSides': ['All'], 'Proportion': 0, 'HAlign': 'Left', 
'VAlign': 'Top', 'Border': 0, 'Expand': True}" 
designerClass="LayoutSpacerPanel"></dPanel>
-                                                                               
                                        <dButton RegID="saveModButton" 
Caption="Save Changes" sizerInfo="{'BorderSides': ['All'], 'Proportion': 0, 
'HAlign': 'Center', 'VAlign': 'Middle', 'Border': 5, 'Expand': False}" 
designerClass="controlMix"></dButton>
-                                                                               
                                        <dButton RegID="delModButton" 
Caption="Delete Modified" sizerInfo="{'BorderSides': ['All'], 'Proportion': 0, 
'HAlign': 'Center', 'VAlign': 'Middle', 'Border': 5, 'Expand': False}" 
designerClass="controlMix" Name="dButton1"></dButton>
+                                                                               
                                        <dButton RegID="saveModButton" 
Caption="Save Changes" sizerInfo="{'BorderSides': ['All'], 'Proportion': 0, 
'HAlign': 'Center', 'VAlign': 'Middle', 'Border': 5, 'Expand': False}" 
code-ID="dButton-dPage" designerClass="controlMix"></dButton>
+                                                                               
                                        <dButton code-ID="dButton-dPage-409" 
Caption="Delete Modified" sizerInfo="{'BorderSides': ['All'], 'Proportion': 0, 
'HAlign': 'Center', 'VAlign': 'Middle', 'Border': 5, 'Expand': False}" 
designerClass="controlMix" Name="dButton1" RegID="delModButton"></dButton>
                                                                                
                                </dSizer>
                                                                                
                                <dEditor RegID="codeEditor" 
code-ID="dEditor-dPage" sizerInfo="{'BorderSides': ['All'], 'Proportion': 1, 
'HAlign': 'Left', 'VAlign': 'Top', 'Border': 0, 'Expand': True}" 
designerClass="controlMix"></dEditor>
                                                                                
                        </dSizer>

Modified: trunk/DaboDemo/Modules.py
===================================================================
--- trunk/DaboDemo/Modules.py   2006-10-30 22:18:27 UTC (rev 437)
+++ trunk/DaboDemo/Modules.py   2006-10-31 16:28:17 UTC (rev 438)
@@ -16,6 +16,13 @@
 #----------------------------------------------------------------------------
 """
 import os
+import sys
+import traceback
+import types
+import dabo
+dabo.ui.loadUI("wx")
+import dabo.dEvents as dEvents
+from dabo.dLocalize import _
 
 
 class ModuleDictWrapper:
@@ -35,26 +42,30 @@
        """Dynamically manages the original/modified versions of a demo
        module.
        """
+       modOrig = 0
+       modMod = 1
+       origDir = "samples"
+       modDir = "modified"
+
+
        def __init__(self, name):
                self.modActive = -1
                # Index used in self.modules for orig and modified versions
-               self.modOrig = 0
-               self.modMod = 1
                self.name = name
                #              (dict , source ,  filename , description   , 
error information )        
                #              (  0  ,   1    ,     2     ,      3        ,     
     4        )        
                self.modules = [[None,  ""    ,    ""     , "<original>"  ,     
   None],
                                [None,  ""    ,    ""     , "<modified>"  ,     
   None]]
                
-               fname = "samples/%s.py" % name
+               fname = "%s/%s.py" % (self.origDir, name)
                # load original module
                self.loadFromFile(fname, self.modOrig)
                self.setActive(self.modOrig)
 
                # load modified module (if one exists)
-               modName = "modified/%s.py" % name
+               modName = "%s/%s.py" % (self.modDir, name)
                if os.path.exists(modName):
-                       self.loadFromFile(modName, modMod)
+                       self.loadFromFile(modName, self.modMod)
 
 
        def loadFromFile(self, filename, modID):
@@ -77,7 +88,7 @@
                                code = compile(source, description, "exec")     
           
                                exec code in self.modules[modID][0]
                        except:
-                               #self.modules[modID][4] = 
DemoError(sys.exc_info())
+                               self.modules[modID][4] = 
DemoError(sys.exc_info())
                                self.modules[modID][0] = None
                        else:
                                self.modules[modID][4] = None
@@ -125,6 +136,35 @@
                return self.modules[self.modMod][1] != ""
 
 
+       def saveMod(self, code):
+               fname = self.modules[self.modMod][2]
+               if not fname:
+                       base = os.path.split(self.modules[self.modOrig][2])[-1]
+                       fname = self.modules[self.modMod][2] = 
os.path.join(self.modDir, base)
+               self.modules[self.modMod][1] = code
+               self.updateFile(self.modMod)
+               self.loadDict(self.modMod)
+       
+       
+       def getOrigDir(cls):
+               return cls.origDir
+       getOrigDir = classmethod(getOrigDir)
+       
+               
+       def getModDir(cls):
+               return cls.modDir
+       getModDir = classmethod(getModDir)
+       
+       
+       def deleteModified(self):
+               fname = self.modules[self.modMod][2]
+               if not fname:
+                       #nothing to delete!
+                       return
+               self.modules[self.modMod][1] = ""
+               os.remove(fname)
+
+               
        def updateFile(self, modID=None):
                """Updates the file from which a module was loaded
                with (possibly updated) source
@@ -133,7 +173,6 @@
                        modID = self.modActive
                source = self.modules[modID][1]
                filename = self.modules[modID][2]
-
                try:            
                        file = open(filename, "wt")
                        file.write(source)
@@ -147,3 +186,114 @@
                self.modules[modID][0] = None
                self.modules[modID][1] = ""
                self.modules[modID][2] = ""
+
+#---------------------------------------------------------------------------
+
+class DemoError:
+    """Wraps and stores information about the current exception"""
+    def __init__(self, exc_info):
+        import copy
+        
+        excType, excValue = exc_info[:2]
+        # traceback list entries: (filename, line number, function name, text)
+        self.traceback = traceback.extract_tb(exc_info[2])
+
+        # --Based on traceback.py::format_exception_only()--
+        if type(excType) == types.ClassType:
+            self.exception_type = excType.__name__
+        else:
+            self.exception_type = excType
+
+        # If it's a syntax error, extra information needs
+        # to be added to the traceback
+        if excType is SyntaxError:
+            try:
+                msg, (filename, lineno, self.offset, line) = excValue
+            except:
+                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(dabo.ui.dPanel):
+       """Panel put into the demo tab when the demo fails to run due  to 
errors"""
+
+       def setErrorInfo(self, codePanel, demoError):
+               self.codePanel = codePanel
+               sz = self.Sizer = dabo.ui.dSizer("v")
+               lbl = dabo.ui.dLabel(self, Caption=_("An error has occurred 
while trying to run the demo"),
+                               ForeColor="red")
+               lbl.FontSize += 2
+               sz.append(lbl, halign="center", border=10)
+
+               bs = dabo.ui.dBorderSizer(self, "v", Caption=_("Exception 
Info"))
+               gs = dabo.ui.dGridSizer(MaxCols=2, HGap=5, VGap=2)
+               gs.append(dabo.ui.dLabel(self, Caption=_("Type:"), 
FontBold=True), halign="right")
+               gs.append(dabo.ui.dLabel(self, 
Caption=demoError.exception_type), halign="left")
+               gs.append(dabo.ui.dLabel(self, Caption=_("Details:"), 
FontBold=True), halign="right")
+               gs.append(dabo.ui.dLabel(self, 
Caption=demoError.exception_details), halign="left")
+               bs.append(gs, border=8)
+               sz.append(bs, halign="center", border=5)
+
+
+               lst = self.tbList = dabo.ui.dListControl(self, 
BorderStyle="sunken", 
+                               MultipleSelect=False)
+               lst.bindEvent(dEvents.MouseLeftDoubleClick, 
self.onListDoubleClick)
+               lst.addColumn(_("Filename"))
+               lst.addColumn(_("Line"))
+               lst.addColumn(_("Function"))
+               lst.addColumn(_("Code"))
+               self.insertTraceback(lst, demoError.traceback)
+               lst.autoSizeColumns((0,1,2))
+               
+               sz.appendSpacer(10)
+               sz.append(dabo.ui.dLabel(self, Caption=_("Traceback")))
+               sz.appendSpacer(5)
+               sz.append1x(lst, border=5)
+               lbl = dabo.ui.dLabel(self, Caption=_("""Entries from the demo 
module are shown in blue
+Double-click on them to go to the offending line"""))
+               sz.append(lbl, halign="center")
+               sz.appendSpacer(5)
+               self.layout()
+
+
+       def insertTraceback(self, lst, traceback):
+               #Add the traceback data
+               for tbNum in range(len(traceback)):
+                       data = traceback[tbNum]
+                       lst.append( (os.path.basename(data[0]), str(data[1]), 
str(data[2]), str(data[3])) )
+                       
+                       # Check whether this entry is from the demo module
+                       pth = os.path.split(data[0])[0]
+                       codeDirs = (DemoModules.getOrigDir(), 
DemoModules.getModDir())
+                       if pth in codeDirs:
+                               lst.setItemData(tbNum, int(data[1]))     # 
Store line number for easy access
+                               # Give it a blue colour
+                               lst.setItemForeColor(tbNum, "blue")
+                       else:
+                               lst.setItemData(tbNum, -1)              # 
Editor can't jump into this one's code
+
+
+       def onListDoubleClick(self, evt):
+               # If double-clicking on a demo's entry, jump to the line number
+               num = self.tbList.getItemData(self.tbList.PositionValue)
+               dabo.ui.callAfter(self.Form.showCode, num)
+               
+




_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/dabo-dev

Reply via email to