]> git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/XmlResourceHandler.py
I think I found out how GTK+ want popup windows
[wxWidgets.git] / wxPython / demo / XmlResourceHandler.py
1
2 import wx
3 import wx.xrc as xrc
4
5 #----------------------------------------------------------------------
6
7 resourceText = r'''<?xml version="1.0"?>
8 <resource>
9
10 <!-- Notice that the class is NOT a standard wx class -->
11
12 <object class="MyCustomPanel" name="MyPanel">
13 <size>200,100</size>
14 <object class="wxStaticText" name="label1">
15 <label>This panel is a custom class derived from wx.Panel,\nand is loaded by a custom XmlResourceHandler.</label>
16 <pos>10,10</pos>
17 </object>
18 </object>
19 </resource>
20 '''
21
22 #----------------------------------------------------------------------
23
24 class MyCustomPanel(wx.Panel):
25 def __init__(self, parent, id, pos, size, style, name):
26 wx.Panel.__init__(self, parent, id, pos, size, style, name)
27
28 # This is the little bit of customization that we do for this
29 # silly example.
30 self.Bind(wx.EVT_SIZE, self.OnSize)
31 t = wx.StaticText(self, -1, "MyCustomPanel")
32 f = t.GetFont()
33 f.SetWeight(wx.BOLD)
34 f.SetPointSize(f.GetPointSize()+2)
35 t.SetFont(f)
36 self.t = t
37
38 def OnSize(self, evt):
39 sz = self.GetSize()
40 w, h = self.t.GetTextExtent(self.t.GetLabel())
41 self.t.SetPosition(((sz.width-w)/2, (sz.height-h)/2))
42
43
44 # To do it the more complex way, (see below) we need to write the
45 # class a little differently... This could obviously be done with a
46 # single class, but I wanted to make separate ones to make clear what
47 # the different requirements are.
48 class PreMyCustomPanel(wx.Panel):
49 def __init__(self):
50 p = wx.PrePanel()
51 self.PostCreate(p)
52
53 def Create(self, parent, id, pos, size, style, name):
54 wx.Panel.Create(self, parent, id, pos, size, style, name)
55 self.Bind(wx.EVT_SIZE, self.OnSize)
56 t = wx.StaticText(self, -1, "MyCustomPanel")
57 f = t.GetFont()
58 f.SetWeight(wx.BOLD)
59 f.SetPointSize(f.GetPointSize()+2)
60 t.SetFont(f)
61 self.t = t
62
63 def OnSize(self, evt):
64 sz = self.GetSize()
65 w, h = self.t.GetTextExtent(self.t.GetLabel())
66 self.t.SetPosition(((sz.width-w)/2, (sz.height-h)/2))
67
68 #----------------------------------------------------------------------
69
70 class MyCustomPanelXmlHandler(xrc.XmlResourceHandler):
71 def __init__(self):
72 xrc.XmlResourceHandler.__init__(self)
73 # Specify the styles recognized by objects of this type
74 self.AddStyle("wxNO_3D", wx.NO_3D);
75 self.AddStyle("wxTAB_TRAVERSAL", wx.TAB_TRAVERSAL);
76 self.AddStyle("wxWS_EX_VALIDATE_RECURSIVELY", wx.WS_EX_VALIDATE_RECURSIVELY);
77 self.AddStyle("wxCLIP_CHILDREN", wx.CLIP_CHILDREN);
78 self.AddWindowStyles();
79
80 # This method and the next one are required for XmlResourceHandlers
81 def CanHandle(self, node):
82 return self.IsOfClass(node, "MyCustomPanel")
83
84 def DoCreateResource(self):
85 # NOTE: wxWindows can be created in either a single-phase or
86 # in a two-phase way. Single phase is what you normally do,
87 # and two-phase creates the instnace first, and then later
88 # creates the actual window when the Create method is called.
89 # (In wxPython the first phase is done using the wxPre*
90 # function, for example, wxPreFrame, wxPrePanel, etc.)
91 #
92 # wxXmlResource supports either method, a premade instance can
93 # be created and populated by xrc using the appropriate
94 # LoadOn* method (such as LoadOnPanel) or xrc can create the
95 # instance too, using the Load* method. However this makes
96 # the handlers a bit more complex. If you can be sure that a
97 # particular class will never be loaded using a pre-existing
98 # instance, then you can make the handle much simpler. I'll
99 # show both methods below.
100
101 if 1:
102 # The simple method assumes that there is no existing
103 # instance. Be sure of that with an assert.
104 assert self.GetInstance() is None
105
106 # Now create the object
107 panel = MyCustomPanel(self.GetParentAsWindow(),
108 self.GetID(),
109 self.GetPosition(),
110 self.GetSize(),
111 self.GetStyle("style", wx.TAB_TRAVERSAL),
112 self.GetName()
113 )
114 else:
115 # When using the more complex (but more flexible) method
116 # the instance may already have been created, check for it
117 panel = self.GetInstance()
118 if panel is None:
119 # if not, then create the instance (but not the window)
120 panel = PreMyCustomPanel()
121
122 # Now call the panel's Create method to actually create the window
123 panel.Create(self.GetParentAsWindow(),
124 self.GetID(),
125 self.GetPosition(),
126 self.GetSize(),
127 self.GetStyle("style", wx.TAB_TRAVERSAL),
128 self.GetName()
129 )
130
131 # These two things should be done in either case:
132 # Set standard window attributes
133 self.SetupWindow(panel)
134 # Create any child windows of this node
135 self.CreateChildren(panel)
136
137 return panel
138
139
140 #----------------------------------------------------------------------
141
142
143 class TestPanel(wx.Panel):
144 def __init__(self, parent, log):
145 self.log = log
146 wx.Panel.__init__(self, parent, -1)
147
148 # make the components
149 label = wx.StaticText(self, -1, "The lower panel was built from this XML:")
150 label.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD))
151
152 text = wx.TextCtrl(self, -1, resourceText,
153 style=wx.TE_READONLY|wx.TE_MULTILINE)
154 text.SetInsertionPoint(0)
155
156 line = wx.StaticLine(self, -1)
157
158 # Load the resource
159 res = xrc.EmptyXmlResource()
160 res.InsertHandler(MyCustomPanelXmlHandler())
161 res.LoadFromString(resourceText)
162
163 # Now create a panel from the resource data
164 panel = res.LoadObject(self, "MyPanel", "MyCustomPanel")
165
166 # and do the layout
167 sizer = wx.BoxSizer(wx.VERTICAL)
168 sizer.Add(label, 0, wx.EXPAND|wx.TOP|wx.LEFT, 5)
169 sizer.Add(text, 1, wx.EXPAND|wx.ALL, 5)
170 sizer.Add(line, 0, wx.EXPAND)
171 sizer.Add(panel, 1, wx.EXPAND|wx.ALL, 5)
172
173 self.SetSizer(sizer)
174 self.SetAutoLayout(True)
175
176
177 #----------------------------------------------------------------------
178
179 def runTest(frame, nb, log):
180 win = TestPanel(nb, log)
181 return win
182
183 #----------------------------------------------------------------------
184
185
186
187 overview = """<html><body>
188 <h2><center>wx.XmlResourceHandler</center></h2>
189
190 Deriving a class from wx.XmlResourceHandler allows you to specify your
191 own classes in XRC resources, and your handler class will then be used
192 to create instances of that class when the resource is loaded.
193
194 </body></html>
195 """
196
197
198
199 if __name__ == '__main__':
200 import sys,os
201 import run
202 run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
203