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

Last change on this file since 8347 was 8347, checked in by ojw, 12 years ago

check everything shares the new name ;)

  • Property svn:executable set to *
File size: 6.4 KB
Line 
1#!/usr/bin/python
2#----------------------------------------------------------------------------
3# Rana main GUI.  Displays maps, for use on a mobile device
4#
5# Controls:
6#   * drag left/right along top of window to zoom in/out
7#   * drag the map to move around
8#   * click on the map for a position menu
9#       * set your own position, if the GPS didn't already do that
10#       * set that location as a destination
11#       * route to that point
12#   * click on the top-left of the window for the main menu
13#       * download routing data around your position
14#       * browse geoRSS, wikipedia, and OSM points of interest
15#       * select your mode of transport for routing
16#           * car, bike, foot currently supported
17#       * toggle whether the map is centred on your GPS position
18#----------------------------------------------------------------------------
19# Copyright 2007-2008, Oliver White
20#
21# This program is free software: you can redistribute it and/or modify
22# it under the terms of the GNU General Public License as published by
23# the Free Software Foundation, either version 3 of the License, or
24# (at your option) any later version.
25#
26# This program is distributed in the hope that it will be useful,
27# but WITHOUT ANY WARRANTY; without even the implied warranty of
28# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29# GNU General Public License for more details.
30#
31# You should have received a copy of the GNU General Public License
32# along with this program.  If not, see <http://www.gnu.org/licenses/>.
33#----------------------------------------------------------------------------
34import pygtk
35pygtk.require('2.0')
36import gobject
37import gtk
38import sys
39import cairo
40import os
41from math import sqrt
42from time import clock
43from gtk import gdk
44
45
46def update(mapWidget):
47  mapWidget.update();
48  return(True)
49
50class MapWidget(gtk.Widget):
51  __gsignals__ = { \
52    'realize': 'override',
53    'expose-event' : 'override',
54    'size-allocate': 'override',
55    'size-request': 'override'
56    }
57  def __init__(self):
58    gtk.Widget.__init__(self)
59    self.draw_gc = None
60    self.timer = gobject.timeout_add(100, update, self)
61    self.d = {} # List of data
62    self.m = {} # List of modules
63    self.loadModules('modules')
64   
65  def loadModules(self, module_path):
66    """Load all modules from the specified directory"""
67    sys.path.append(module_path)
68    print "importing modules:"
69    for f in os.listdir(module_path):
70      if(f[0:4] == 'mod_' and f[-3:] == '.py'):
71        name = f[4:-3]
72        filename = os.path.join(module_path, f[0:-3]) # with directory name, but without .py extension
73        a = __import__(filename)
74        self.m[name] = a.getModule(self.m,self.d)
75        print " * %s: %s" % (name, self.m[name].__doc__)
76   
77  def blankData(self):
78    self.d['ownpos'] = {'valid':False}
79    self.d['mode'] = 'cycle'
80    self.d['centred'] = False
81    self.d['logging'] = True
82 
83  def beforeDie(self):
84    print "Handling last few checks before we close"
85 
86  def update(self):
87    if(self.d.get("needRedraw", False)):
88      self.forceRedraw()
89
90  def mousedown(self,x,y):
91    pass
92   
93  def click(self, x, y):
94    print "Clicked %d,%d"%(x,y)
95     
96  def forceRedraw(self):
97    """Make the window trigger a draw event. 
98    TODO: consider replacing this if porting pyroute to another platform"""
99    self.d['needRedraw'] = False
100    try:
101      self.window.invalidate_rect((0,0,self.rect.width,self.rect.height),False)
102    except AttributeError:
103      pass
104   
105  def zoom(self,dx):
106    """Handle dragging left/right along top of the screen to zoom"""
107    pass
108
109  def handleDrag(self,x,y,dx,dy,startX,startY):
110    pass
111   
112
113  def draw(self, cr):
114    start = clock()
115    #proj = self.modules['projection']
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.