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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2008 - (hide annotations) (download) (as text)
Mon Apr 27 09:00:09 2009 UTC (11 years, 6 months ago) by jpye
File MIME type: text/x-python
File size: 11800 byte(s)
Fixed 'preview' window in canvas GUI.
Add missing link to libm and libdl in Linux.
1 jpye 1945 #!/usr/bin/env python
2 jpye 1935 from __future__ import with_statement
3 jpye 1937 import os, sys
4 jpye 1929
5 jpye 1940 os.chdir(os.path.abspath(os.path.dirname(sys.argv[0])))
6 jpye 1951
7 jpye 1937 os.environ['ASCENDLIBRARY'] = "../../models"
8 jpye 1984 os.environ['ASCENDSOLVERS'] = "../../solvers/qrslv"
9 jpye 1951
10     if sys.platform.startswith("win"):
11     os.environ['PATH'] += ";..\.."
12     else:
13     os.environ['LD_LIBRARY_PATH'] = "../.."
14    
15 jpye 1937 sys.path.append("..")
16    
17 jpye 1973 #import gtkexcepthook
18 jpye 1954
19 jpye 1929 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 jpye 1801 import ascpy
42    
43     L = ascpy.Library()
44    
45 jpye 1929 # FIXME need to add way to add/remove modules from the Library?
46     L.load('test/canvas/blocktypes.a4c')
47 jpye 1801
48     D = L.getAnnotationDatabase()
49    
50     M = L.getModules()
51    
52     blocktypes = set()
53    
54 jpye 1813 for m in M:
55     T = L.getModuleTypes(m)
56     for t in T:
57 jpye 1925 # '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 jpye 1893 continue
62 jpye 1925 x = D.getNotes(t,ascpy.SymChar("block"),ascpy.SymChar("SELF"))
63     if x:
64 jpye 1813 blocktypes.add(t)
65    
66 jpye 1935 blocks = []
67    
68 jpye 1945 from blocktype import *
69 jpye 1813 print "block types:"
70     if not blocktypes:
71     print "NONE FOUND"
72     for t in blocktypes:
73    
74 jpye 1945 b = BlockType(t,D)
75 jpye 1926
76 jpye 1935 blocks += [b]
77 jpye 1925
78 jpye 1935 # render icon table
79     import threading
80     import gtk
81     import os, os.path, re
82 jpye 1936
83     import cairo
84    
85 jpye 1951 #gtk.gdk.threads_init()
86 jpye 1935
87 jpye 1937 class BlockIconView(gtk.IconView):
88 jpye 1940 """
89 jpye 1945 IconView containing the palette of BlockTypes available for use in the
90 jpye 1940 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 jpye 1937 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 jpye 1951 #thread = threading.RLock()
102 jpye 1937 n = 0
103 jpye 1951 #with thread:
104     for b in blocks:
105     n += 1
106 jpye 1967 pixbuf = b.get_icon(48,48)
107 jpye 1951 iter = self.model.append([b.type.getName(), pixbuf])
108     path = self.model.get_path(iter)
109     self.otank[path] = b
110 jpye 1937
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 jpye 1940 def item_activated(self,iconview, path):
127     self.app.set_placement_tool(self.otank[path])
128    
129 jpye 1945 from gaphas import GtkView, View
130     from gaphas.tool import HoverTool, PlacementTool, HandleTool, ToolChain
131 jpye 1973 from gaphas.tool import LineSegmentTool
132 jpye 1971 from gaphas.tool import Tool, ItemTool, RubberbandTool
133 jpye 2004 from gaphas.painter import ItemPainter
134 jpye 1979 from blockconnecttool import BlockConnectTool
135     from blockline import *
136 jpye 1945 from blockitem import *
137     from contextmenutool import *
138 jpye 1943 from connectortool import *
139 jpye 1945 from blockcanvas import *
140 jpye 1997 #from panzoom import ZoomTool
141 jpye 1982 #from panzoom import PanTool
142 jpye 1997 from gaphas.tool import PanTool, ZoomTool
143 jpye 1945 from blockinstance import *
144 jpye 2005 import info
145 jpye 1943
146 jpye 1939 def BlockToolChain():
147 jpye 1942 """
148 jpye 1954 ToolChain for working with BlockCanvas, including several custom Tools.
149 jpye 1942 """
150     chain = ToolChain()
151     chain.append(HoverTool())
152 jpye 1979 chain.append(BlockConnectTool()) # for connect/disconnect of lines
153 jpye 1978 chain.append(ConnectorTool()) # for creating new lines by drag from Port
154     chain.append(ContextMenuTool()) # right-click
155     chain.append(LineSegmentTool()) # for moving line 'elbows'
156 jpye 1942 chain.append(ItemTool())
157 jpye 1984 chain.append(PanTool())
158 jpye 1942 chain.append(ZoomTool())
159     chain.append(RubberbandTool())
160     return chain
161 jpye 1939
162 jpye 1935 class app(gtk.Window):
163     def __init__(self):
164 jpye 1969 """
165     Initialise the application -- create all the widgets, and populate
166     the icon palette.
167     TODO: separate the icon palette into a separate method.
168     """
169 jpye 1937 self.status = gtk.Statusbar()
170 jpye 1936
171 jpye 1937 # the Gaphas canvas
172 jpye 1936 canvas = BlockCanvas()
173    
174 jpye 1937 # the main window
175 jpye 1935 gtk.Window.__init__(self)
176     self.set_title("ASCEND Blocks")
177     self.set_default_size(400, 500)
178     self.connect("destroy", gtk.main_quit)
179 jpye 1938 self.connect("key-press-event", self.key_press_event)
180 jpye 1935
181 jpye 1943 windowicon = gtk.Image()
182     windowicon.set_from_file(os.path.join("../glade/ascend.svg"))
183     self.set_icon(windowicon.get_pixbuf())
184    
185 jpye 1937 # vbox containing the main view and the status bar at the bottom
186 jpye 1935 vbox = gtk.VBox()
187    
188 jpye 1977 tb = gtk.Toolbar()
189 jpye 1967 loadbutton = gtk.ToolButton(gtk.STOCK_OPEN)
190     loadbutton.connect("clicked",self.load_canvas)
191     tb.insert(loadbutton,0)
192     savebutton = gtk.ToolButton(gtk.STOCK_SAVE)
193     savebutton.connect("clicked",self.save_canvas)
194     tb.insert(savebutton,1)
195 jpye 1963 debugbutton = gtk.ToolButton(gtk.STOCK_PROPERTIES)
196     debugbutton.set_label("Debug")
197     debugbutton.connect("clicked",self.debug_canvas)
198 jpye 1967 tb.insert(debugbutton,2)
199     previewb = gtk.ToolButton(gtk.STOCK_PRINT_PREVIEW)
200     previewb.set_label("Preview")
201     previewb.connect("clicked",self.preview_canvas)
202     tb.insert(previewb,3)
203 jpye 2004 exportbutton = gtk.ToolButton(gtk.STOCK_CONVERT)
204     exportbutton.set_label("Export SVG")
205     exportbutton.connect("clicked",self.export_svg)
206     tb.insert(exportbutton,2)
207 jpye 1982 runb = gtk.ToolButton(gtk.STOCK_EXECUTE)
208     runb.set_label("Run")
209     runb.connect("clicked",self.run_canvas)
210     tb.insert(runb,4)
211 jpye 1967
212 jpye 1963 vbox.pack_start(tb, True, True)
213    
214 jpye 1937 # hbox occupies top part of vbox, with icons on left & canvas on right.
215 jpye 1977 paned = gtk.HPaned()
216    
217 jpye 1937 # the 'view' widget implemented by Gaphas
218 jpye 1997 import gaphas.view
219 jpye 2004 #gaphas.view.DEBUG_DRAW_BOUNDING_BOX = True
220 jpye 1997 self.view = GtkView()
221 jpye 1939 self.view.tool = BlockToolChain()
222 jpye 1936
223 jpye 1937 # table containing scrollbars and main canvas
224 jpye 1936 t = gtk.Table(2,2)
225 jpye 1937 self.view.canvas = canvas
226     self.view.zoom(1)
227     self.view.set_size_request(600, 500)
228     hs = gtk.HScrollbar(self.view.hadjustment)
229     vs = gtk.VScrollbar(self.view.vadjustment)
230     t.attach(self.view, 0, 1, 0, 1)
231 jpye 1936 t.attach(hs, 0, 1, 1, 2, xoptions=gtk.FILL, yoptions=gtk.FILL)
232     t.attach(vs, 1, 2, 0, 1, xoptions=gtk.FILL, yoptions=gtk.FILL)
233    
234 jpye 1937 # a scrolling window to contain the icon palette
235     scroll = gtk.ScrolledWindow()
236     scroll.set_border_width(2)
237     scroll.set_shadow_type(gtk.SHADOW_ETCHED_IN)
238 jpye 1977
239 jpye 1937 scroll.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
240     # icon palette
241     self.blockiconview = BlockIconView(blocks, self)
242     scroll.add(self.blockiconview)
243    
244 jpye 1977 paned.pack1(scroll, True, True)
245     paned.pack2(t, True, True)
246     vbox.pack_start(paned, True, True)
247 jpye 1937 vbox.pack_start(self.status, False, False)
248 jpye 1935 self.add(vbox)
249     self.show_all()
250    
251 jpye 1937 # a message about the found blocks
252     self.status.push(0, "Found %d block types." % (len(blocks)))
253    
254 jpye 1945 def set_placement_tool(self,blocktype):
255 jpye 1969 """
256     Prepare the canvas for drawing a block of the type selected in the
257     icon palette.
258     """
259 jpye 1938 # TODO: add undo handler
260 jpye 1945 label = blocktype.type.getName()
261 jpye 1937 def my_block_factory():
262     def wrapper():
263 jpye 1945 b = BlockInstance(blocktype)
264     bi = DefaultBlockItem(b)
265     self.view.canvas.add(bi)
266     return bi
267 jpye 1937 return wrapper
268     self.view.tool.grab(PlacementTool(my_block_factory(), HandleTool(), 2))
269 jpye 1945 self.status.push(0,"Selected '%s'..." % blocktype.type.getName())
270 jpye 1938
271 jpye 1940 def set_connector_tool(self):
272 jpye 1969 """
273     Prepare the canvas for drawing a connecting line (note that one can
274     alternatively just drag from a port to another port).
275     """
276 jpye 1940 def my_line_factory():
277     def wrapper():
278 jpye 1979 l = BlockLine()
279 jpye 1940 self.view.canvas.add(l)
280     return l
281     return wrapper
282     self.view.tool.grab(PlacementTool(my_line_factory(), HandleTool(), 1))
283    
284 jpye 1938 def key_press_event(self,widget,event):
285 jpye 1969 """
286     Handle various application-level keypresses. Fall through if keypress
287     is not handled here; it might be picked up elsewhere.
288     """
289 jpye 1938 # TODO: add undo handler
290     key = gtk.gdk.keyval_name(event.keyval)
291     if key == 'Delete' and self.view.focused_item:
292     self.view.canvas.remove(self.view.focused_item)
293     self.status.push(0,"Item deleted.")
294 jpye 1940 elif key == 'l' or key == 'L':
295     self.set_connector_tool()
296     self.status.push(0,"Line draw mode...")
297 jpye 1954 elif key == 'S' or key == 's':
298 jpye 1967 self.save_canvas(None)
299 jpye 1954 elif key == 'R' or key == 'r':
300 jpye 1967 self.load_canvas(None)
301 jpye 1969 elif key == 'V' or key == 'v':
302     self.preview_canvas(None)
303 jpye 1984 elif key == 'X' or key == 'x':
304     self.run_canvas(None)
305 jpye 2004 elif key == 'G' or key == 'g':
306     self.export_svg(None)
307 jpye 1963
308 jpye 1967
309 jpye 1963 def debug_canvas(self,widget):
310 jpye 1969 """
311     Display an 'object browser' to allow inspection of the objects
312     in the canvas.
313     """
314 jpye 1963 import obrowser
315 jpye 1965 b = obrowser.Browser("canvas",self.view.canvas, False)
316 jpye 1967
317 jpye 1981
318 jpye 1967 def save_canvas(self,widget):
319 jpye 1969 """
320     Save the canvas in 'pickle' format. Currently saves to a single
321     predefined file named 'test.a4b'.
322     """
323 jpye 1967 import pickle as pickle
324     import gaphas.picklers
325     f = file("./test.a4b","w")
326     try:
327     pickle.dump(self.view.canvas,f)
328     except Exception,e:
329 jpye 1984 print "ERROR:",str(e)
330 jpye 1967 import obrowser
331     b = obrowser.Browser("canvas",self.view.canvas)
332     d = gtk.Dialog("Error",self,gtk.DIALOG_DESTROY_WITH_PARENT,
333     (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)
334     )
335     d.vbox.add(gtk.Label(str(e)))
336     d.show_all()
337     d.run()
338     d.hide()
339     finally:
340     f.close()
341     self.status.push(0,"Canvas saved...")
342    
343     def load_canvas(self,widget):
344 jpye 1969 """
345     Restore a saved canvas in 'pickle' format. Currently always uses the
346     default 'test.a4b' filename.
347     """
348 jpye 1967 import pickle as pickle
349     import gaphas.picklers
350     f = file("./test.a4b","r")
351     try:
352     self.view.canvas = pickle.load(f)
353 jpye 1973 #print "canvas = ",self.view.canvas.__class__
354     #print dir(self.view.canvas)
355 jpye 1967 self.view.canvas.reattach_ascend(L,D)
356     self.view.canvas.update_now()
357     finally:
358     f.close()
359 jpye 2004
360 jpye 1967 self.status.push(0,"Canvas loaded...")
361    
362     def preview_canvas(self,widget):
363 jpye 1969 """
364     Output an ASCEND representation of the canvas on the commandline.
365     Under development.
366     """
367 jpye 1982
368 jpye 2008 info.Info(self.view.parent.parent.parent.parent,str(self.view.canvas),"Canvas Preview").run()
369 jpye 2005
370 jpye 2004 def export_svg(self,widget):
371     svgview = View(self.view.canvas)
372     svgview.painter = ItemPainter()
373    
374     # Update bounding boxes with a temporaly CairoContext
375     # (used for stuff like calculating font metrics)
376     tmpsurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 0, 0)
377     tmpcr = cairo.Context(tmpsurface)
378     svgview.update_bounding_box(tmpcr)
379     tmpcr.show_page()
380     tmpsurface.flush()
381    
382     fn = 'demo.svg'
383     w, h = svgview.bounding_box.width, svgview.bounding_box.height
384     surface = cairo.SVGSurface(fn , w, h)
385     cr = cairo.Context(surface)
386     svgview.matrix.translate(-svgview.bounding_box.x, -svgview.bounding_box.y)
387     svgview.paint(cr)
388     cr.show_page()
389     surface.flush()
390     surface.finish()
391    
392     self.status.push(0,"Wrote SVG file '%s'." % fn)
393    
394 jpye 1982 def run_canvas(self,widget):
395     """
396     Export canvas to ASCEND solver and attempt to solve, or at least to
397     to instantiate the model.
398     """
399     model = str(self.view.canvas)
400     print model
401     print "RUN NOT IMPLEMENTED"
402 jpye 1984 L.loadString(model,"canvasmodel")
403 jpye 2005 print "STRING MODEL LOADED"
404 jpye 1984 T = L.findType("canvasmodel")
405     M = T.getSimulation('canvassim')
406     M.setSolver(ascpy.Solver("QRSlv"))
407     M.solve(ascpy.Solver("QRSlv"),ascpy.SolverReporter())
408 jpye 2004
409 jpye 1935 a = app()
410     gtk.main()
411    

Properties

Name Value
svn:executable *

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