source: subversion/applications/routing/pyroute/overlay.py @ 8327

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

return to map after downloading

File size: 15.1 KB
Line 
1import cairo
2import os
3from base import pyrouteModule
4from pyrouteMenu import *
5from menuIcons import menuIcons
6from overlayArea import overlayArea
7from colorsys import hsv_to_rgb
8import geometry
9
10class guiOverlay(pyrouteModule):
11    def __init__(self, modules):
12        pyrouteModule.__init__(self, modules)
13        self.modules = modules
14        self.icons = menuIcons()
15        self.menus = loadMenus('Menus')
16        self.dragbar = None
17        self.dragpos = 0
18
19    def fullscreen(self):
20        """Asks if the menu is fullscreen -- if it is, then the
21        map doesn't need to be drawn underneath"""
22        return(self.get('menu'))
23   
24    def handleDrag(self,dx,dy,startX,startY):
25      if(self.dragbar):
26        if(self.dragbar.contains(startX,startY)):
27          scale = -20.0 / float(self.rect.h)
28          self.dragpos = self.dragpos + dy * scale
29          if(self.dragpos < 0):
30            self.dragpos = 0
31          #print "Dragging %1.2f (by %1.2f * %1.2f)" % (self.dragpos, dy,scale)
32          return(True)
33      return(False)
34   
35    def handleClick(self,x,y):
36        """return 1 if click was handled"""
37        for cell in self.clickable:
38            if(cell.contains(x,y)):
39                if(cell.handleClick(x,y)):
40                    return(1)
41        if(self.fullscreen()):
42            return(1)
43        return(0)
44    def draw(self, cr, rect):
45        self.cr = cr
46        self.rect = overlayArea(cr,rect.x,rect.y,rect.width,rect.height,self.modules,self.icons)
47        nx = 3
48        ny = 4
49        self.clickable = []
50        self.cells = {}
51        rotate = (rect.width > rect.height)
52        if(not rotate):
53          dx = rect.width / nx
54          dy = rect.height / ny
55          for i in range(0,nx):
56              x1 = rect.x + i * dx
57              self.cells[i] = {}
58              for j in range(0,ny):
59                  y1 = rect.y + j * dy
60                  self.cells[i][j] = overlayArea(cr,x1,y1,dx,dy,self.modules, self.icons)
61                  self.clickable.append(self.cells[i][j])
62        else:
63          dy = rect.height / nx
64          dx = rect.width / ny
65          for i in range(0,nx):
66              y1 = rect.y + i * dy
67              self.cells[i] = {}
68              for j in range(0,ny):
69                  x1 = rect.x + j * dx
70                  self.cells[i][j] = overlayArea(cr,x1,y1,dx,dy,self.modules, self.icons)
71                  self.clickable.append(self.cells[i][j])
72         
73
74         
75        currentMenu = self.get('menu')
76        if(currentMenu):
77            self.drawMenu(currentMenu)
78        else:
79          self.mapOverlay()
80
81    def mapOverlay(self):
82      if(self.get("shaded")):
83        self.rect.fill(0,0,0,False,self.get("shade_amount",0.5))
84     
85      if(1):
86        self.cells[0][0].button("Menu",None,"hint")
87        self.cells[1][0].button("","zoom:out","zoom_out")
88        self.cells[2][0].button("","zoom:in","zoom_in")
89      else:
90              # Tickmark to show where the active button is
91              self.cr.set_line_width(2)
92              self.cr.set_dash((10,5), 0);
93              self.cr.set_source_rgba(0.4,0,0)
94              button = self.cells[0][0]
95              self.cr.move_to(button.xc(0.5),button.y2)
96              self.cr.line_to(button.x2,button.y2)
97              self.cr.line_to(button.x2,button.yc(0.5))
98              self.cr.stroke()
99   
100      # Make the buttons clickable
101      self.cells[0][0].setEvent("menu:main")
102     
103      # New-style zoom buttons on map: much smaller
104      if(0):
105        z1 = self.cells[2][0].copyself(0.5,0,1,0.5)
106        z2 = self.cells[2][0].copyself(0.5,0.5,1,1)
107        z1.button("ZOUT",None,None)
108        z2.button("ZIN",None,None)
109
110
111    def drawMenu(self, menu):
112      try:
113        self.genericMenu(self.menus[menu])
114        return
115      except KeyError:
116        menuName = 'menu_%s' % menu
117        try:
118          function = getattr(self, menuName)
119        except AttributeError:
120          print "Error: %s not defined" % menuName
121          self.set('menu','')
122          return
123        function()
124
125    def sketchOverlay(self):
126      colourMenu = self.cells[2][3]
127      r = float(self.get('sketch_r',0))
128      g = float(self.get('sketch_g',0))
129      b = float(self.get('sketch_b',0))
130      colourMenu.fill(r,g,b)
131      colourMenu.setEvent("menu:sketch_colour")
132      # TODO: all clickable places to global array/module
133         
134    def menu_gps(self):
135      self.backButton(0,0)
136     
137      selectLine = self.cells[0][1].copyAndExtendTo(self.cells[2][1])
138      selectLine.icon("3h")
139      mode = self.get("PositionMode")
140      self.cells[0][1].button( \
141        "GPSd",
142        "option:set:PositionMode:gpsd",
143        mode == 'gpsd' and 'selected' or 'unselected')
144      self.cells[1][1].button( \
145        "Manual",
146        "option:set:PositionMode:manual",
147        mode == 'manual' and 'selected' or 'unselected')
148      self.cells[2][1].button( \
149        "pos.txt",
150        "option:set:PositionMode:txt",
151        mode == 'txt' and 'selected' or 'unselected')
152     
153    def menu_download(self):
154      self.backButton(0,0)
155      self.cells[0][1].button('Routes', 'menu:download_data', None)
156      self.cells[1][1].button('Tiles', 'menu:download_tiles', None)
157      self.cells[2][1].button('POI', None, None)
158
159    def menu_download_data(self):
160      self.backButton(0,0)
161
162
163      distanceLine = self.cells[0][2].copyAndExtendTo(self.cells[2][2])
164      distanceLine.icon("3h")
165     
166      self.cells[0][2].button( \
167        "20km",
168        "option:set:DownloadRange:20",
169        self.get('DownloadRange') == '20' and 'selected' or 'unselected')
170      self.cells[1][2].button( \
171        "100km",
172        "option:set:DownloadRange:100",
173        self.get('DownloadRange') == '100' and 'selected' or 'unselected')
174      self.cells[2][2].button( \
175        "500km",
176        "option:set:DownloadRange:500",
177        self.get('DownloadRange') == '500' and 'selected' or 'unselected')
178     
179      self.cells[2][3].button("Go","+download:","download")
180
181    def menu_download_tiles(self):
182      self.backButton(0,0)
183     
184
185      distanceLine = self.cells[0][1].copyAndExtendTo(self.cells[2][1])
186      distanceLine.icon("3h")
187     
188      self.cells[0][1].button( \
189        "20km",
190        "option:set:DownloadRange:20",
191        self.get('DownloadRange') == '20' and 'selected' or 'unselected')
192      self.cells[1][1].button( \
193        "100km",
194        "option:set:DownloadRange:70",
195        self.get('DownloadRange') == '70' and 'selected' or 'unselected')
196      self.cells[2][1].button( \
197        "500km",
198        "option:set:DownloadRange:150",
199        self.get('DownloadRange') == '150' and 'selected' or 'unselected')
200           
201      centreLine = self.cells[0][2].copyAndExtendTo(self.cells[2][2])
202      centreLine.icon("3h")
203     
204      self.cells[0][2].button( \
205        "Around me",
206        "option:set:DownloadCentre:pos",
207        self.get('DownloadCentre') == 'pos' and 'selected' or 'unselected')
208      self.cells[1][2].button( \
209        "Around route",
210        "option:set:DownloadCentre:route",
211        self.get('DownloadCentre') == 'route' and 'selected' or 'unselected')
212      self.cells[2][2].button( \
213        "Destination",
214        "option:set:DownloadCentre:dest",
215        self.get('DownloadCentre') == 'dest' and 'selected' or 'unselected')
216       
217      detailLine = self.cells[0][3].copyAndExtendTo(self.cells[1][3])
218      detailLine.icon("2h")
219     
220      self.cells[0][3].button( \
221        "This zoom",
222        "option:set:DownloadDetail:selected",
223        self.get('DownloadDetail') == 'selected' and 'selected' or 'unselected')
224      self.cells[1][3].button( \
225        "All zoom",
226        "option:set:DownloadDetail:all",
227        self.get('DownloadDetail') == 'all' and 'selected' or 'unselected')
228     
229      self.cells[2][3].button("Go","+download_tiles:","download")
230
231
232    def menu_sketch_colour(self):
233      self.backButton(0,0)
234      self.colourMenu(1,0, 0,1,0, 'sketch')
235      self.colourMenu(2,0, 0,0,1, 'sketch')
236      self.colourMenu(0,1, 1,1,0, 'sketch')
237      self.colourMenu(1,1, 0,1,1, 'sketch')
238      self.colourMenu(2,1, 1,0,1, 'sketch')
239      self.colourMenu(0,2, 1,0,0, 'sketch')
240      self.colourMenu(1,2, 0,0,0, 'sketch')
241      self.colourMenu(2,2, 1,1,1, 'sketch')
242     
243    def colourMenu(self,x,y,r,g,b,use):
244      self.cells[x][y].fill(r,g,b)
245      self.cells[x][y].setEvent("+set_colour:%s:%1.2f:%1.2f:%1.2f" % (use,r,g,b))
246     
247   
248    def backButton(self,i,j):
249        self.cells[i][j].button("","menu:","up")
250    def genericMenu(self, menu):
251      for y in range(4):
252        for x in range(3):
253          item = menu["%d,%d"%(x,y)]
254          if item['name'] == 'Up':
255            self.backButton(x,y)
256          else:
257            self.cells[x][y].button(item['name'],item['action'],item['icon'])
258
259    def menu_feeds(self):
260      self.menu_list("rss")
261    def menu_geonames(self):
262      self.menu_list("geonames")
263    def menu_waypoints(self):
264      self.menu_list("waypoints")
265    def menu_poi(self):
266      self.menu_list("osm")
267     
268    def menu_list(self, module):
269      self.backButton(0,0)
270      selectedFeed = int(self.get('selectedFeed',0))
271      titlebar = self.rect.copyself(1.0/3.0,0,1,0.25)
272      line1, line2 = titlebar.ysplit(0.5)
273      back = line1.copyself(0,0,0.25,1)
274      next = line1.copyself(0.75,0,1,1)
275      back.button("","option:add:selectedFeed:-1","back")
276      next.button("","option:add:selectedFeed:1","next")
277      self.clickable.append(back)
278      self.clickable.append(next)
279
280      try:
281        group = self.modules['poi'][module].groups[selectedFeed]
282      except KeyError:
283        line2.drawText("\"%s\" not loaded"%module)
284        return
285      except IndexError:
286        line2.drawText("No such set #%d"%selectedFeed)
287        return
288       
289      group.sort(self.get('ownpos'))
290     
291      line1.copyself(0.28,0,0.73,1).drawText("Set %d of %d" % (selectedFeed + 1, len(self.modules['poi'][module].groups)))
292     
293      line2.drawText(group.name)
294      self.drawListableItem(group)
295     
296    def drawListableItem(self,group):
297      n = 9
298      offset = int(self.dragpos)
299      listrect = self.rect.ysplitn(0, 0.25, 1.0, 1, n)
300      ownpos = self.get('ownpos')
301     
302      self.dragbar = self.rect.copyself(0.0,0.25,0.88,1.0)
303     
304      listLen = group.numItems()
305      for i in range(0,n):
306       
307        itemNum = i + offset
308        if(itemNum >= listLen):
309          return
310
311        # Separate area
312        textarea, button = listrect[i].xsplit(0.88)
313        color, textarea = textarea.xsplit(0.025)
314       
315        # Pattern for the left hand side to show how far down the list
316        # we are - model it as a colour, where red is the top, and purple
317        # is bottom
318        h = float(itemNum) / float(listLen)
319        v = (((i + offset) % 2) == 0) and 1.0 or 0.95
320        r,g,b = hsv_to_rgb(h, 1, v)
321        color.fill(r,g,b)
322       
323        if(i > 0):
324          # Line between list items
325          self.cr.set_line_width(0.5)
326          self.cr.set_dash((2,2,2), 0);
327          self.cr.set_source_rgb(0,0,0)
328          self.cr.move_to(textarea.x1,textarea.y1)
329          self.cr.line_to(textarea.x2,textarea.y1)
330          self.cr.stroke()
331        try:
332          # Draw each item
333          label = group.getItemText(itemNum)
334          textarea.drawTextSomewhere(label, 0.1,0.1,0.9,0.5)
335         
336          action = None
337          if(group.isLocation(itemNum)):
338            location = group.getItemLatLon(itemNum)
339            subtitleText = self.formatPosition(location, ownpos)
340            action = "+route:%1.5f:%1.5f" % (location[0], location[1])
341          else:
342            subtitleText = group.getItemStatus(itemNum)
343            if(group.getItemClickable(itemNum)):
344              action = group.getItemAction(itemNum)
345          textarea.drawTextSomewhere(subtitleText, 0.1,0.6,0.9,0.9)
346         
347          if(action != None):
348            button.button("", action, "goto")
349            self.clickable.append(button)
350           
351        except IndexError:
352          pass
353       
354    def formatPosition(self,pos, ownPos = None):
355      if(ownPos and ownPos['valid']):
356        a = (ownPos['lat'], ownPos['lon'])
357        b = pos
358        return("%1.2fkm %s" % \
359          (geometry.distance(a,b),
360          geometry.compassPoint(geometry.bearing(a,b))))
361      else:
362        return("%f,%f" % (self.lat,self.lon))
363   
364    def menu_meta(self):
365      self.backButton(0,0)
366      self.drawListableItem(self.m["meta"])
367     
368    def menu_main(self):
369        self.backButton(0,0)
370        self.checkbox(2,0,"Sketch mode","sketch",True)
371
372        self.cells[0][1].button("View","menu:view","view")
373        self.cells[1][1].button("GPS","menu:gps","gps")
374        self.cells[2][1].button("Download","menu:download","download")
375
376        self.cells[0][2].button("Data","menu:data","data")
377        self.cells[1][2].button("","",None)
378        self.cells[1][2].button("","",None)
379
380        self.checkbox(0,3, "Centre me","centred")
381        #self.cells[1][3].button("Options","menu:options",None)
382        self.cells[1][3].button("Meta","menu:meta",None)
383        self.cells[2][3].button("Mode","menu:mode","mode")
384
385    def checkbox(self, x,y, label, setting, returnToMap = False):
386      button = self.cells[x][y]
387      button.icon("generic")
388      action = "option:toggle:%s" % setting
389      if(returnToMap):
390        action = "+" + action
391      button.button(label, action, self.get(setting) and "checked" or "unchecked")
392   
393    def menu_click(self):
394        self.backButton(0,0)
395       
396        latlonRect = self.rect.copyself(0.33,0,1,0.25)
397        latRect = latlonRect.copyself(0,0,1,0.5)
398        lonRect = latlonRect.copyself(0,0.5,1,1)
399       
400        lat,lon = self.get('clicked')
401       
402        NS = lat > 0 and 'N' or 'S'
403        EW = lon > 0 and 'E' or 'W'
404       
405        latRect.drawTextSomewhere('%1.4f %s' % (abs(lat), NS), 0.05, 0.05, 0.7, 0.95)
406        lonRect.drawTextSomewhere('%1.4f %s' % (abs(lon), EW), 0.3, 0.05, 0.95, 0.95)
407        #def drawTextSomewhere(self,text,px1,py1,px2,py2):
408        #innerBox = self.copyself(px1,py1,px2,py2)
409        #innerBox.drawText(text)
410   
411        #self.cells[1][0].button("(lat)",None,None)
412        #self.cells[2][0].button("(lon)",None,None)
413
414        self.cells[0][1].button("set pos","+ownpos:clicked","set_pos")
415        self.cells[1][1].button("route to","+route:clicked","route_to")
416        self.cells[2][1].button("direct to","+direct:clicked","direct_to")
417
418        self.cells[0][2].button("waypoint", "+add_waypoint:clicked", "bookmarks")
419        self.cells[1][2].button("extend route", "+extend:route:clicked", "extend_route")
420        self.cells[2][2].button("extend direct", "+extend:direct:clicked", "extend_direct")
421
422        self.cells[0][3].button("",None,None)
423        self.cells[1][3].button("",None,None)
424        self.cells[2][3].button("",None,None)
425
426    def menu_options(self):
427        view,scroll = self.rect.xsplit(0.8)
428        view.fill(1,0,0)
429        scroll.fill(0,1,0)
430        self.backButton(0,0)
431
432
433if __name__ == "__main__":
434    a = guiOverlay(None,None)
435    print dir(a)
Note: See TracBrowser for help on using the repository browser.