]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wxPython/lib/PyCrust/filling.py
f0f24eb952c1eaa6c722d1fa20583b3f45e8cfd7
[wxWidgets.git] / wxPython / wxPython / lib / PyCrust / filling.py
1 """PyCrust Filling is the gui tree control through which a user can navigate
2 the local namespace or any object."""
3
4 __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
5 __cvsid__ = "$Id$"
6 __date__ = "August 21, 2001"
7 __version__ = "$Revision$"[11:-2]
8
9 from wxPython.wx import *
10 from wxPython.stc import *
11 from version import VERSION
12 import inspect
13 import introspect
14 import keyword
15 import sys
16 import types
17
18
19 class FillingTree(wxTreeCtrl):
20 """PyCrust FillingTree based on wxTreeCtrl."""
21
22 name = 'PyCrust Filling Tree'
23 revision = __version__
24
25 def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
26 size=wxDefaultSize, style=wxTR_HAS_BUTTONS, \
27 rootObject=None, rootLabel=None, rootIsNamespace=0):
28 """Create a PyCrust FillingTree instance."""
29 wxTreeCtrl.__init__(self, parent, id, pos, size)
30 self.rootIsNamespace = rootIsNamespace
31 if not rootObject:
32 import __main__
33 rootObject = __main__
34 self.rootIsNamespace = 1
35 if not rootLabel: rootLabel = 'Ingredients'
36 rootData = wxTreeItemData(rootObject)
37 self.root = self.AddRoot(rootLabel, -1, -1, rootData)
38 self.SetItemHasChildren(self.root, self.hasChildren(self.root))
39 EVT_TREE_ITEM_EXPANDING(self, self.GetId(), self.OnItemExpanding)
40 EVT_TREE_ITEM_COLLAPSED(self, self.GetId(), self.OnItemCollapsed)
41 EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
42
43 def hasChildren(self, object):
44 """Return true if object has children."""
45 if self.getChildren(object):
46 return true
47 else:
48 return false
49
50 def getChildren(self, object):
51 """Return a dictionary with the attributes or contents of object."""
52 dict = {}
53 objtype = type(object)
54 if objtype is types.DictType:
55 dict = object
56 elif (objtype in (types.ClassType, types.InstanceType, \
57 types.ModuleType)) \
58 or hasattr(object, '__class__'):
59 for key in introspect.getAttributeNames(object):
60 # Believe it or not, some attributes can disappear, such as
61 # the exc_traceback attribute of the sys module. So this is
62 # nested in a try block.
63 try:
64 dict[key] = getattr(object, key)
65 except:
66 pass
67 return dict
68
69 def OnItemExpanding(self, event):
70 selection = event.GetItem()
71 if self.IsExpanded(selection):
72 return
73 object = self.GetPyData(selection)
74 children = self.getChildren(object)
75 if not children:
76 return
77 list = children.keys()
78 list.sort()
79 for item in list:
80 itemtext = str(item)
81 # Show string dictionary items with single quotes, except for
82 # the first level of items, if they represent a namespace.
83 if type(object) is types.DictType \
84 and type(item) is types.StringType \
85 and (selection != self.root \
86 or (selection == self.root and not self.rootIsNamespace)):
87 itemtext = repr(item)
88 child = self.AppendItem(selection, itemtext, -1, -1, \
89 wxTreeItemData(children[item]))
90 self.SetItemHasChildren(child, self.hasChildren(children[item]))
91
92 def OnItemCollapsed(self, event):
93 """Remove all children from the item."""
94 item = event.GetItem()
95 self.DeleteChildren(item)
96
97 def OnSelChanged(self, event):
98 item = event.GetItem()
99 if item == self.root:
100 self.setText('')
101 return
102 object = self.GetPyData(item)
103 text = ''
104 text += self.getFullName(item)
105 text += '\n\nType: ' + str(type(object))[7:-2]
106 value = str(object)
107 if type(object) is types.StringType:
108 value = repr(value)
109 text += '\n\nValue: ' + value
110 if type(object) is types.InstanceType:
111 try:
112 text += '\n\nClass Definition:\n\n' + \
113 inspect.getsource(object.__class__)
114 except:
115 try:
116 text += '\n\n"""' + inspect.getdoc(object).strip() + '"""'
117 except:
118 pass
119 else:
120 try:
121 text += '\n\nSource Code:\n\n' + \
122 inspect.getsource(object)
123 except:
124 try:
125 text += '\n\n"""' + inspect.getdoc(object).strip() + '"""'
126 except:
127 pass
128 self.setText(text)
129
130 def getFullName(self, item, partial=''):
131 """Return a syntactically proper name for item."""
132 parent = self.GetItemParent(item)
133 parentobject = self.GetPyData(parent)
134 name = self.GetItemText(item)
135 # Apply dictionary syntax to dictionary items, except the root
136 # and first level children of a namepace.
137 if type(parentobject) is types.DictType \
138 and ((item != self.root and parent != self.root) \
139 or (parent == self.root and not self.rootIsNamespace)):
140 name = '[' + name + ']'
141 # Apply dot syntax to multipart names.
142 if partial:
143 if partial[0] == '[':
144 name += partial
145 else:
146 name += '.' + partial
147 # Repeat for everything but the root item
148 # and first level children of a namespace.
149 if (item != self.root and parent != self.root) \
150 or (parent == self.root and not self.rootIsNamespace):
151 name = self.getFullName(parent, partial=name)
152 return name
153
154 def setText(self, text):
155 """Display information about the current selection."""
156
157 # This method will most likely be replaced by the enclosing app
158 # to do something more interesting, like write to a text control.
159 print text
160
161 def setStatusText(self, text):
162 """Display status information."""
163
164 # This method will most likely be replaced by the enclosing app
165 # to do something more interesting, like write to a status bar.
166 print text
167
168
169 if wxPlatform == '__WXMSW__':
170 faces = { 'times' : 'Times New Roman',
171 'mono' : 'Courier New',
172 'helv' : 'Lucida Console',
173 'lucida' : 'Lucida Console',
174 'other' : 'Comic Sans MS',
175 'size' : 10,
176 'lnsize' : 9,
177 'backcol': '#FFFFFF',
178 }
179 # Versions of wxPython prior to 2.3.2 had a sizing bug on Win platform.
180 # The font was 2 points too large. So we need to reduce the font size.
181 if ((wxMAJOR_VERSION, wxMINOR_VERSION) == (2, 3) and wxRELEASE_NUMBER < 2) \
182 or (wxMAJOR_VERSION <= 2 and wxMINOR_VERSION <= 2):
183 faces['size'] -= 2
184 faces['lnsize'] -= 2
185 else: # GTK
186 faces = { 'times' : 'Times',
187 'mono' : 'Courier',
188 'helv' : 'Helvetica',
189 'other' : 'new century schoolbook',
190 'size' : 12,
191 'lnsize' : 10,
192 'backcol': '#FFFFFF',
193 }
194
195
196 class FillingText(wxStyledTextCtrl):
197 """PyCrust FillingText based on wxStyledTextCtrl."""
198
199 name = 'PyCrust Filling Text'
200 revision = __version__
201
202 def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
203 size=wxDefaultSize, style=wxCLIP_CHILDREN):
204 """Create a PyCrust FillingText instance."""
205 wxStyledTextCtrl.__init__(self, parent, id, pos, size, style)
206 # Configure various defaults and user preferences.
207 self.config()
208
209 def config(self):
210 """Configure shell based on user preferences."""
211 self.SetMarginWidth(1, 0)
212
213 self.SetLexer(wxSTC_LEX_PYTHON)
214 self.SetKeyWords(0, ' '.join(keyword.kwlist))
215
216 self.setStyles(faces)
217 self.SetViewWhiteSpace(0)
218 self.SetTabWidth(4)
219 self.SetUseTabs(0)
220
221 def setStyles(self, faces):
222 """Configure font size, typeface and color for lexer."""
223
224 # Default style
225 self.StyleSetSpec(wxSTC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces)
226
227 self.StyleClearAll()
228
229 # Built in styles
230 self.StyleSetSpec(wxSTC_STYLE_LINENUMBER, "back:#C0C0C0,face:%(mono)s,size:%(lnsize)d" % faces)
231 self.StyleSetSpec(wxSTC_STYLE_CONTROLCHAR, "face:%(mono)s" % faces)
232 self.StyleSetSpec(wxSTC_STYLE_BRACELIGHT, "fore:#0000FF,back:#FFFF88")
233 self.StyleSetSpec(wxSTC_STYLE_BRACEBAD, "fore:#FF0000,back:#FFFF88")
234
235 # Python styles
236 self.StyleSetSpec(wxSTC_P_DEFAULT, "face:%(mono)s" % faces)
237 self.StyleSetSpec(wxSTC_P_COMMENTLINE, "fore:#007F00,face:%(mono)s" % faces)
238 self.StyleSetSpec(wxSTC_P_NUMBER, "")
239 self.StyleSetSpec(wxSTC_P_STRING, "fore:#7F007F,face:%(mono)s" % faces)
240 self.StyleSetSpec(wxSTC_P_CHARACTER, "fore:#7F007F,face:%(mono)s" % faces)
241 self.StyleSetSpec(wxSTC_P_WORD, "fore:#00007F,bold")
242 self.StyleSetSpec(wxSTC_P_TRIPLE, "fore:#7F0000")
243 self.StyleSetSpec(wxSTC_P_TRIPLEDOUBLE, "fore:#000033,back:#FFFFE8")
244 self.StyleSetSpec(wxSTC_P_CLASSNAME, "fore:#0000FF,bold")
245 self.StyleSetSpec(wxSTC_P_DEFNAME, "fore:#007F7F,bold")
246 self.StyleSetSpec(wxSTC_P_OPERATOR, "")
247 self.StyleSetSpec(wxSTC_P_IDENTIFIER, "")
248 self.StyleSetSpec(wxSTC_P_COMMENTBLOCK, "fore:#7F7F7F")
249 self.StyleSetSpec(wxSTC_P_STRINGEOL, "fore:#000000,face:%(mono)s,back:#E0C0E0,eolfilled" % faces)
250
251
252 class Filling(wxSplitterWindow):
253 """PyCrust Filling based on wxSplitterWindow."""
254
255 name = 'PyCrust Filling'
256 revision = __version__
257
258 def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
259 size=wxDefaultSize, style=wxSP_3D, name='Filling Window', \
260 rootObject=None, rootLabel=None, rootIsNamespace=0):
261 """Create a PyCrust Filling instance."""
262 wxSplitterWindow.__init__(self, parent, id, pos, size, style, name)
263 self.fillingTree = FillingTree(parent=self, rootObject=rootObject, \
264 rootLabel=rootLabel, \
265 rootIsNamespace=rootIsNamespace)
266 self.fillingText = FillingText(parent=self)
267 self.SplitVertically(self.fillingTree, self.fillingText, 200)
268 self.SetMinimumPaneSize(1)
269 # Override the filling so that descriptions go to fillingText.
270 self.fillingTree.setText = self.fillingText.SetText
271 # Select the root item.
272 self.fillingTree.SelectItem(self.fillingTree.root)
273
274
275 class FillingFrame(wxFrame):
276 """Frame containing the PyCrust filling, or namespace tree component."""
277
278 name = 'PyCrust Filling Frame'
279 revision = __version__
280
281 def __init__(self, parent=None, id=-1, title='PyFilling', \
282 pos=wxDefaultPosition, size=wxDefaultSize, \
283 style=wxDEFAULT_FRAME_STYLE, rootObject=None, \
284 rootLabel=None, rootIsNamespace=0):
285 """Create a PyCrust FillingFrame instance."""
286 wxFrame.__init__(self, parent, id, title, pos, size, style)
287 intro = 'Welcome To PyFilling - The Tastiest Namespace Inspector'
288 self.CreateStatusBar()
289 self.SetStatusText(intro)
290 if wxPlatform == '__WXMSW__':
291 icon = wxIcon('PyCrust.ico', wxBITMAP_TYPE_ICO)
292 self.SetIcon(icon)
293 self.filling = Filling(parent=self, rootObject=rootObject, \
294 rootLabel=rootLabel, \
295 rootIsNamespace=rootIsNamespace)
296 # Override the filling so that status messages go to the status bar.
297 self.filling.fillingTree.setStatusText = self.SetStatusText
298
299
300 class App(wxApp):
301 """PyFilling standalone application."""
302
303 def OnInit(self):
304 self.fillingFrame = FillingFrame()
305 self.fillingFrame.Show(true)
306 self.SetTopWindow(self.fillingFrame)
307 return true
308
309
310