1.1 --- a/EventAggregatorSupport.py Sun Apr 10 23:52:35 2011 +0200
1.2 +++ b/EventAggregatorSupport.py Tue Apr 12 00:01:28 2011 +0200
1.3 @@ -105,6 +105,12 @@
1.4 else:
1.5 return cmp(x, y)
1.6
1.7 +def sign(x):
1.8 + if x < 0:
1.9 + return -1
1.10 + else:
1.11 + return 1
1.12 +
1.13 # Utility classes and associated functions.
1.14
1.15 class Form:
1.16 @@ -1782,6 +1788,61 @@
1.17 today = datetime.date.today()
1.18 return today.year
1.19
1.20 +# Location-related functions.
1.21 +
1.22 +class Reference:
1.23 +
1.24 + "A map reference."
1.25 +
1.26 + def __init__(self, degrees, minutes=0, seconds=0):
1.27 + self.degrees = degrees
1.28 + self.minutes = minutes
1.29 + self.seconds = seconds
1.30 +
1.31 + def __repr__(self):
1.32 + return "Reference(%d, %d, %d)" % (self.degrees, self.minutes, self.seconds)
1.33 +
1.34 + def __add__(self, other):
1.35 + if not isinstance(other, Reference):
1.36 + return NotImplemented
1.37 + else:
1.38 + s = sign(self.degrees)
1.39 + o = sign(other.degrees)
1.40 + carry, seconds = adc(s * self.seconds, o * other.seconds)
1.41 + carry, minutes = adc(s * self.minutes, o * other.minutes + carry)
1.42 + return Reference(self.degrees + other.degrees + carry, minutes, seconds)
1.43 +
1.44 + def __sub__(self, other):
1.45 + if not isinstance(other, Reference):
1.46 + return NotImplemented
1.47 + else:
1.48 + return self.__add__(Reference(-other.degrees, other.minutes, other.seconds))
1.49 +
1.50 + def to_degrees(self):
1.51 + return sign(self.degrees) * (abs(self.degrees) + self.minutes / 60.0 + self.seconds / 3600.0)
1.52 +
1.53 + def to_pixels(self, scale):
1.54 + return self.to_degrees() * scale
1.55 +
1.56 +def adc(x, y):
1.57 + result = x + y
1.58 + return divmod(result, 60)
1.59 +
1.60 +def getPositionForReference(latitude, longitude, map_y, map_x, map_x_scale, map_y_scale):
1.61 + return (longitude - map_x).to_pixels(map_x_scale), (latitude - map_y).to_pixels(map_y_scale)
1.62 +
1.63 +def getPositionForCentrePoint(position, map_x_scale, map_y_scale):
1.64 + x, y = position
1.65 + return x - map_x_scale / 2.0, y - map_y_scale / 2.0
1.66 +
1.67 +def getMapReference(value):
1.68 +
1.69 + "Return a map reference by parsing the given 'value'."
1.70 +
1.71 + return Reference(*map(float, value.split(":")))
1.72 +
1.73 +# vim: tabstop=4 expandtab shiftwidth=4
1.74 +
1.75 # User interface functions.
1.76
1.77 def getParameter(request, name, default=None):
2.1 --- a/css/event-aggregator.css Sun Apr 10 23:52:35 2011 +0200
2.2 +++ b/css/event-aggregator.css Tue Apr 12 00:01:28 2011 +0200
2.3 @@ -426,5 +426,20 @@
2.4 background-color: #fff;
2.5 }
2.6
2.7 +.event-map-description p {
2.8 + font-weight: bold;
2.9 + font-size: larger;
2.10 +}
2.11 +
2.12 +ul.event-map-description-events {
2.13 + list-style-type: none;
2.14 + padding: 0.25em;
2.15 +}
2.16 +
2.17 +ul.event-map-description-events li {
2.18 + text-align: left;
2.19 + padding: 0.25em 0 0.25em 0;
2.20 +}
2.21 +
2.22 /* vim: tabstop=4 expandtab shiftwidth=4
2.23 */
3.1 --- a/macros/EventAggregator.py Sun Apr 10 23:52:35 2011 +0200
3.2 +++ b/macros/EventAggregator.py Tue Apr 12 00:01:28 2011 +0200
3.3 @@ -1342,7 +1342,16 @@
3.4
3.5 if maps is not None and map_name is not None:
3.6 try:
3.7 - map_bottom_left, map_top_right, map_width, map_height, map_image = maps[map_name].split()
3.8 + map_details = maps[map_name].split()
3.9 +
3.10 + map_bottom_left_latitude, map_bottom_left_longitude, map_top_right_latitude, map_top_right_longitude = \
3.11 + map(getMapReference, map_details[:4])
3.12 + map_width, map_height = map(int, map_details[4:6])
3.13 + map_image = map_details[6]
3.14 +
3.15 + map_x_scale = map_width / (map_top_right_longitude - map_bottom_left_longitude).to_degrees()
3.16 + map_y_scale = map_height / (map_top_right_latitude - map_bottom_left_latitude).to_degrees()
3.17 +
3.18 except (KeyError, ValueError):
3.19 pass
3.20
3.21 @@ -1368,10 +1377,22 @@
3.22 _("You do not have read access to the locations page:"),
3.23 locations_page))
3.24
3.25 - # Attempt to show the image.
3.26 + # Attempt to show the map.
3.27
3.28 else:
3.29
3.30 + # Get events by position.
3.31 +
3.32 + events_by_location = {}
3.33 +
3.34 + for event in all_shown_events:
3.35 + event_details = event.getDetails()
3.36 +
3.37 + location = event_details.get("location")
3.38 + if not events_by_location.has_key(location):
3.39 + events_by_location[location] = []
3.40 + events_by_location[location].append(event)
3.41 +
3.42 # Get the map image URL.
3.43
3.44 map_image_url = AttachFile.getAttachUrl(maps_page, map_image, request)
3.45 @@ -1385,6 +1406,65 @@
3.46 escattr(map_width), escattr(map_height), map_image_url)
3.47 ))
3.48
3.49 + # Show the events in the map.
3.50 +
3.51 + for location, events in events_by_location.items():
3.52 +
3.53 + # Look up the position of a location using the locations page.
3.54 +
3.55 + latitude, longitude = None, None
3.56 +
3.57 + if location is not None:
3.58 + try:
3.59 + latitude, longitude = map(getMapReference, locations[location].split())
3.60 + except (KeyError, ValueError):
3.61 + pass
3.62 +
3.63 + # Skip unpositioned locations or events.
3.64 +
3.65 + if latitude is None or longitude is None:
3.66 + continue
3.67 +
3.68 + # Get the position and dimensions of the map marker.
3.69 + # NOTE: Use one degree as the marker size.
3.70 +
3.71 + marker_x, marker_y = getPositionForCentrePoint(
3.72 + getPositionForReference(latitude, longitude, map_bottom_left_latitude, map_bottom_left_longitude,
3.73 + map_x_scale, map_y_scale),
3.74 + map_x_scale, map_y_scale)
3.75 +
3.76 + # Put a marker on the map.
3.77 +
3.78 + output.append(fmt.div(on=1, css_class="event-map-label",
3.79 + style="left:%dpx; bottom:%dpx; min-width:%dpx; min-height:%dpx") % (
3.80 + marker_x, marker_y, map_x_scale, map_y_scale))
3.81 + output.append(fmt.div(on=1, css_class="event-map-details"))
3.82 + output.append(fmt.div(on=1, css_class="event-map-shadow"))
3.83 + output.append(fmt.div(on=1, css_class="event-map-description"))
3.84 +
3.85 + output.append(fmt.paragraph(on=1))
3.86 + output.append(fmt.text(location))
3.87 + output.append(fmt.paragraph(on=0))
3.88 +
3.89 + output.append(fmt.bullet_list(on=1, attr={"class" : "event-map-description-events"}))
3.90 +
3.91 + for event in events:
3.92 + event_page = event.getPage()
3.93 + event_summary = event.getSummary(parent_name)
3.94 +
3.95 + # Link to the page using the summary.
3.96 +
3.97 + output.append(fmt.listitem(on=1))
3.98 + output.append(event_page.linkToPage(request, event_summary))
3.99 + output.append(fmt.listitem(on=0))
3.100 +
3.101 + output.append(fmt.bullet_list(on=0))
3.102 +
3.103 + output.append(fmt.div(on=0))
3.104 + output.append(fmt.div(on=0))
3.105 + output.append(fmt.div(on=0))
3.106 + output.append(fmt.div(on=0))
3.107 +
3.108 # End of map view output.
3.109
3.110 output.append(fmt.div(on=0))