############################################################################# ## This file is part of TunnelHack II. ## ##-------------------------------------------------------------------------## ## Copyright 2007-2008 Bryce Schroeder ## ## bryce.schroeder@gmail.com ## ## http://www.ferazelhosting.net/~bryce/ ## ##-------------------------------------------------------------------------## ## This program is free software: you can redistribute it and/or modify ## ## it under the terms of the GNU General Public License as published by ## ## the Free Software Foundation, either version 3 of the License, or ## ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## ## along with this program. If not, see . ## ############################################################################# from .interface import IObj, IExclusiveGroup, button from .g import g import pygame class IDraggable(IObj): """ This is a class for draggable objects. It is a thin wrapper for various draggable items that might be implemented. It needs a parameter source= in case the drag is rejected. If this is None, the dragged object will just disappear into the void! On the other hand, if you provide a link delivery_confirmation, it will will send a message to that receptor when the object is successfully dropped. The constructor requires a parameter draggable=, which is an object supporting the draggable interface. This consists of: * blit method, conformant to the one of the image object. * width and height methods that do what their names say :) """ def init(self): self.accept_events = False self.delivery_confirmation = self.p.get('delivery_confirmation',None) self.source = self.p.get('source', None) self.mouse_follow = ( -self.draggable.width() / 2, -self.draggable.height() / 2) if self.source: self.source.transition('unmouse') self.done = False def render_self(self, theme, target, px, py): self.draggable.blit(target, px, py) def compute_rect(self): self.draggable = self.p.draggable self.rect = pygame.rect.Rect( 0, 0, self.draggable.width(), self.draggable.height()) def was_dropped(self, target=None): """ The item was dropped over target. """ if target: self.end_drag(target) self.do_delivery_confirmation() else: self.return_to_sender() def end_drag(self, target=None): self.window_manager.end_drag(target) self.done = True def return_to_sender(self): if not self.source: self.end_drag() return x, y = self.source.get_absolute_position() if self.p.offset is not None: x, y = x + self.p.offset[0], y + self.p.offset[1] self.go_to(x, y, 10) def do_delivery_confirmation(self): if not self.delivery_confirmation: return def finish_movement(self): self.source.handle_drop(self.draggable) self.end_drag() class IDragObject(IObj): def blit(self, target, x, y): self.p.image.blit(target, x, y) def width(self): return self.p.image.width() def height(self): return self.p.image.height() class IDragReceptacle(IObj): value = None drop_destination = property(lambda self: not self.value) state_mapping = { IObj.NORMAL: IObj.TOGGLED, IObj.FOCUSED: IObj.CLICKED } def render_self(self, theme, target, px, py): width, height = self.p.w, self.p.h self.draw_rect((1, 10), target, px, py, width, height, True, self.state_mapping) if self.value: mx, my = self.value.width(), self.value.height() mx, my = (width * 16 - mx) / 2, (height * 16 - my) / 2 self.value.blit(target, px + mx, py + my) def handle_unclick(self, lx, ly): if self.value: v, self.value = self.value, None mx, my = v.width(), v.height() mx, my = (self.p.w * 16 - mx) / 2, (self.p.h * 16 - my) / 2 self.start_drag(v, (mx, my)) def handle_drop(self, item): self.set_value(item)