source: subversion/applications/mobile/rana/gui.py @ 8435

Revision 8435, 6.1 KB checked in by ojw, 6 years ago (diff)

try using module path to import just by name

  • Property svn:executable set to *
Line 
1#!/usr/bin/python
2#----------------------------------------------------------------------------
3# Rana main GUI.  Displays maps, for use on a mobile device
4#
5# Controls:
6#   * click on the overlay text to change fields displayed
7#----------------------------------------------------------------------------
8# Copyright 2007-2008, Oliver White
9#
10# This program is free software: you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation, either version 3 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program.  If not, see <http://www.gnu.org/licenses/>.
22#----------------------------------------------------------------------------
23import pygtk
24pygtk.require('2.0')
25import gobject
26import gtk
27import sys
28import cairo
29import os
30from math import sqrt
31from time import clock
32from gtk import gdk
33
34
35def update(mapWidget):
36  mapWidget.update();
37  return(True)
38
39class MapWidget(gtk.Widget):
40  __gsignals__ = { \
41    'realize': 'override',
42    'expose-event' : 'override',
43    'size-allocate': 'override',
44    'size-request': 'override'
45    }
46  def __init__(self):
47    gtk.Widget.__init__(self)
48    self.draw_gc = None
49    self.timer = gobject.timeout_add(100, update, self)
50    self.d = {} # List of data
51    self.m = {} # List of modules
52    self.loadModules('modules')
53   
54  def loadModules(self, module_path):
55    """Load all modules from the specified directory"""
56    sys.path.append(module_path)
57    print "importing modules:"
58    for f in os.listdir(module_path):
59      if(f[0:4] == 'mod_' and f[-3:] == '.py'):
60        name = f[4:-3]
61        filename = "%s\\%s" % ( module_path, f[0:-3]) # with directory name, but without .py extension
62        a = __import__(f[0:-3])
63        self.m[name] = a.getModule(self.m,self.d)
64        print " * %s: %s" % (name, self.m[name].__doc__)
65
66  def beforeDie(self):
67    print "Shutting-down modules"
68    for m in self.m.values():
69      m.shutdown()
70 
71  def update(self):
72    for m in self.m.values():
73      m.update()
74    if(self.d.get("needRedraw", False)):
75      self.forceRedraw()
76
77  def mousedown(self,x,y):
78    pass
79   
80  def click(self, x, y):
81    m = self.m.get("clickHandler",None)
82    if(m != None):
83      m.handleClick(x,y)
84     
85  def forceRedraw(self):
86    """Make the window trigger a draw event. 
87    TODO: consider replacing this if porting pyroute to another platform"""
88    self.d['needRedraw'] = False
89    try:
90      self.window.invalidate_rect((0,0,self.rect.width,self.rect.height),False)
91    except AttributeError:
92      pass
93   
94  def zoom(self,dx):
95    """Handle dragging left/right along top of the screen to zoom"""
96    pass
97
98  def handleDrag(self,x,y,dx,dy,startX,startY):
99    pass
100   
101
102  def draw(self, cr):
103    start = clock()
104    for m in self.m.values():
105      m.beforeDraw()
106     
107    if(self.d.get('menu', None) != None):
108      for m in self.m.values():
109        m.drawMenu(cr)
110    else:
111      # TODO: make these different contexts
112      for m in self.m.values():
113        m.drawMap(cr)
114      for m in self.m.values():
115        m.drawMapOverlay(cr)
116
117    #print "Redraw took %1.2f ms" % (1000 * (clock() - start))
118   
119  def do_realize(self):
120    self.set_flags(self.flags() | gtk.REALIZED)
121    self.window = gdk.Window( \
122      self.get_parent_window(),
123      width = self.allocation.width,
124      height = self.allocation.height,
125      window_type = gdk.WINDOW_CHILD,
126      wclass = gdk.INPUT_OUTPUT,
127      event_mask = self.get_events() | gdk.EXPOSURE_MASK)
128    self.window.set_user_data(self)
129    self.style.attach(self.window)
130    self.style.set_background(self.window, gtk.STATE_NORMAL)
131    self.window.move_resize(*self.allocation)
132  def do_size_request(self, allocation):
133    pass
134  def do_size_allocate(self, allocation):
135    self.allocation = allocation
136    if self.flags() & gtk.REALIZED:
137      self.window.move_resize(*allocation)
138  def _expose_cairo(self, event, cr):
139    self.rect = self.allocation
140    self.d['viewport'] = (self.rect.x, self.rect.y, self.rect.width, self.rect.height)
141    #self.modules['projection'].setView( \
142    #  self.rect.x,
143    #  self.rect.y,
144    #  self.rect.width,
145    #  self.rect.height)
146    self.draw(cr)
147  def do_expose_event(self, event):
148    self.chain(event)
149    cr = self.window.cairo_create()
150    return self._expose_cairo(event, cr)
151
152class GuiBase:
153  """Wrapper class for a GUI interface"""
154  def __init__(self):
155    # Create the window
156    win = gtk.Window()
157    win.set_title('Rana')
158    win.connect('delete-event', gtk.main_quit)
159    win.resize(480,640)
160    win.move(50, gtk.gdk.screen_height() - 650)
161   
162    # Events
163    event_box = gtk.EventBox()
164    event_box.connect("button_press_event", lambda w,e: self.pressed(e))
165    event_box.connect("button_release_event", lambda w,e: self.released(e))
166    event_box.connect("motion_notify_event", lambda w,e: self.moved(e))
167    win.add(event_box)
168   
169    # Create the map
170    self.mapWidget = MapWidget()
171    event_box.add(self.mapWidget)
172   
173    # Finalise the window
174    win.show_all()
175    gtk.main()
176    self.mapWidget.beforeDie()
177   
178  def pressed(self, event):
179    self.dragstartx = event.x
180    self.dragstarty = event.y
181    #print dir(event)
182    #print "Pressed button %d at %1.0f, %1.0f" % (event.button, event.x, event.y)
183   
184    self.dragx = event.x
185    self.dragy = event.y
186    self.mapWidget.mousedown(event.x,event.y)
187   
188  def moved(self, event):
189    """Drag-handler"""
190
191    self.mapWidget.handleDrag( \
192      event.x,
193      event.y,
194      event.x - self.dragx, 
195      event.y - self.dragy,
196      self.dragstartx,
197      self.dragstarty)
198
199    self.dragx = event.x
200    self.dragy = event.y
201  def released(self, event):
202    dx = event.x - self.dragstartx
203    dy = event.y - self.dragstarty
204    distSq = dx * dx + dy * dy
205    if distSq < 4:
206      self.mapWidget.click(event.x, event.y)
207
208
209if __name__ == "__main__":
210  program = GuiBase()
211
212 
Note: See TracBrowser for help on using the repository browser.