source: subversion/applications/routing/pyroute-dev/overlay.py @ 18446

Last change on this file since 18446 was 18446, checked in by buerste, 10 years ago

-adding/changing path to python binary
+encoding definition

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