| 1 |
#!/usr/bin/env python |
| 2 |
# -*- coding: utf-8 -*- |
| 3 |
|
| 4 |
from gi.repository import GtkClutter, Clutter |
| 5 |
GtkClutter.init([]) # Must be initialized before importing those: |
| 6 |
from gi.repository import GObject, Gtk, Champlain, GtkChamplain |
| 7 |
|
| 8 |
from markers import create_marker_layer |
| 9 |
|
| 10 |
|
| 11 |
class LauncherGTK: |
| 12 |
|
| 13 |
def __init__(self): |
| 14 |
self.window = Gtk.Window() |
| 15 |
self.window.set_border_width(10) |
| 16 |
self.window.set_title("libchamplain Gtk+ demo (python introspection)") |
| 17 |
self.window.connect("destroy", Gtk.main_quit) |
| 18 |
|
| 19 |
vbox = Gtk.VBox(False, 10) |
| 20 |
|
| 21 |
embed = GtkChamplain.Embed() |
| 22 |
|
| 23 |
self.view = embed.get_view() |
| 24 |
self.view.set_reactive(True) |
| 25 |
self.view.connect('button-release-event', self.mouse_click_cb, |
| 26 |
self.view) |
| 27 |
|
| 28 |
self.view.set_property('kinetic-mode', True) |
| 29 |
self.view.set_property('zoom-level', 5) |
| 30 |
|
| 31 |
scale = Champlain.Scale() |
| 32 |
scale.connect_view(self.view) |
| 33 |
self.view.bin_layout_add(scale, Clutter.BinAlignment.START, |
| 34 |
Clutter.BinAlignment.END) |
| 35 |
|
| 36 |
license = self.view.get_license_actor() |
| 37 |
license.set_extra_text("Don't eat cereals with orange juice\nIt tastes bad") |
| 38 |
|
| 39 |
self.view.center_on(45.466, -73.75) |
| 40 |
|
| 41 |
self.layer = create_marker_layer(self.view) |
| 42 |
self.view.add_layer(self.layer) |
| 43 |
self.layer.hide_all_markers() |
| 44 |
|
| 45 |
self.path_layer = Champlain.PathLayer() |
| 46 |
# Cheap approx of Highway 10 |
| 47 |
self.add_node(self.path_layer, 45.4095, -73.3197) |
| 48 |
self.add_node(self.path_layer, 45.4104, -73.2846) |
| 49 |
self.add_node(self.path_layer, 45.4178, -73.2239) |
| 50 |
self.add_node(self.path_layer, 45.4176, -73.2181) |
| 51 |
self.add_node(self.path_layer, 45.4151, -73.2126) |
| 52 |
self.add_node(self.path_layer, 45.4016, -73.1926) |
| 53 |
self.add_node(self.path_layer, 45.3994, -73.1877) |
| 54 |
self.add_node(self.path_layer, 45.4000, -73.1815) |
| 55 |
self.add_node(self.path_layer, 45.4151, -73.1218) |
| 56 |
self.view.add_layer(self.path_layer) |
| 57 |
|
| 58 |
embed.set_size_request(640, 480) |
| 59 |
|
| 60 |
bbox = Gtk.HBox(False, 10) |
| 61 |
button = Gtk.Button(stock=Gtk.STOCK_ZOOM_IN) |
| 62 |
button.connect("clicked", self.zoom_in) |
| 63 |
bbox.add(button) |
| 64 |
|
| 65 |
button = Gtk.Button(stock=Gtk.STOCK_ZOOM_OUT) |
| 66 |
button.connect("clicked", self.zoom_out) |
| 67 |
bbox.add(button) |
| 68 |
|
| 69 |
button = Gtk.ToggleButton(label="Markers") |
| 70 |
button.set_active(False) |
| 71 |
button.connect("toggled", self.toggle_layer) |
| 72 |
bbox.add(button) |
| 73 |
|
| 74 |
combo = Gtk.ComboBox() |
| 75 |
map_source_factory = Champlain.MapSourceFactory.dup_default() |
| 76 |
liststore = Gtk.ListStore(str, str) |
| 77 |
for source in map_source_factory.get_registered(): |
| 78 |
liststore.append([source.get_id(), source.get_name()]) |
| 79 |
combo.set_model(liststore) |
| 80 |
cell = Gtk.CellRendererText() |
| 81 |
combo.pack_start(cell, False) |
| 82 |
combo.add_attribute(cell, 'text', 1) |
| 83 |
combo.connect("changed", self.map_source_changed) |
| 84 |
combo.set_active(0) |
| 85 |
bbox.add(combo) |
| 86 |
|
| 87 |
self.spinbutton = Gtk.SpinButton.new_with_range(0, 20, 1) |
| 88 |
self.spinbutton.connect("changed", self.zoom_changed) |
| 89 |
self.view.connect("notify::zoom-level", self.map_zoom_changed) |
| 90 |
self.spinbutton.set_value(5) |
| 91 |
bbox.add(self.spinbutton) |
| 92 |
|
| 93 |
button = Gtk.Image() |
| 94 |
self.view.connect("notify::state", self.view_state_changed, button) |
| 95 |
bbox.pack_end(button, False, False, 0) |
| 96 |
|
| 97 |
vbox.pack_start(bbox, expand=False, fill=False, padding=0) |
| 98 |
vbox.add(embed) |
| 99 |
|
| 100 |
self.window.add(vbox) |
| 101 |
|
| 102 |
self.window.show_all() |
| 103 |
|
| 104 |
def add_node(self, path_layer, lat, lon): |
| 105 |
coord = Champlain.Coordinate.new_full(lat, lon) |
| 106 |
path_layer.add_node(coord) |
| 107 |
|
| 108 |
def zoom_in(self, widget): |
| 109 |
self.view.zoom_in() |
| 110 |
|
| 111 |
def zoom_out(self, widget): |
| 112 |
self.view.zoom_out() |
| 113 |
|
| 114 |
def toggle_layer(self, widget): |
| 115 |
if widget.get_active(): |
| 116 |
self.path_layer.show() |
| 117 |
self.layer.animate_in_all_markers() |
| 118 |
else: |
| 119 |
self.path_layer.hide() |
| 120 |
self.layer.animate_out_all_markers() |
| 121 |
|
| 122 |
def mouse_click_cb(self, actor, event, view): |
| 123 |
x, y = event.x, event.y |
| 124 |
lat, lon = view.x_to_longitude(x), view.y_to_latitude(y) |
| 125 |
print "Mouse click at: %f %f" % (lon, lat) |
| 126 |
return True |
| 127 |
|
| 128 |
def zoom_changed(self, widget): |
| 129 |
self.view.set_property("zoom-level", self.spinbutton.get_value_as_int()) |
| 130 |
|
| 131 |
def map_source_changed(self, widget): |
| 132 |
model = widget.get_model() |
| 133 |
iter = widget.get_active_iter() |
| 134 |
id = model.get_value(iter, 0) |
| 135 |
map_source_factory = Champlain.MapSourceFactory.dup_default() |
| 136 |
source = map_source_factory.create_cached_source(id); |
| 137 |
self.view.set_property("map-source", source) |
| 138 |
|
| 139 |
def map_zoom_changed(self, widget, value): |
| 140 |
self.spinbutton.set_value(self.view.get_property("zoom-level")) |
| 141 |
|
| 142 |
def view_state_changed(self, view, paramspec, image): |
| 143 |
state = view.get_state() |
| 144 |
if state == Champlain.State.LOADING: |
| 145 |
image.set_from_stock(Gtk.STOCK_NETWORK, Gtk.IconSize.BUTTON) |
| 146 |
else: |
| 147 |
image.clear() |
| 148 |
|
| 149 |
|
| 150 |
if __name__ == "__main__": |
| 151 |
GObject.threads_init() |
| 152 |
LauncherGTK() |
| 153 |
Gtk.main() |