selection.py :  » GUI » Sketch » skencil-0.6.17 » Sketch » Graphics » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » GUI » Sketch 
Sketch » skencil 0.6.17 » Sketch » Graphics » selection.py
# Sketch - A Python-based interactive drawing program
# Copyright (C) 1997, 1998, 1999, 2000 by Bernhard Herzog
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


# Classes for handling selections. These include classes that represent
# lists of selected objects and classes that represent the combined
# bounding rectangle of all selected objects. The user can interact in
# the usual fashion with these selection rects to transform (translate,
# rotate, scale, shear) the selected objects.


import operator, math
from types import ListType,InstanceType,TupleType
import time

from Sketch.Lib.util import flatten

from Sketch.UI.skpixmaps import pixmaps
from Sketch.warn import pdebug,warn,INTERNAL
from Sketch import const
from Sketch.const import SelectSet

from Sketch import _,Point,Polar,Rect,UnionRects,RectType,Identity,\
     Trafo, TrafoType, Rotation, CreateListUndo, NullUndo

import handle
from base import SelectAndDrag,Bounded
import selinfo


class SelRectBase(SelectAndDrag, Bounded):

    #
    # Handle/selection numbers:
    #  sx    ex
    #  1  2  3  sy
    #
    #  8    4
    #
    #  7  6  5  ey
    #
    #  -1: whole object

    selTop  = (1, 2, 3)
    selBottom  = (7, 6, 5)
    selLeft  = (1, 8, 7)
    selRight  = (3, 4, 5)
    selAspect  = (1, 3, 5, 7)  # constrain aspect ratio for these selections

    handle_idx_to_sel = (7, 6, 5, 8, 4, 1, 2, 3)

    def __init__(self):
  SelectAndDrag.__init__(self)
  self.outline_object = None

    def update_rects(self):
  self.coord_rect = Rect(self.start, self.end)
  self.bounding_rect = self.coord_rect

    def SetOutlineObject(self, obj):
  # XXX: this is a hack...
  if obj is not None:
      if obj.is_Compound:
    objects = obj.GetObjects()
    if len(objects) == 1:
        obj = objects[0]
    else:
        return
      if not obj.is_Compound and not obj.is_Text:
    self.outline_object = obj


class SelectionRectangle(SelRectBase):

    def __init__(self, rect, anchor = None):
  SelRectBase.__init__(self)
  if type(rect) == RectType:
      self.start = Point(rect.left, rect.bottom)
      self.end = Point(rect.right, rect.top)
      self.Normalize()
      self.anchor = anchor
  else:
      # assume type Point and interactive creation
      self.start = rect
      self.end = rect
      self.anchor = None
      self.selection = 5

    def DrawDragged(self, device, partially):
  sel = self.selection

  if sel == -1:
      sx, sy = self.start + self.off
      ex, ey = self.end + self.off
  else:
      if sel in self.selTop:
    sy = self.drag_cur.y
      else:
    sy = self.start.y

      if sel in self.selBottom:
    ey = self.drag_cur.y
      else:
    ey = self.end.y

      if sel in self.selLeft:
    sx = self.drag_cur.x
      else:
    sx = self.start.x

      if sel in self.selRight:
    ex = self.drag_cur.x
      else:
    ex = self.end.x

  if sx > ex:
      tmp = sx; sx = ex; ex = tmp
  if sy < ey:
      tmp = sy; sy = ey; ey = tmp

  device.DrawRubberRect(Point(sx, sy), Point(ex, ey))

    def ButtonDown(self, p, button, state):
  SelectAndDrag.DragStart(self, p)
  sel = self.selection
  if sel == -1:
      if self.anchor: #XXX shouldn't this be 'if self.anchor is not None'
    start = self.anchor
      else:
    start = self.start
      self.drag_start = self.drag_cur = start
      return (p - start, self.coord_rect.translated(-start))
  ds_x , ds_y = (self.start + self.end) / 2
  if sel in self.selLeft:
      ds_x = self.start.x
  if sel in self.selTop:
      ds_y = self.start.y
  if sel in self.selRight:
      ds_x = self.end.x
  if sel in self.selBottom:
      ds_y = self.end.y
  self.drag_cur = self.drag_start = ds = Point(ds_x, ds_y)
  self.init_constraint()
  return p - ds

    def init_constraint(self):
  pass

    def apply_constraint(self, p, state):
  return p

    def MouseMove(self, p, state):
  p = self.apply_constraint(p, state)
  SelectAndDrag.MouseMove(self, p, state)

    def compute_endpoints(self):
  cur = self.drag_cur
  start = self.start
  end = self.end
  sel = self.selection
  if sel in self.selTop:
      start = Point(start.x, cur.y)
  if sel in self.selBottom:
      end    = Point(end.x,   cur.y)
  if sel in self.selLeft:
      start = Point(cur.x, start.y)
  if sel in self.selRight:
      end = Point(cur.x, end.y)
  if sel == -1:
      start = start + self.off
      end = end + self.off
        return start, end

    def ButtonUp(self, p, button, state):
  p = self.apply_constraint(p, state)
  SelectAndDrag.DragStop(self, p)
  cur = self.drag_cur
  oldstart = self.start
  oldend = self.end
  start, end = self.compute_endpoints()
  self.start = start
  self.end = end
  result = self.ComputeTrafo(oldstart, oldend, start, end)
  self.Normalize()
  return result

    def ComputeTrafo(self, oldStart, oldEnd, start, end):
  pass

    def Normalize(self):
  sx, sy = self.start
  ex, ey = self.end
  if sx > ex:
      sx, ex = ex, sx
  if sy > ey:
      sy, ey = ey, sy
  self.start = Point(sx, sy)
  self.end = Point(ex, ey)

    def Hit(self, p, rect, device):
  pass

    def Select(self):
  self.selection = -1

    def SelectPoint(self, p, rect, device, mode = SelectSet):
  if p:
      self.selection = 0
  else:
      self.selection = -1
  return self.selection

    def SelectHandle(self, handle, mode = SelectSet):
  self.selection = self.handle_idx_to_sel[handle.index]

    def GetHandles(self):
  sx = self.start.x
  sy = self.start.y
  ex = self.end.x
  ey = self.end.y
  x2 = (sx + ex) / 2
  y2 = (sy + ey) / 2
  return map(handle.MakeOffsetHandle,
       [Point(sx, ey),  Point(x2, ey),  Point(ex, ey),
        Point(sx, y2),      Point(ex, y2),
        Point(sx, sy),  Point(x2, sy),  Point(ex, sy)],
       [(-1,  1),    (0,  1),  ( 1,  1),
        (-1,  0),        ( 1,  0),
        (-1, -1),    (0, -1),  ( 1, -1)])



class Selection(Bounded):

    is_EditSelection = 0

    _lazy_attrs = Bounded._lazy_attrs.copy()
    _lazy_attrs['rect'] = 'update_rectangle'
    
    def __init__(self, copy_from = None):
  if copy_from is not None:
      if type(copy_from) == ListType:
    self.objects = copy_from[:]
      else:
    # assume copy_from is another instance of a selection class
    self.objects = copy_from.objects
    self.coord_rect = copy_from.coord_rect
    self.bounding_rect = copy_from.bounding_rect
    self.anchor = copy_from.anchor
  else:
      self.objects = []
      self.anchor = None

    def normalize(self):
  # make sure that self.objects contains no object more than once
  # and that no two objects have a direct or indirect parent/child
  # relationship.
  objs = self.objects
  changed = 0
  if len(objs) > 1:
      objs.sort()
      last_info, obj = objs[-1]
      for idx in range(len(objs) - 2, -1, -1):
    info, obj = objs[idx]
    if info == last_info:
        del objs[idx]
        changed = 1
        continue
    if len(info) < len(last_info):
        while info == last_info[:len(info)]:
      del objs[idx + 1]
      changed = 1
      if idx + 1 < len(objs):
          last_info = objs[idx + 1][0]
      else:
          break
    last_info = info
  return changed

    def update_selinfo(self):
        objs = self.objects
        for i in range(len(objs)):
            objs[i] = objs[i][-1].SelectionInfo()

    def SetSelection(self, info):
  old_objs = self.objects
  if info:
      if type(info) == ListType:
    self.objects = info
    self.objects.sort()
      else:
    self.objects = [info]
  else:
      self.objects = []
  self.del_lazy_attrs()
  return old_objs != self.objects

    def SetSelectionTree(self, info):
  return self.SetSelection(selinfo.tree_to_list(info))

    def Add(self, info):
  if not info:
      return 0
  old_len = len(self.objects)
  if type(info) == ListType:
      self.objects = self.objects + info
  elif info:
      self.objects.append(info)
  changed = self.normalize()
  self.del_lazy_attrs()
  return changed or old_len != len(self.objects)

    def Subtract(self, info):
  if not info:
      return 0
  old_len = len(self.objects)
  if type(info) != ListType:
      info = [info]
  objects = self.objects
  for item in info:
      if item in objects:
    objects.remove(item)
  self.del_lazy_attrs()
  return old_len != len(self.objects)

    def GetObjects(self):
  return map(operator.getitem, self.objects, [-1] * len(self.objects))

    def GetInfo(self):
  return self.objects

    def GetInfoTree(self):
  return selinfo.list_to_tree(self.objects)

    def Depth(self):
  if self.objects:
      lengths = map(len, map(operator.getitem, self.objects,
           [0] * len(self.objects)))
      lmin = min(lengths)
      lmax = max(lengths)
      if lmin == lmax:
    return lmin
      return (lmin, lmax)
  return 0

    def IsSingleDepth(self):
  if self.objects:
      return type(self.Depth()) != TupleType
  return 1

    def GetPath(self):
  if len(self.objects) == 1:
      return self.objects[0][0]
  return ()

    def for_all(self, func):
  return map(func, self.GetObjects())

    def ForAllUndo(self, func):
  undoinfo = self.for_all(func)
  self.del_lazy_attrs()
  if len(undoinfo) == 1:
      undoinfo = undoinfo[0]
  if type(undoinfo) == ListType:
      return CreateListUndo(undoinfo)
  return undoinfo

    def ForAllUndo2(self, method, *args):
  t = time.clock()
  methods = map(getattr, self.GetObjects(), [method] * len(self.objects))
  #print time.clock() - t,
  #undoinfo = self.for_all(func)
  undoinfo = map(apply, methods, [args] * len(methods))
  #print time.clock() - t
  self.del_lazy_attrs()
  if len(undoinfo) == 1:
      undoinfo = undoinfo[0]
  if type(undoinfo) == ListType:
      return CreateListUndo(undoinfo)
  return undoinfo

    def __len__(self):
  return len(self.objects)

    __nonzero__ = __len__

    def update_rects(self):
  objects = self.GetObjects()
  boxes = map(lambda o: o.coord_rect, objects)
  if boxes:
      self.coord_rect = reduce(UnionRects, boxes)
  else:
      self.coord_rect = None
  boxes = map(lambda o: o.bounding_rect, objects)
  if boxes:
      self.bounding_rect = reduce(UnionRects, boxes)
  else:
      self.bounding_rect = None
  if len(objects) == 1:
      self.anchor = objects[0].LayoutPoint()
  else:
      self.anchor = None

    def ChangeRect(self):
  return self.bounding_rect

    def ResetRectangle(self):
  self.del_lazy_attrs()

    def Hit(self, p, rect, device):
  test = rect.overlaps
  for obj in self.GetObjects():
      if test(obj.bounding_rect):
    if obj.Hit(p, rect, device):
        return 1
  return 0

    def DragCancel(self):
  self.rect.DragCancel()

    def GetHandles(self):
  rect_handles = self.rect.GetHandles()
  multiple = len(self.objects) > 1
  handles = flatten(self.for_all(lambda o, m = multiple:
               o.GetObjectHandle(m)))
  rect_handles.append(handle.MakeObjectHandleList(handles))
  return rect_handles

    def CallObjectMethod(self, aclass, methodname, args):
  if len(self.objects) == 1:
      obj = self.objects[0][-1]
      if not isinstance(obj, aclass):
    return NullUndo
      try:
    method = getattr(obj, methodname)
      except AttributeError:
    return NullUndo

      undo = apply(method, args)
      if undo is None:
    undo = NullUndo
      return undo
  return NullUndo

    def GetObjectMethod(self, aclass, method):
  if len(self.objects) == 1:
      obj = self.objects[0][-1]
      if isinstance(obj, aclass):
    try:
        return getattr(obj, method)
    except AttributeError:
        pass
  return None

    def InfoText(self):
  # Return a string describing the selected object(s)
        result = _("No Selection")
  if self.objects:
      sel_info = self.objects
      document = sel_info[0][1].document
      if len(sel_info) == 1:
                path, obj = sel_info[0]
                dict = {'layer': document[path[0]].Name()}
    info = obj.Info()
                if type(info) == TupleType:
                    dict.update(info[1])
                    # the %% is correct here. The result has to be a
                    # %-template itself.
                    text = _("%s on `%%(layer)s'") % info[0]
                else:
                    dict['object'] = info
                    text = _("%(object)s on `%(layer)s'")
                result = text, dict
      else:
    layer = sel_info[0][0][0]
    if layer == sel_info[-1][0][0]:
        # a single layer
        layer_name = document.layers[layer].Name()
        result = _("%(number)d objects on `%(layer)s'") \
                             % {'number':len(sel_info), 'layer':layer_name}
    else:
        result = _("%d objects on several layers") % len(sel_info)

        return result

    def CurrentInfoText(self):
        return ''

    def _dummy(self, *args):
  pass

    Hide   = _dummy
    DragStart   = None
    DragMove   = None
    DragStop   = None
    Show   = _dummy
    Hide   = _dummy
    SelectPoint   = _dummy
    SelectHandle = _dummy

    drag_mask = SelectAndDrag.drag_mask



class SizeRectangle(SelectionRectangle):

    def init_constraint(self):
  sel = self.selection
  if sel == 1:
      self.reference = tuple(self.end)
  elif sel == 3:
      self.reference = (self.start.x, self.end.y)
  elif sel == 5:
      self.reference = tuple(self.start)
  elif sel == 7:
      self.reference = (self.end.x, self.start.y)
  else:
      return
  width = abs(self.start.x - self.end.x)
  height = abs(self.start.y - self.end.y)
  if width >= 1e-10:
      self.aspect = height / width
  else:
      self.aspect = None

    def apply_constraint(self, p, state):
  if state & const.ConstraintMask:
      if self.selection in self.selAspect:
    ref_x, ref_y = self.reference
    aspect = self.aspect
    if aspect is None:
        # width is 0
        p = Point(self.drag_start.x, p.y)
    else:
        w = p.x - ref_x
        h = p.y - ref_y
        if w == 0:
      w = 0.00001
        a = h / w
        if a > 0:
      sign = 1
        else:
      sign = -1
        if abs(a) > aspect:
      h = sign * w * aspect
        else:
      w = sign * h / aspect
        p = Point(ref_x + w, ref_y + h)
      elif self.selection == -1:
    pi4 = math.pi / 4
    off = p - self.drag_start
                d = Polar(pi4 * round(math.atan2(off.y, off.x) / pi4))
                p = self.drag_start + (off * d) * d
  return p

    def ButtonDown(self, p, button, state):
        self.trafo = Identity
        return SelectionRectangle.ButtonDown(self, p, button, state)

    def MouseMove(self, p, state):
  p = self.apply_constraint(p, state)
  SelectAndDrag.MouseMove(self, p, state)
        start, end = self.compute_endpoints()
        text, self.trafo = self.ComputeTrafo(self.start, self.end, start, end)

    def ComputeTrafo(self, oldStart, oldEnd, start, end):
  oldDelta = oldEnd - oldStart
  delta   = end - start
  if self.selection == -1:
      # a translation.
      return _("Move Objects"), start - oldStart
  else:
      try:
    m11 = delta.x / oldDelta.x
      except ZeroDivisionError:
    m11 = 0
    if __debug__:
        pdebug(None, 'ComputeTrafo: ZeroDivisionError')
      try:
    m22 = delta.y / oldDelta.y
      except ZeroDivisionError:
    m22 = 0
    if __debug__:
        pdebug(None, 'ComputeTrafo: ZeroDivisionError')
      offx = start.x - m11 * oldStart.x
      offy = start.y - m22 * oldStart.y
      return _("Resize Objects"), Trafo(m11, 0, 0, m22, offx, offy)

    def DrawDragged(self, device, partial):
  SelectionRectangle.DrawDragged(self, device, partial)
  if self.outline_object is not None:
      trafo = self.trafo
      device.PushTrafo()
      if type(trafo) == TrafoType:
    device.Concat(trafo)
      else:
    device.Translate(trafo.x, trafo.y)
      self.outline_object.DrawShape(device)
      device.PopTrafo()

    def CurrentInfoText(self):
        t = self.trafo
        data = {}
        if type(t) == TrafoType:
            x = t.m11
            y = t.m22
            #if round(x, 3) == round(y, 3):
            #    text = _("Uniform Scale %(factor)[factor]")
            #    data['factor'] = x
            #else:
            text = _("Scale %(factorx)[factor], %(factory)[factor]")
            data['factorx'] = x
            data['factory'] = y
        else:
            text = _("Move %(x)[length], %(y)[length]")
            data['x'] = t.x
            data['y'] = t.y
        return text, data



class SizeSelection(Selection):

    def __init__(self, arg = None):
  Selection.__init__(self, arg)

    def update_rectangle(self):
  if self:
      self.rect = SizeRectangle(self.coord_rect, self.anchor)
  else:
      self.rect = SizeRectangle(Rect(0, 0, 0, 0))

    def ButtonDown(self, p, button, state):
  if len(self.objects) == 1:
      self.rect.SetOutlineObject(self.objects[0][-1])
  return self.rect.ButtonDown(p, button, state)

    def MouseMove(self, p, state):
  self.rect.MouseMove(p, state)

    def ButtonUp(self, p, button, state, forget_trafo = 0):
  self.rect.SetOutlineObject(None)
  undo_text, trafo = self.rect.ButtonUp(p, button, state)
  if forget_trafo:
      return None, None
  t = time.clock()
  if type(trafo) == TrafoType:
      #undo = self.ForAllUndo(lambda o, t = trafo: o.Transform(t))
      undo = self.ForAllUndo2('Transform', trafo)
  else:
      # trafo is point representing a translation
      undo = self.ForAllUndo2('Translate', trafo)
  #print 'transform/translate', time.clock() - t
  self.del_lazy_attrs()
  return undo_text, undo

    def Show(self, device, partially = 0):
  self.rect.Show(device, partially)

    def Hide(self, device, partially = 0):
  self.rect.Hide(device, partially)

    def DrawDragged(self, device, partial):
  self.rect.DrawDragged(device, partial)

    def SelectPoint(self, p, rect, device, mode = SelectSet):
  if not self.rect.SelectPoint(p, rect, device, mode):
      if self.Hit(p, rect, device):
    self.rect.Select()

    def SelectHandle(self, handle, mode = SelectSet):
  self.rect.SelectHandle(handle, mode)

    def Hit(self, p, rect, device):
  if self.objects:
      return (rect.overlaps(self.bounding_rect)
        and Selection.Hit(self, p, rect, device))
  return 0

    def CurrentInfoText(self):
        return self.rect.CurrentInfoText()

class TrafoRectangle(SelRectBase):

    selTurn = [1, 3, 5, 7]
    selShear = [2, 4, 6, 8]
    selCenter = 100

    def __init__(self, rect, center = None):
  SelRectBase.__init__(self)
  self.start = Point(rect.left, rect.bottom)
  self.end = Point(rect.right, rect.top)
  if center is None:
      self.center = rect.center()
  else:
      self.center = center

    def compute_trafo(self, state = 0):
  sel = self.selection
  if sel in self.selTurn:
      # rotation
      vec = self.drag_cur - self.center
      angle = math.atan2(vec.y, vec.x)
      angle = angle - self.start_angle + 2 * math.pi
      if state & const.ConstraintMask:
    pi12 = math.pi / 12
    angle = pi12 * int(angle / pi12 + 0.5)
            self.trafo = Rotation(angle, self.center)
            self.trafo_desc = (1, angle)
  elif sel in self.selShear:
      if sel in (2,6):
    # horiz. shear
    height = self.drag_start.y - self.reference
    if height:
        ratio = self.off.x / height
        self.trafo = Trafo(1, 0, ratio, 1,
                                       - ratio * self.reference, 0)
                    self.trafo_desc = (2, ratio)
      else:
    # vert. shear
    width = self.drag_start.x - self.reference
    if width:
        ratio = self.off.y / width
        self.trafo = Trafo(1, ratio, 0, 1, 0,
                                       - ratio * self.reference)
                    self.trafo_desc = (3, ratio)

    def DrawDragged(self, device, partially):
  sel = self.selection
  if sel == self.selCenter:
      device.DrawPixmapHandle(self.drag_cur, pixmaps.Center)
  else:
      trafo = self.trafo
      if trafo:
    device.PushTrafo()
    device.Concat(trafo)
    device.DrawRubberRect(self.start, self.end)
    if self.outline_object is not None:
        self.outline_object.DrawShape(device)
    device.PopTrafo()

    def ButtonDown(self, p, button, state):
  self.drag_state = state
        self.trafo = Identity
        self.trafo_desc = (0, 0)
  SelectAndDrag.DragStart(self, p)
  sel = self.selection
  if sel == self.selCenter:
      self.drag_cur = self.drag_start = self.center
      return p - self.center
  ds_x = ds_y = 0
  if sel in self.selLeft:
      ds_x = self.start.x
  if sel in self.selTop:
      ds_y = self.start.y
  if sel in self.selRight:
      ds_x = self.end.x
  if sel in self.selBottom:
      ds_y = self.end.y
  self.drag_cur = self.drag_start = ds = Point(ds_x, ds_y)
  if sel in self.selTurn:
      vec = ds - self.center
      self.start_angle = math.atan2(vec.y, vec.x)
  else:
      if sel == 2:
    self.reference = self.end.y
      elif sel == 4:
    self.reference = self.start.x
      elif sel == 6:
    self.reference = self.start.y
      elif sel == 8:
    self.reference = self.end.x
  return p - ds

    def constrain_center(self, p, state):
  if state & const.ConstraintMask:
      start = self.start
      end = self.end
      if p.x < 0.75 * start.x + 0.25 * end.x:
    x = start.x
      elif p.x > 0.25 * start.x + 0.75 * end.x:
    x = end.x
      else:
    x = (start.x + end.x) / 2
      if p.y < 0.75 * start.y + 0.25 * end.y:
    y = start.y
      elif p.y > 0.25 * start.y + 0.75 * end.y:
    y = end.y
      else:
    y = (start.y + end.y) / 2
      return Point(x, y)
  return p

    def MouseMove(self, p, state):
  self.drag_state = state
  if self.selection == self.selCenter:
      p = self.constrain_center(p, state)
  SelectAndDrag.MouseMove(self, p, state)
        self.compute_trafo(state)

    def ButtonUp(self, p, button, state):
  if self.selection == self.selCenter:
      p = self.constrain_center(p, state)
  SelectAndDrag.DragStop(self, p)
  sel = self.selection
  if sel == self.selCenter:
      self.center = self.drag_cur
      return '', None
  else:
            self.compute_trafo(state)
      trafo = self.trafo
      if self.selection in self.selShear:
    text = _("Shear Objects")
      else:
    text = _("Rotate Objects")
      return text, trafo

    def CurrentInfoText(self):
        if self.selection == self.selCenter:
            text = _("Rotation Center at %(position)[position]")
            data = {'position': self.drag_cur}
        else:
            type, value = self.trafo_desc
            if type == 1:
                text = _("Rotate by %(angle)[angle]")
                data = {'angle': value}
            elif type == 2:
                text = _("Horizontal Shear by %(ratio)[factor]")
                data = {'ratio': value}
            elif type == 3:
                text = _("Vertical Shear by %(ratio)[factor]")
                data = {'ratio': value}
            else:
                text = _("Identity Transform")
                data = {}
        return text, data

    def Hit(self, p, rect, device):
  pass

    def Select(self):
  pass

    def SelectPoint(self, p, rect, device, mode = SelectSet):
  self.selection = 0
  return self.selection

    def SelectHandle(self, handle, mode = SelectSet):
  handle = handle.index
  if handle == len(self.handle_idx_to_sel):
      self.selection = self.selCenter
  else:
      self.selection = self.handle_idx_to_sel[handle]

    def GetHandles(self):
  sx = self.start.x
  sy = self.start.y
  ex = self.end.x
  ey = self.end.y
  x2 = (sx + ex) / 2
  y2 = (sy + ey) / 2
  return map(handle.MakePixmapHandle,
       [Point(sx, ey),  Point(x2, ey),  Point(ex, ey),
        Point(sx, y2),      Point(ex, y2),
        Point(sx, sy),  Point(x2, sy),  Point(ex, sy)],
       [(-1,  1),    (0,  1),  ( 1,  1),
        (-1,  0),        ( 1,  0),
        (-1, -1),    (0, -1),  ( 1, -1)],
       [pixmaps.TurnTL, pixmaps.ShearLR,  pixmaps.TurnTR,
        pixmaps.ShearUD,      pixmaps.ShearUD,
        pixmaps.TurnBL, pixmaps.ShearLR,  pixmaps.TurnBR],
       [const.CurTurn] * 8) \
       + [handle.MakePixmapHandle(self.center, (0, 0), pixmaps.Center)]


class TrafoSelection(Selection):

    def __init__(self, copy_from = None):
  Selection.__init__(self, copy_from)
  self.center = None

    def update_rectangle(self, same_center = 1):
  if self:
      self.rect = TrafoRectangle(self.coord_rect, self.center)
  else:
      self.rect = TrafoRectangle(Rect(0, 0, 0, 0))

    def ButtonDown(self, p, button, state):
  if len(self.objects) == 1:
      self.rect.SetOutlineObject(self.objects[0][-1])
  return self.rect.ButtonDown(p, button, state)

    def MouseMove(self, p, state):
  self.rect.MouseMove(p, state)

    def ButtonUp(self, p, button, state, forget_trafo = 0):
  self.rect.SetOutlineObject(None)
  undo_text, trafo = self.rect.ButtonUp(p, button, state)
  self.center = self.rect.center
  if forget_trafo:
      return None, None
  if trafo is not None:
      t = time.clock()
      #undo = self.ForAllUndo(lambda o, t = trafo: o.Transform(t))
      undo = self.ForAllUndo2('Transform', trafo)
      self.del_lazy_attrs()
      #print 'transform/translate', time.clock() - t
      return undo_text, undo
  return '', None

    def Show(self, device, partially = 0):
  self.rect.Show(device, partially)

    def Hide(self, device, partially = 0):
  self.rect.Hide(device, partially)

    def DrawDragged(self, device, partial):
  self.rect.DrawDragged(device, partial)

    def SelectPoint(self, p, rect, device, mode = SelectSet):
  if not self.rect.SelectPoint(p, rect, device, mode):
      if self.Hit(p, rect, device):
    self.rect.Select()

    def SelectHandle(self, handle, mode = SelectSet):
  self.rect.SelectHandle(handle, mode)

    def Hit(self, p, rect, device):
  if self.objects:
      return (rect.overlaps(self.rect.bounding_rect)
        and Selection.Hit(self, p, rect, device))
  return 0

    def CurrentInfoText(self):
        return self.rect.CurrentInfoText()

class EditorWrapper:

    def __init__(self, editor):
  self.editor = editor

    def __del__(self):
  self.editor.Destroy()

    def __getattr__(self, attr):
  return getattr(self.editor, attr)

    def compatible(self, aclass):
  obj = self.editor
  return isinstance(obj, aclass) or issubclass(obj.EditedClass, aclass)



class EditSelection(Selection):

    is_EditSelection = 1
    
    drag_this = None
    editor = None

    def __init__(self, copy_from = None):
  Selection.__init__(self, copy_from)
  self.check_edit_mode()
  if type(copy_from) == InstanceType \
     and copy_from.__class__ == self.__class__:
      self.editor = copy_from.editor
  else:
      self.get_editor()

    def check_edit_mode(self):
  # allow only one object for editing at a time
  if self.objects:
      if len(self.objects) > 1 or not self.objects[0][-1].has_edit_mode:
    self.objects = []

    def get_editor(self):
  if self.objects:
      self.editor = EditorWrapper(self.objects[0][-1].Editor())
  else:
      self.editor = None

    def GetHandles(self):
  if self.editor is not None:
      return self.editor.GetHandles()
  return []

    def ButtonDown(self, p, button, state):
  if self.drag_this is not None:
      return self.drag_this.ButtonDown(p, button, state)
  else:
      return None

    def MouseMove(self, p, state):
  if self.drag_this is not None:
      self.drag_this.MouseMove(p, state)

    def ButtonUp(self, p, button, state, forget_trafo = 0):
  if self.drag_this is not None:
      self.del_lazy_attrs()
      return _("Edit Object"), self.drag_this.ButtonUp(p, button, state)
  return ('', None)
  # XXX make the undo text more general by a method of graphics objects

    def Show(self, device, partially = 0):
  if self.editor is not None:
      self.editor.Show(device, partially)

    def Hide(self, device, partially = 0):
  if self.editor is not None:
      self.editor.Hide(device, partially)

    def DrawDragged(self, device, partial):
  if self.editor is not None:
            self.editor.DrawDragged(device, partial)

    def SetSelection(self, info):
  old_sel = self.objects
  Selection.SetSelection(self, info)
  self.check_edit_mode()
  if old_sel != self.objects:
      self.get_editor()
      return 1
  return 0

    def SelectPoint(self, p, rect, device, mode = const.SelectSet):
  self.drag_this = None
  if self.editor is not None:
      if self.editor.SelectPoint(p, rect, device, mode):
    self.drag_this = self.editor
  return self.drag_this != None

    def SelectHandle(self, handle, mode = SelectSet):
  if self.editor is not None:
      self.editor.SelectHandle(handle, mode)
      self.drag_this = self.editor
  else:
      self.drag_this = None

    def SelectRect(self, rect, mode = SelectSet):
  self.drag_this = None
  if self.editor is not None:
      if self.editor.SelectRect(rect, mode):
    self.drag_this = self.editor
  return self.drag_this != None

    def CallObjectMethod(self, aclass, methodname, args):
  if len(self.objects) == 1:
      if self.editor is not None:
    obj = self.editor
    if not obj.compatible(aclass):
        warn(INTERNAL, 'EditSelection.GetObjectMethod: '
       'editor %s is not compatible with class %s',
       self.editor, aclass)
        return NullUndo
      else:
    obj = self.objects[0][-1]
    if not isinstance(obj, aclass):
        warn(INTERNAL, 'EditSelection.GetObjectMethod: '
       'object is not instance of %s', aclass)
        return NullUndo
      try:
    method = getattr(obj, methodname)
      except AttributeError:
    warn(INTERNAL, 'EditSelection.GetObjectMethod: '
         'no method %s for class %s', methodname, aclass)
    return NullUndo

      undo = apply(method, args)
      if undo is None:
    undo = NullUndo
      return undo
  return NullUndo

    def GetObjectMethod(self, aclass, method):
  if len(self.objects) == 1:
      if self.editor is not None:
    obj = self.editor
    if not obj.compatible(aclass):
        warn(INTERNAL, 'EditSelection.GetObjectMethod: '
       'editor is not compatible with class %s', aclass)
        return None
      else:
    obj = self.objects[0][-1]
    if not isinstance(obj, aclass):
        warn(INTERNAL, 'EditSelection.GetObjectMethod: '
       'object is not instance of %s', aclass)
        return None
      try:
    return getattr(obj, method)
      except AttributeError:
    warn(INTERNAL, 'EditSelection.GetObjectMethod: '
         'no method %s for class %s', method, aclass)
    pass
  return None


    def ChangeRect(self):
  if self.editor is not None:
      return self.editor.ChangeRect()
  return self.bounding_rect

    def InfoText(self):
  # Return a string describing the selected object(s)
  # XXX we shouldn't access document.layers directly
  if self.editor is not None:
      return self.editor.Info()
  else:
      return _("No Selection")

    def CurrentInfoText(self):
  if self.editor is not None:
      return self.editor.CurrentInfoText()
  else:
      return ""
        
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.