Changeset 328
- Timestamp:
- Thu Sep 13 20:49:59 2007
- Files:
-
- scripts/trunk/ORM/Install ORM Tables.py (modified) (diff)
- scripts/trunk/ORM/Open ORM Window.py (modified) (diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
scripts/trunk/ORM/Install ORM Tables.py
r326 r328 21 21 # Included draft of tables and objects 22 22 # 070807 - added object and report_object 23 # 070907 - more corrections and additions 23 24 24 25 # These design notes are intended to explore the problem. They include more than will be … … 30 31 31 32 # Report 32 # set it so that data.py won't manage the rows 33 # set it so that data.py won't manage the rows - done 32 33 33 # Row 34 # - PosX 34 # ReportRow - all diagram objects are represented as a report row 35 # - ID 36 # - ReportID 37 # - PosX # these refer to the center of the object (the target of arrows pointing to the object) 35 38 # - PosY 36 # - Moveable # can this object be moved with the mouse 37 # - FollowID # if this ID is moved, follow it 38 # - EndAID # this line connects these two objects, follow each end if it is moved 39 # - EndBID 39 # # this line connects these two objects, follow each end if it is moved 40 # - NodeAID # these are pointers to other ReportRow objects that are the ends of a connector 41 # - NodeBID 42 # - OffsetX # Text that is displayed offset from the main object (that text is separately moveable) 43 # - OffsetY # needed for role, probably not for reading 44 # - Moveable # can this object be moved with the mouse - is this needed???? 45 # - FollowID # if this ID is moved, follow it - is this needed? - maybe - for reading? 40 46 41 47 # ORMObject … … 51 57 52 58 rt = { 'Name': 'ORM Diagram', 'TableA': 'ORMObject', 'TableB': None, 'Also': None, 'AllOrEach': 'each', 53 'SuggestedColumns': ',ID;,Name' } 59 'SuggestedColumns': ',ID;,Name', 'AdjustRowOption': 'ORMDiagram' } 53 59 ct = [ 54 60 { 'Name': 'ID', 'Label': None, 'DataType': 'i', 'AccessType': 'd', 'T': 'A', 'Edit': False, 'Width': 35 }, … … 78 84 # - ID 79 85 # - ProjectID (Schema) 80 # - Nary (2 ..) 81 # - ReadingID 82 # - ReadingAlternateID 86 # - Nary (1 ..) 87 # - ORMReadingID # prefered reading 88 # - ORMReadingAltID # do I need this???? 83 89 # - Derived [None, '*', '+'] 84 90 # - DerivationRule … … 100 106 Data.AddReportType(rt, ct) 101 107 102 # ORMReading (follows the fact, but has it's own X&Y 108 # ORMReading (follows the fact, but has it's own X&Y) 102 108 # - ID 103 109 # - ProjectID (Schema) 104 110 # - ORMFactID 105 # - Reading 111 # - Reading (reading text refers to role ids??) 105 111 106 112 rt = { 'Name': 'ORM Reading', 'TableA': 'ORMReading', 'TableB': None, 'Also': None, 'AllOrEach': 'each', … … 121 127 # - ID 122 128 # - ProjectID (Schema) 129 # - ORMFactID - NodeA in the report row 130 # - ORMObjectID - NodeB in the report row 131 # - Seq = sequence number - this identifies the position of the role in the fact 123 132 # - Name 124 133 # - Mandatory ['a', 'd'] … … 131 140 { 'Name': 'Project/Name', 'Label': 'Project\nName', 'DataType': 't', 'AccessType': 'i', 'T': 'A', 'Edit': False, 'Width': 100 }, 132 141 { 'Name': 'ID', 'Label': None, 'DataType': 'i', 'AccessType': 'd', 'T': 'A', 'Edit': False, 'Width': 35 }, 133 { 'Name': 'ORMObjectID', 'Label': None, 'DataType': 'i', 'AccessType': 'd', 'T': 'A', 'Edit': True, 'Width': 100 },134 142 { 'Name': 'ORMFactID', 'Label': None, 'DataType': 'i', 'AccessType': 'd', 'T': 'A', 'Edit': True, 'Width': 100 }, 143 { 'Name': 'ORMObjectID', 'Label': None, 'DataType': 'i', 'AccessType': 'd', 'T': 'A', 'Edit': True, 'Width': 100 }, 135 144 { 'Name': 'Seq', 'Label': None, 'DataType': 'i', 'AccessType': 'd', 'T': 'A', 'Edit': True, 'Width': 100 }, 136 145 { 'Name': 'Name', 'Label': None, 'DataType': 't', 'AccessType': 'd', 'T': 'A', 'Edit': True, 'Width': 35 }, 146 { 'Name': 'Mandatory', 'Label': None, 'DataType': 't', 'AccessType': 'd', 'T': 'A', 'Edit': True, 'Width': 35 }, 147 { 'Name': 'Unique', 'Label': None, 'DataType': 't', 'AccessType': 'd', 'T': 'A', 'Edit': True, 'Width': 35 }, 137 148 { 'Name': 'DateAdded', 'Label': 'Date\nAdded', 'DataType': 'd', 'AccessType': 'd', 'T': 'A', 'Edit': True, 'Width': 80 }, 138 149 ] … … 187 198 # - ID 188 199 # - ProjectID (Schema) 189 # - Note # notes are always at one end of the note connector 190 # - TableName - this is the what ganttpv points to any object 200 # - ORMNoteID # notes are always at one end of the note connector 201 # - TableName - this is the way ganttpv points to any object 191 202 # - TableID 192 203 204 rt = { 'Name': 'ORM Note Connectors', 'TableA': 'ORMNoteConnector', 'TableB': None, 'Also': None, 'AllOrEach': 'each', 205 'SuggestedColumns': ',ID;,ORMNoteID;,TableName;,TableID' } 206 ct = [ 207 { 'Name': 'ID', 'Label': None, 'DataType': 'i', 'AccessType': 'd', 'T': 'A', 'Edit': False, 'Width': 35 }, 208 { 'Name': 'ORMNoteID', 'Label': None, 'DataType': 'i', 'AccessType': 'd', 'T': 'A', 'Edit': True, 'Width': 55 }, 209 { 'Name': 'TableName', 'Label': None, 'DataType': 't', 'AccessType': 'd', 'T': 'A', 'Edit': True, 'Width': 100 }, 210 { 'Name': 'TableID', 'Label': None, 'DataType': 'i', 'AccessType': 'd', 'T': 'A', 'Edit': True, 'Width': 55 }, 211 ] 212 Data.AddReportType(rt, ct) 213 193 214 # -------------------------- 194 # ReportORMObject195 # - ORMObjectID # many may point to same196 # - ReportID197 # - PosX198 # - PosY199 215 200 216 ### instead of a report object, it might be better just to use the good old report row? -
scripts/trunk/ORM/Open ORM Window.py
r326 r328 2038 2038 object_id = Data.Update(model)['ID'] 2039 2039 2040 graphic = {'Table': 'ReportRow', 'ProjectID': projectid, 'ReportID': self.ReportID,2040 graphic = {'Table': 'ReportRow', 'ProjectID': projectid, 'ReportID': report_object.ID, 2040 2040 'TableName': object_type, 'TableID': object_id, 2041 2041 'PosX': x, 'PosY': y, … … 2055 2055 def AddConnectorToDiagram(report_object, object_type, nodea, nodeb): 2056 2056 ''' Add report row, add target object, connect to end objects''' 2057 if debug: print report_object2057 if debug: print 'adding %s to %s' % (object_type, report_object) 2057 2057 project = report_object.Get('Project') 2058 2058 projectid = project.ID … … 2062 2062 # I think that subtype is the only example of linking the same types to each other 2063 2063 model = {'Table': object_type, 'ProjectID': projectid, 'DateAdded': today} 2064 model[nodea.Ta rget.Table + 'ID'] = nodea.Target.ID2064 model[nodea.TableName + 'ID'] = nodea.TableID 2064 2064 if object_type == 'ORMSubtypeArrow': # what should this be called? 2065 model['ORMSubtypeID'] = nodeb.Target.ID 2065 model['ORMSubtypeID'] = nodeb.TableID 2066 elif object_type == 'ORMNoteConnector': # may connect to anything 2067 model['TableName'] = nodeb.TableName 2068 model['TableID'] = nodeb.TableID 2066 2069 else: 2067 model[nodeb.Ta rget.Table + 'ID'] = nodeb.Target.ID2070 model[nodeb.TableName + 'ID'] = nodeb.TableID 2067 2070 object_id = Data.Update(model)['ID'] 2068 2071 2069 graphic = {'Table': 'ReportRow', 'ProjectID': projectid, 'ReportID': self.ReportID,2072 graphic = {'Table': 'ReportRow', 'ProjectID': projectid, 'ReportID': report_object.ID, 2069 2072 'TableName': object_type, 'TableID': object_id, 2070 2073 'NodeAID': nodea.ID, 'NodeBID': nodeb.ID, # objects pointed to 2071 # 'PosX': x, 'PosY': y,2074 'PosX': -1, 'PosY': -1, 2071 2074 'DateAdded': today} 2072 2075 newrowid = Data.Update(graphic)['ID'] … … 2621 2624 wx.ScrolledWindow.__init__(self, parent, id, (0, 0), size=size, style=wx.SUNKEN_BORDER) 2622 2625 2623 self.leftClickType = 'ORMObject' 2626 self.leftClickType = 'ORMObject' # where to specify behaviors? 2623 2626 2624 2627 self.Report = report # report object 2625 self.ReportID = report.ID 2628 self.ReportID = report.ID # redundant - may remove 2625 2628 2626 2629 self.lines = [] … … 2663 2666 # wxCURSOR_PENCIL 2664 2667 # wxCURSOR_PAINT_BRUSH 2665 self.SetCursor(wx.StockCursor(wx.CURSOR_PENCIL)) 2668 # self.SetCursor(wx.StockCursor(wx.CURSOR_PENCIL)) 2665 2668 2666 2669 # -- code for popup menu on canvas??? -- This isn't working … … 2709 2712 # add some other items 2710 2713 menu.Append(self.popupID2, "Fact") 2711 menu.Append(self.popupID3, " Three")2714 menu.Append(self.popupID3, "Constraint - not implemented") 2711 2714 menu.Append(self.popupID4, "Four") 2712 menu.Append(self.popupID5, "Five") 2713 menu.Append(self.popupID6, "Six") 2715 menu.Append(self.popupID5, "Undo - not implemented") 2716 menu.Append(self.popupID6, "Redo - not implemented") 2714 2717 # make a submenu 2715 2718 sm = wx.Menu() … … 2727 2730 2728 2731 def OnPopupOne(self, event): 2729 self.AddNode('ORMNote', self.popupx, self.popupy) 2732 new_shape = self.AddNode('ORMNote', self.popupx, self.popupy) 2729 2732 Data.SetUndo('Add Note') 2733 id = self.shapexref[new_shape.ID] 2734 self.RedisplayID(id) 2730 2735 2731 2736 def OnPopupTwo(self, event): 2732 self.AddNode('ORMFact', self.popupx, self.popupy) 2737 new_shape = self.AddNode('ORMFact', self.popupx, self.popupy) 2732 2737 Data.SetUndo('Add Fact') 2738 id = self.shapexref[new_shape.ID] 2739 self.RedisplayID(id) 2733 2740 2734 2741 def OnPopupThree(self, event): … … 2774 2781 self.CreateNode(dc, shape) 2775 2782 dc.EndDrawing() 2783 return shape 2784 2785 def AddConnector(self, node_type, source, target): # create model and graphic objects 2786 shape = AddConnectorToDiagram(self.Report, node_type, source, target) 2787 dc = self.pdc 2788 dc.BeginDrawing() 2789 self.CreateNode(dc, shape) 2790 dc.EndDrawing() 2791 return shape 2776 2792 2777 2793 def CreateNode(self, dc, shape): # create graphics node for existing model object … … 2785 2801 # can't store in object, must be in the graphics window 2786 2802 self.shapexref[shape.ID] = id 2803 self.idxref[id] = shape 2787 2804 2788 2805 orm_object = shape.Get('Target') 2789 x = shape.PosX 2806 x = shape.PosX # treat this as the center of the shape 2789 2806 y = shape.PosY 2790 2807 … … 2796 2813 return 2797 2814 if orm_object.Table in ('ORMObject'): 2815 ## word = orm_object.Name or 'default name' 2816 ## name_w,name_h = self.GetFullTextExtent(word)[0:2] # pull out only w and h 2817 ## box_w = name_w + 6 2818 ## box_h = name_h + 6 2819 2820 # text = orm_object.Text or 'empty note' 2821 lines = [] 2798 2822 word = orm_object.Name or 'default name' 2799 name_w,name_h = self.GetFullTextExtent(word)[0:2] # pull out only w and h 2800 box_w = name_w + 6 2801 box_h = name_h + 6 2823 if orm_object.Independent: 2824 work += "!" 2825 if orm_object.Derived: 2826 work += orm_object.Derived 2827 lines.append(word) 2828 word = orm_object.RefMode or '' 2829 if word: 2830 word = '(' + word + ')' 2831 lines.append(word) 2832 2833 sizes = [ self.GetFullTextExtent(line)[0:2] for line in lines ] # pull out only w and h 2834 w = 5 2835 h = 0 2836 for line_w,line_h in sizes: 2837 w = max(w, line_w) 2838 h += line_h 2839 box_w = w + 8 2840 box_h = h + 6 2802 2841 2803 2842 if orm_object.Type == 'Entity': … … 2809 2848 dc.SetBrush(self.CachedBrush('White')) 2810 2849 if debug: print 'round rectangle dimensions',x, y, box_w, box_h 2811 dc.DrawRoundedRectangle(x,y,box_w,box_h,8) 2850 box_x = x - box_w/2 2851 box_y = y - box_h/2 2852 # dc.DrawRoundedRectangle(box_x,box_y,box_w,box_h,8) 2853 dc.DrawRoundedRectangle(box_x,box_y,box_w,box_h,6) 2812 2854 2813 2855 dc.SetFont(self.GetFont()) … … 2816 2858 dc.SetTextForeground('Black') 2817 2859 dc.SetTextBackground('White') 2818 dc.DrawText(word, x+3, y+3) 2860 dc.DrawText(lines[0], x - sizes[0][0]/2, box_y+3) # center text in box 2861 dc.DrawText(lines[1], x - sizes[1][0]/2, box_y+box_h/2+1) 2819 2862 2820 r = wx.Rect( x,y,box_w,box_h)2863 r = wx.Rect(box_x,box_y,box_w,box_h) 2820 2863 r.Inflate(pen.GetWidth(),pen.GetWidth()) 2821 2864 dc.SetIdBounds(id,r) … … 2886 2929 dc.SetIdBounds(id,r) 2887 2930 2931 elif orm_object.Table in ('ORMRole'): 2932 nodea = shape.Get('NodeA') 2933 nodeb = shape.Get('NodeB') 2934 2935 minx = min(nodea.PosX, nodeb.PosX) 2936 maxx = max(nodea.PosX, nodeb.PosX) 2937 miny = min(nodea.PosY, nodeb.PosY) 2938 maxy = max(nodea.PosY, nodeb.PosY) 2939 2940 box_w = maxx - minx + 6 2941 box_h = maxy - miny + 6 2942 2943 pen = self.CachedPen(1, 1, wx.SOLID) 2944 dc.SetPen(pen) 2945 dc.DrawLine(nodea.PosX,nodea.PosY,nodeb.PosX, nodeb.PosY) 2946 2947 # need to add logic to draw the role name 2948 2949 r = wx.Rect(minx,miny,box_w,box_h) 2950 r.Inflate(pen.GetWidth(),pen.GetWidth()) 2951 dc.SetIdBounds(id,r) 2952 2953 elif orm_object.Table in ('ORMNoteConnector'): 2954 nodea = shape.Get('NodeA') 2955 nodeb = shape.Get('NodeB') 2956 2957 minx = min(nodea.PosX, nodeb.PosX) 2958 maxx = max(nodea.PosX, nodeb.PosX) 2959 miny = min(nodea.PosY, nodeb.PosY) 2960 maxy = max(nodea.PosY, nodeb.PosY) 2961 2962 box_w = maxx - minx + 6 2963 box_h = maxy - miny + 6 2964 2965 pen = self.CachedPen(1, 1, wx.DOT) 2966 dc.SetPen(pen) 2967 dc.DrawLine(nodea.PosX,nodea.PosY,nodeb.PosX, nodeb.PosY) 2968 2969 r = wx.Rect(minx,miny,box_w,box_h) 2970 r.Inflate(pen.GetWidth(),pen.GetWidth()) 2971 dc.SetIdBounds(id,r) 2972 2888 2973 self.objids.append(id) 2889 2974 2975 def RedisplayID(self, id): 2976 r = self.pdc.GetIdBounds(id) 2977 r.Inflate(4,4) 2978 self.OffsetRect(r) 2979 self.RefreshRect(r, False) 2980 2981 def ConnectEm(self, source, target): 2982 if debug: print 'connecting', source.TableName, target.TableName 2983 if (source.TableName == 'ORMNote' 2984 and target.TableName in ('ORMObject', 'ORMFact')): 2985 new_shape = self.AddConnector('ORMNoteConnector', source, target) 2986 Data.SetUndo('Add Note Connector') 2987 elif (target.TableName == 'ORMNote' 2988 and source.TableName in ('ORMObject', 'ORMFact')): 2989 new_shape = self.AddConnector('ORMNoteConnector', target, source) 2990 Data.SetUndo('Add Note Connector') 2991 elif source.TableName == 'ORMObject' and target.TableName == 'ORMFact': 2992 new_shape = self.AddConnector('ORMRole', target, source) 2993 Data.SetUndo('Add Role Connector') 2994 elif source.TableName == 'ORMFact' and target.TableName == 'ORMObject': 2995 new_shape = self.AddConnector('ORMRole', source, target) 2996 Data.SetUndo('Add Role Connector') 2997 id = self.shapexref[new_shape.ID] 2998 self.RedisplayID(id) 2999 3000 2890 3001 def OnMouse(self, event): 2891 3002 global hitradius 2892 if 1: # if self.draw_mode:3003 if self.demo.draw_mode: # "demo" is a poor name, this is where the window global data is 2892 3003 if event.LeftDown(): # select object -> object potentially source of arrow 2893 3004 x,y = self.ConvertEventCoords(event) … … 2900 3011 self.dragid = id 2901 3012 self.lastpos = (event.GetX(),event.GetY()) 3013 if debug: print 'left clicked on', self.idxref.get(id) 2902 3014 break 2903 3015 else: # didn't click on any object 2904 self.AddNode(self.leftClickType, x, y) 3016 # add new object 3017 new_shape = self.AddNode(self.leftClickType, x, y) 3018 Data.SetUndo('Add %s' % self.leftClickType) 3019 # redisplay object?? 3020 id = self.shapexref[new_shape.ID] 3021 self.RedisplayID(id) 3022 # make object current selection 3023 self.dragid = id # remember start of drag 3024 self.lastpos = (event.GetX(),event.GetY()) # needed? 2905 3025 elif event.RightDown(): 2906 3026 x,y = self.ConvertEventCoords(event) … … 2919 3039 elif event.Dragging() or event.LeftUp(): 2920 3040 if self.dragid != -1: 2921 x,y = self.lastpos 2922 dx = event.GetX() - x 2923 dy = event.GetY() - y 2924 r = self.pdc.GetIdBounds(self.dragid) 2925 self.pdc.TranslateId(self.dragid, dx, dy) 2926 r2 = self.pdc.GetIdBounds(self.dragid) 2927 r = r.Union(r2) 2928 r.Inflate(4,4) 2929 self.OffsetRect(r) 2930 self.RefreshRect(r, False) 2931 self.lastpos = (event.GetX(),event.GetY()) 3041 pass 3042 ## x,y = self.lastpos 3043 ## dx = event.GetX() - x 3044 ## dy = event.GetY() - y 3045 ## r = self.pdc.GetIdBounds(self.dragid) 3046 ## self.pdc.TranslateId(self.dragid, dx, dy) 3047 ## r2 = self.pdc.GetIdBounds(self.dragid) 3048 ## r = r.Union(r2) 3049 ## r.Inflate(4,4) 3050 ## self.OffsetRect(r) 3051 ## self.RefreshRect(r, False) 3052 ## self.lastpos = (event.GetX(),event.GetY()) 2932 3053 if event.LeftUp(): 2933 self.dragid = -1 3054 # self.dragid = -1 2933 3054 # what did we release on? 2934 3055 x,y = self.ConvertEventCoords(event) 2935 3056 #l = self.pdc.FindObjectsByBBox(x, y) 2936 3057 l = self.pdc.FindObjects(x, y, hitradius) 2937 if l: # connect to this object (if legal) 2938 pass 2939 else: # create target object (if legal) 3058 if l: # connect to this object and maybe connection (if legal) 3059 target = self.idxref.get(l[0]) 3060 source = self.idxref.get(self.dragid) 3061 self.ConnectEm(source, target) 3062 else: # create target object and connection (if legal) 2940 3063 pass 3064 ## # add new object 3065 ## ll = self.AddNode(self.leftClickType, x, y) 3066 ## Data.SetUndo('Add %s' % self.leftClickType) 3067 ## # redisplay object?? 3068 ## r = self.pdc.GetIdBounds(self.shapexref[ll]) 3069 ## r.Inflate(4,4) 3070 ## self.OffsetRect(r) 3071 ## self.RefreshRect(r, False) 3072 ## # make object current selection 3073 ## self.dragid = id # remember start of draf 3074 ## self.lastpos = (event.GetX(),event.GetY()) 2941 3075 else: 2942 3076 if event.LeftDown(): … … 3045 3179 random.seed() 3046 3180 self.objids = [] 3047 self.shapexref = {} # xref between shapes and dc_ids 3181 self.shapexref = {} # xrefs between shapes and dc_ids 3182 self.idxref = {} # inverse of shapexref 3048 3183 self.boundsdict = {} 3049 3184 dc.BeginDrawing() … … 3189 3324 self.report_toolbar.SetToolBitmapSize((16, 16)) # change 3190 3325 # self.SetToolBar(self.report_toolbar) 3191 self.report_toolbar.AddLabelTool(ID.INSERT_ROW, _("Insert %s"), Menu.Bitmap("icons/Insert Row.bmp", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, _("Insert new %s"), _("Insert new %s below selection")) 3192 self.report_toolbar.AddLabelTool(ID.DUPLICATE_ROW, _("Duplicate %s"), Menu.Bitmap("icons/Duplicate.bmp", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, _("Duplicate %s"), _("Duplicate selected %s")) 3326 self.report_toolbar.AddLabelTool(ID.NORMAL, _("Normal Mode"), Menu.Bitmap("icons/Insert Row.bmp", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, _("Normal Mode"), _("Draging will move objects")) 3327 self.report_toolbar.AddLabelTool(ID.DRAW, _("Drawing Mode"), Menu.Bitmap("icons/Duplicate.bmp", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, _("Drawing Mode"), _("Draging will connect objects")) 3193 3328 self.report_toolbar.Realize() 3194 3329 … … 3209 3344 sc.Bind(wx.EVT_SPINCTRL,self.OnChange) 3210 3345 sc.Bind(wx.EVT_TEXT,self.OnChange) 3346 3347 wx.EVT_TOOL(self, ID.NORMAL,self.OnNormal) 3348 wx.EVT_TOOL(self, ID.DRAW,self.OnDraw) 3211 3349 3212 3350 def OnChange(self, event): … … 3214 3352 hitradius = self.sc.GetValue() 3215 3353 3354 def OnNormal(self, event): 3355 self.demo.draw_mode = False 3356 3357 def OnDraw(self, event): 3358 self.demo.draw_mode = True 3359 3216 3360 #--------------------------------------------------------------------------- 3217 3361 # BELOW HERE IT IS NOTEBOOK … … 3291 3435 wx.Frame.__init__(self, parent, title="FlatNotebook Demo", size=(800,600)) 3292 3436 self.log = log 3293 3437 self.draw_mode = False # used by canvas 3438 3294 3439 self._bShowImages = False 3295 3440 self._bVCStyle = False … … 3799 3944 pnl = wx.Panel(nb, wx.ID_ANY,size=(200,30)) 3800 3945 pnl2 = ControlPanel(pnl,wx.ID_ANY) 3946 pnl2.demo = self # so control panel can save data at application level 3801 3947 win = MyCanvas(pnl, wx.ID_ANY, log, report=report) 3948 win.demo = self # so canvas can save data at application level 3802 3949 sz = wx.BoxSizer(wx.VERTICAL) 3803 3950 sz.Add(pnl2,0,wx.EXPAND|wx.ALL,5) … … 3835 3982 pnl = wx.Panel(nb, wx.ID_ANY,size=(200,30)) 3836 3983 pnl2 = ControlPanel(pnl,wx.ID_ANY) 3984 pnl2.demo = self # so control panel can save data at application level 3837 3985 win = MyCanvas(pnl, wx.ID_ANY, log, report=report) 3986 win.demo = self # so canvas can save data at application level 3838 3987 sz = wx.BoxSizer(wx.VERTICAL) 3839 3988 sz.Add(pnl2,0,wx.EXPAND|wx.ALL,5)
