/[ascend]/trunk/pygtk/canvas/blocklist.py
ViewVC logotype

Contents of /trunk/pygtk/canvas/blocklist.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1984 - (show annotations) (download) (as text)
Wed Jan 21 22:56:28 2009 UTC (13 years, 5 months ago) by jpye
File MIME type: text/x-python
File size: 10604 byte(s)
Added Library::loadString method for loading string modules.
First steps on 'run' command for canvas-based models.
Fixed bug with use of obrowser.
Minor correction to blocktypes.a4c.
1 #!/usr/bin/env python
2 from __future__ import with_statement
3 import os, sys
4
5 os.chdir(os.path.abspath(os.path.dirname(sys.argv[0])))
6
7 os.environ['ASCENDLIBRARY'] = "../../models"
8 os.environ['ASCENDSOLVERS'] = "../../solvers/qrslv"
9
10 if sys.platform.startswith("win"):
11 os.environ['PATH'] += ";..\.."
12 else:
13 os.environ['LD_LIBRARY_PATH'] = "../.."
14
15 sys.path.append("..")
16
17 #import gtkexcepthook
18
19 if sys.platform.startswith("win"):
20 # Fetchs gtk2 path from registry
21 import _winreg
22 import msvcrt
23 try:
24 k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, "Software\\GTK\\2.0")
25 except EnvironmentError:
26 # use TkInter to report the error :-)
27 from TkInter import *
28 root = Tk()
29 w = Label(root,"You must install the Gtk+ 2.2 Runtime Environment to run this program")
30 w.pack()
31 root.mainloop()
32 sys.exit(1)
33 else:
34 gtkdir = _winreg.QueryValueEx(k, "Path")
35 import os
36 # we must make sure the gtk2 path is the first thing in the path
37 # otherwise, we can get errors if the system finds other libs with
38 # the same name in the path...
39 os.environ['PATH'] = "%s/lib;%s/bin;" % (gtkdir[0], gtkdir[0]) + os.environ['PATH']
40
41 import ascpy
42
43 L = ascpy.Library()
44
45 # FIXME need to add way to add/remove modules from the Library?
46 L.load('test/canvas/blocktypes.a4c')
47
48 D = L.getAnnotationDatabase()
49
50 M = L.getModules()
51
52 blocktypes = set()
53
54 for m in M:
55 T = L.getModuleTypes(m)
56 for t in T:
57 # 'block' types must not be parametric, because they must be able to
58 # exist even without being connected, and parametric models impose
59 # restrictions on the use of ARE_THE_SAME and similar.
60 if t.hasParameters():
61 continue
62 x = D.getNotes(t,ascpy.SymChar("block"),ascpy.SymChar("SELF"))
63 if x:
64 blocktypes.add(t)
65
66 blocks = []
67
68 from blocktype import *
69 print "block types:"
70 if not blocktypes:
71 print "NONE FOUND"
72 for t in blocktypes:
73
74 b = BlockType(t,D)
75
76 blocks += [b]
77
78 # render icon table
79 import threading
80 import gtk
81 import os, os.path, re
82
83 import cairo
84
85 #gtk.gdk.threads_init()
86
87 class BlockIconView(gtk.IconView):
88 """
89 IconView containing the palette of BlockTypes available for use in the
90 canvas. The list of blocks is supplied currently as an initialisation
91 parameter, but it is intended that this would be dynamic in a final system.
92
93 It should be possible drag icons from the palette into the canvas, but
94 that is not yet implemented.
95 """
96 def __init__(self,blocks,app):
97 # the mode containing the icons themselves...
98 self.model = gtk.ListStore(str, gtk.gdk.Pixbuf)
99 self.app = app
100 self.otank = {}
101 #thread = threading.RLock()
102 n = 0
103 #with thread:
104 for b in blocks:
105 n += 1
106 pixbuf = b.get_icon(48,48)
107 iter = self.model.append([b.type.getName(), pixbuf])
108 path = self.model.get_path(iter)
109 self.otank[path] = b
110
111 gtk.IconView.__init__(self)
112 self.set_model(self.model)
113 self.set_text_column(0)
114 self.set_pixbuf_column(1)
115 self.set_columns(-1)
116 self.set_size_request(180,100)
117 self.connect("item-activated", self.item_activated)
118 self.connect("selection-changed", self.selection_changed)
119
120 def selection_changed(self,iconview):
121 s = self.get_selected_items()
122 if len(s)==1:
123 b = self.otank[s[0]]
124 self.app.set_placement_tool(b)
125
126 def item_activated(self,iconview, path):
127 self.app.set_placement_tool(self.otank[path])
128
129 from gaphas import GtkView, View
130 from gaphas.tool import HoverTool, PlacementTool, HandleTool, ToolChain
131 from gaphas.tool import LineSegmentTool
132 from gaphas.tool import Tool, ItemTool, RubberbandTool
133 from blockconnecttool import BlockConnectTool
134 from blockline import *
135 from blockitem import *
136 from contextmenutool import *
137 from connectortool import *
138 from blockcanvas import *
139 from panzoom import ZoomTool
140 #from panzoom import PanTool
141 from gaphas.tool import PanTool
142 from blockinstance import *
143
144 def BlockToolChain():
145 """
146 ToolChain for working with BlockCanvas, including several custom Tools.
147 """
148 chain = ToolChain()
149 chain.append(HoverTool())
150 chain.append(BlockConnectTool()) # for connect/disconnect of lines
151 chain.append(ConnectorTool()) # for creating new lines by drag from Port
152 chain.append(ContextMenuTool()) # right-click
153 chain.append(LineSegmentTool()) # for moving line 'elbows'
154 chain.append(ItemTool())
155 chain.append(PanTool())
156 chain.append(ZoomTool())
157 chain.append(RubberbandTool())
158 return chain
159
160 class app(gtk.Window):
161 def __init__(self):
162 """
163 Initialise the application -- create all the widgets, and populate
164 the icon palette.
165 TODO: separate the icon palette into a separate method.
166 """
167 self.status = gtk.Statusbar()
168
169 # the Gaphas canvas
170 canvas = BlockCanvas()
171
172 # the main window
173 gtk.Window.__init__(self)
174 self.set_title("ASCEND Blocks")
175 self.set_default_size(400, 500)
176 self.connect("destroy", gtk.main_quit)
177 self.connect("key-press-event", self.key_press_event)
178
179 windowicon = gtk.Image()
180 windowicon.set_from_file(os.path.join("../glade/ascend.svg"))
181 self.set_icon(windowicon.get_pixbuf())
182
183 # vbox containing the main view and the status bar at the bottom
184 vbox = gtk.VBox()
185
186 tb = gtk.Toolbar()
187 loadbutton = gtk.ToolButton(gtk.STOCK_OPEN)
188 loadbutton.connect("clicked",self.load_canvas)
189 tb.insert(loadbutton,0)
190 savebutton = gtk.ToolButton(gtk.STOCK_SAVE)
191 savebutton.connect("clicked",self.save_canvas)
192 tb.insert(savebutton,1)
193 debugbutton = gtk.ToolButton(gtk.STOCK_PROPERTIES)
194 debugbutton.set_label("Debug")
195 debugbutton.connect("clicked",self.debug_canvas)
196 tb.insert(debugbutton,2)
197 previewb = gtk.ToolButton(gtk.STOCK_PRINT_PREVIEW)
198 previewb.set_label("Preview")
199 previewb.connect("clicked",self.preview_canvas)
200 tb.insert(previewb,3)
201 runb = gtk.ToolButton(gtk.STOCK_EXECUTE)
202 runb.set_label("Run")
203 runb.connect("clicked",self.run_canvas)
204 tb.insert(runb,4)
205
206 vbox.pack_start(tb, True, True)
207
208 # hbox occupies top part of vbox, with icons on left & canvas on right.
209 paned = gtk.HPaned()
210
211 # the 'view' widget implemented by Gaphas
212 self.view = GtkView()
213 self.view.tool = BlockToolChain()
214
215 # table containing scrollbars and main canvas
216 t = gtk.Table(2,2)
217 self.view.canvas = canvas
218 self.view.zoom(1)
219 self.view.set_size_request(600, 500)
220 hs = gtk.HScrollbar(self.view.hadjustment)
221 vs = gtk.VScrollbar(self.view.vadjustment)
222 t.attach(self.view, 0, 1, 0, 1)
223 t.attach(hs, 0, 1, 1, 2, xoptions=gtk.FILL, yoptions=gtk.FILL)
224 t.attach(vs, 1, 2, 0, 1, xoptions=gtk.FILL, yoptions=gtk.FILL)
225
226 # a scrolling window to contain the icon palette
227 scroll = gtk.ScrolledWindow()
228 scroll.set_border_width(2)
229 scroll.set_shadow_type(gtk.SHADOW_ETCHED_IN)
230
231 scroll.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
232 # icon palette
233 self.blockiconview = BlockIconView(blocks, self)
234 scroll.add(self.blockiconview)
235
236 paned.pack1(scroll, True, True)
237 paned.pack2(t, True, True)
238 vbox.pack_start(paned, True, True)
239 vbox.pack_start(self.status, False, False)
240 self.add(vbox)
241 self.show_all()
242
243 # a message about the found blocks
244 self.status.push(0, "Found %d block types." % (len(blocks)))
245
246 def set_placement_tool(self,blocktype):
247 """
248 Prepare the canvas for drawing a block of the type selected in the
249 icon palette.
250 """
251 # TODO: add undo handler
252 label = blocktype.type.getName()
253 def my_block_factory():
254 def wrapper():
255 b = BlockInstance(blocktype)
256 bi = DefaultBlockItem(b)
257 self.view.canvas.add(bi)
258 return bi
259 return wrapper
260 self.view.tool.grab(PlacementTool(my_block_factory(), HandleTool(), 2))
261 self.status.push(0,"Selected '%s'..." % blocktype.type.getName())
262
263 def set_connector_tool(self):
264 """
265 Prepare the canvas for drawing a connecting line (note that one can
266 alternatively just drag from a port to another port).
267 """
268 def my_line_factory():
269 def wrapper():
270 l = BlockLine()
271 self.view.canvas.add(l)
272 return l
273 return wrapper
274 self.view.tool.grab(PlacementTool(my_line_factory(), HandleTool(), 1))
275
276 def key_press_event(self,widget,event):
277 """
278 Handle various application-level keypresses. Fall through if keypress
279 is not handled here; it might be picked up elsewhere.
280 """
281 # TODO: add undo handler
282 key = gtk.gdk.keyval_name(event.keyval)
283 if key == 'Delete' and self.view.focused_item:
284 self.view.canvas.remove(self.view.focused_item)
285 self.status.push(0,"Item deleted.")
286 elif key == 'l' or key == 'L':
287 self.set_connector_tool()
288 self.status.push(0,"Line draw mode...")
289 elif key == 'S' or key == 's':
290 self.save_canvas(None)
291 elif key == 'R' or key == 'r':
292 self.load_canvas(None)
293 elif key == 'V' or key == 'v':
294 self.preview_canvas(None)
295 elif key == 'X' or key == 'x':
296 self.run_canvas(None)
297
298
299 def debug_canvas(self,widget):
300 """
301 Display an 'object browser' to allow inspection of the objects
302 in the canvas.
303 """
304 import obrowser
305 b = obrowser.Browser("canvas",self.view.canvas, False)
306
307
308 def save_canvas(self,widget):
309 """
310 Save the canvas in 'pickle' format. Currently saves to a single
311 predefined file named 'test.a4b'.
312 """
313 import pickle as pickle
314 import gaphas.picklers
315 f = file("./test.a4b","w")
316 try:
317 pickle.dump(self.view.canvas,f)
318 except Exception,e:
319 print "ERROR:",str(e)
320 import obrowser
321 b = obrowser.Browser("canvas",self.view.canvas)
322 d = gtk.Dialog("Error",self,gtk.DIALOG_DESTROY_WITH_PARENT,
323 (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)
324 )
325 d.vbox.add(gtk.Label(str(e)))
326 d.show_all()
327 d.run()
328 d.hide()
329 finally:
330 f.close()
331 self.status.push(0,"Canvas saved...")
332
333 def load_canvas(self,widget):
334 """
335 Restore a saved canvas in 'pickle' format. Currently always uses the
336 default 'test.a4b' filename.
337 """
338 import pickle as pickle
339 import gaphas.picklers
340 f = file("./test.a4b","r")
341 try:
342 self.view.canvas = pickle.load(f)
343 #print "canvas = ",self.view.canvas.__class__
344 #print dir(self.view.canvas)
345 self.view.canvas.reattach_ascend(L,D)
346 self.view.canvas.update_now()
347 finally:
348 f.close()
349 self.status.push(0,"Canvas loaded...")
350
351 def preview_canvas(self,widget):
352 """
353 Output an ASCEND representation of the canvas on the commandline.
354 Under development.
355 """
356 print self.view.canvas
357
358 def run_canvas(self,widget):
359 """
360 Export canvas to ASCEND solver and attempt to solve, or at least to
361 to instantiate the model.
362 """
363 model = str(self.view.canvas)
364 print model
365 print "RUN NOT IMPLEMENTED"
366 L.loadString(model,"canvasmodel")
367 T = L.findType("canvasmodel")
368 M = T.getSimulation('canvassim')
369 M.setSolver(ascpy.Solver("QRSlv"))
370 M.solve(ascpy.Solver("QRSlv"),ascpy.SolverReporter())
371
372
373
374 a = app()
375 gtk.main()
376

Properties

Name Value
svn:executable *

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22