1 |
# Copyright (c) 2001, 2002 by Intevation GmbH |
# Copyright (c) 2001, 2002, 2003 by Intevation GmbH |
2 |
# Authors: |
# Authors: |
3 |
# Bernhard Herzog <[email protected]> |
# Bernhard Herzog <[email protected]> |
4 |
# |
# |
30 |
from Thuban.Model.label import ALIGN_CENTER, ALIGN_TOP, ALIGN_BOTTOM, \ |
from Thuban.Model.label import ALIGN_CENTER, ALIGN_TOP, ALIGN_BOTTOM, \ |
31 |
ALIGN_LEFT, ALIGN_RIGHT |
ALIGN_LEFT, ALIGN_RIGHT |
32 |
from Thuban.Lib.connector import Publisher |
from Thuban.Lib.connector import Publisher |
33 |
|
from Thuban.Model.color import Color |
34 |
|
|
35 |
from renderer import ScreenRenderer, PrinterRender |
from renderer import ScreenRenderer, PrinterRender |
36 |
|
|
280 |
# if the mouse is outside the window. |
# if the mouse is outside the window. |
281 |
self.current_position = None |
self.current_position = None |
282 |
|
|
|
# If true, OnIdle will call do_redraw to do the actual |
|
|
# redrawing. Set by OnPaint to avoid some unnecessary redraws. |
|
|
# To force a redraw call full_redraw(). |
|
|
self.redraw_on_idle = 0 |
|
|
|
|
283 |
# the bitmap serving as backing store |
# the bitmap serving as backing store |
284 |
self.bitmap = None |
self.bitmap = None |
285 |
|
|
299 |
EVT_MOTION(self, self.OnMotion) |
EVT_MOTION(self, self.OnMotion) |
300 |
EVT_LEAVE_WINDOW(self, self.OnLeaveWindow) |
EVT_LEAVE_WINDOW(self, self.OnLeaveWindow) |
301 |
wx.EVT_SIZE(self, self.OnSize) |
wx.EVT_SIZE(self, self.OnSize) |
|
wx.EVT_IDLE(self, self.OnIdle) |
|
302 |
|
|
303 |
def __del__(self): |
def __del__(self): |
304 |
wxWindow.__del__(self) |
wxWindow.__del__(self) |
307 |
def OnPaint(self, event): |
def OnPaint(self, event): |
308 |
dc = wxPaintDC(self) |
dc = wxPaintDC(self) |
309 |
if self.map is not None and self.map.HasLayers(): |
if self.map is not None and self.map.HasLayers(): |
310 |
# We have a non-empty map. Redraw it in idle time |
self.do_redraw() |
|
self.redraw_on_idle = 1 |
|
311 |
else: |
else: |
312 |
# If we've got no map or if the map is empty, simply clear |
# If we've got no map or if the map is empty, simply clear |
313 |
# the screen. |
# the screen. |
498 |
offx, offy = self.offset |
offx, offy = self.offset |
499 |
self.set_view_transform(self.scale, (offx + dx, offy + dy)) |
self.set_view_transform(self.scale, (offx + dx, offy + dy)) |
500 |
|
|
501 |
|
def SelectTool(self, tool): |
502 |
|
"""Make tool the active tool. |
503 |
|
|
504 |
|
The parameter should be an instance of Tool or None to indicate |
505 |
|
that no tool is active. |
506 |
|
""" |
507 |
|
self.tool = tool |
508 |
|
|
509 |
def ZoomInTool(self): |
def ZoomInTool(self): |
510 |
"""Start the zoom in tool""" |
"""Start the zoom in tool""" |
511 |
self.tool = ZoomInTool(self) |
self.SelectTool(ZoomInTool(self)) |
512 |
|
|
513 |
def ZoomOutTool(self): |
def ZoomOutTool(self): |
514 |
"""Start the zoom out tool""" |
"""Start the zoom out tool""" |
515 |
self.tool = ZoomOutTool(self) |
self.SelectTool(ZoomOutTool(self)) |
516 |
|
|
517 |
def PanTool(self): |
def PanTool(self): |
518 |
"""Start the pan tool""" |
"""Start the pan tool""" |
519 |
self.tool = PanTool(self) |
self.SelectTool(PanTool(self)) |
520 |
|
|
521 |
def IdentifyTool(self): |
def IdentifyTool(self): |
522 |
"""Start the identify tool""" |
"""Start the identify tool""" |
523 |
self.tool = IdentifyTool(self) |
self.SelectTool(IdentifyTool(self)) |
524 |
|
|
525 |
def LabelTool(self): |
def LabelTool(self): |
526 |
"""Start the label tool""" |
"""Start the label tool""" |
527 |
self.tool = LabelTool(self) |
self.SelectTool(LabelTool(self)) |
528 |
|
|
529 |
def CurrentTool(self): |
def CurrentTool(self): |
530 |
"""Return the name of the current tool or None if no tool is active""" |
"""Return the name of the current tool or None if no tool is active""" |
570 |
self.set_current_position(event) |
self.set_current_position(event) |
571 |
if self.dragging: |
if self.dragging: |
572 |
self.ReleaseMouse() |
self.ReleaseMouse() |
573 |
self.tool.Hide(self.drag_dc) |
try: |
574 |
self.tool.MouseUp(event) |
self.tool.Hide(self.drag_dc) |
575 |
self.drag_dc = None |
self.tool.MouseUp(event) |
576 |
self.dragging = 0 |
finally: |
577 |
|
self.drag_dc = None |
578 |
|
self.dragging = 0 |
579 |
|
|
580 |
def OnMotion(self, event): |
def OnMotion(self, event): |
581 |
self.set_current_position(event) |
self.set_current_position(event) |
587 |
def OnLeaveWindow(self, event): |
def OnLeaveWindow(self, event): |
588 |
self.set_current_position(None) |
self.set_current_position(None) |
589 |
|
|
|
def OnIdle(self, event): |
|
|
if self.redraw_on_idle: |
|
|
self.do_redraw() |
|
|
self.redraw_on_idle = 0 |
|
|
|
|
590 |
def OnSize(self, event): |
def OnSize(self, event): |
591 |
# the window's size has changed. We have to get a new bitmap. If |
# the window's size has changed. We have to get a new bitmap. If |
592 |
# we want to be clever we could try to get by without throwing |
# we want to be clever we could try to get by without throwing |
617 |
self.last_selected_layer = layer |
self.last_selected_layer = layer |
618 |
self.last_selected_shape = shape |
self.last_selected_shape = shape |
619 |
|
|
620 |
def unprojected_rect_around_point(self, x, y): |
def unprojected_rect_around_point(self, x, y, dist): |
621 |
"""return a rect a few pixels around (x, y) in unprojected corrdinates |
"""return a rect dist pixels around (x, y) in unprojected corrdinates |
622 |
|
|
623 |
The return value is a tuple (minx, miny, maxx, maxy) suitable a |
The return value is a tuple (minx, miny, maxx, maxy) suitable a |
624 |
parameter to a layer's ShapesInRegion method. |
parameter to a layer's ShapesInRegion method. |
632 |
xs = [] |
xs = [] |
633 |
ys = [] |
ys = [] |
634 |
for dx, dy in ((-1, -1), (1, -1), (1, 1), (-1, 1)): |
for dx, dy in ((-1, -1), (1, -1), (1, 1), (-1, 1)): |
635 |
px, py = self.win_to_proj(x + dx, y + dy) |
px, py = self.win_to_proj(x + dist * dx, y + dist * dy) |
636 |
if inverse: |
if inverse: |
637 |
px, py = inverse(px, py) |
px, py = inverse(px, py) |
638 |
xs.append(px) |
xs.append(px) |
661 |
scale = self.scale |
scale = self.scale |
662 |
offx, offy = self.offset |
offx, offy = self.offset |
663 |
|
|
|
box = self.unprojected_rect_around_point(px, py) |
|
|
|
|
664 |
if select_labels: |
if select_labels: |
665 |
labels = self.map.LabelLayer().Labels() |
labels = self.map.LabelLayer().Labels() |
666 |
|
|
707 |
if not layer.Visible(): |
if not layer.Visible(): |
708 |
continue |
continue |
709 |
|
|
710 |
filled = layer.fill is not None |
filled = layer.GetClassification().GetDefaultFill() \ |
711 |
stroked = layer.stroke is not None |
is not Color.None |
712 |
|
stroked = layer.GetClassification().GetDefaultLineColor() \ |
713 |
|
is not Color.None |
714 |
|
|
715 |
layer_proj = layer.projection |
layer_proj = layer.projection |
716 |
if layer_proj is not None: |
if layer_proj is not None: |
722 |
|
|
723 |
select_shape = -1 |
select_shape = -1 |
724 |
|
|
725 |
|
# Determine the ids of the shapes that overlap a tiny area |
726 |
|
# around the point. For layers containing points we have to |
727 |
|
# choose a larger size of the box we're testing agains so |
728 |
|
# that we take the size of the markers into account |
729 |
|
# FIXME: Once the markers are more flexible this part has to |
730 |
|
# become more flexible too, of course |
731 |
|
if shapetype == SHAPETYPE_POINT: |
732 |
|
box = self.unprojected_rect_around_point(px, py, 5) |
733 |
|
else: |
734 |
|
box = self.unprojected_rect_around_point(px, py, 1) |
735 |
shape_ids = layer.ShapesInRegion(box) |
shape_ids = layer.ShapesInRegion(box) |
736 |
shape_ids.reverse() |
shape_ids.reverse() |
737 |
|
|