#
# Copyright (c) 2002, 2003, 2004 Art Haas
#
# This file is part of PythonCAD.
# 
# PythonCAD 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 2 of the License, or
# (at your option) any later version.
# 
# PythonCAD 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 PythonCAD; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#
# handle cut, copy, paste, selections, etc
#

import pygtk
pygtk.require('2.0')
import gtk

from PythonCAD.Generic.point import Point
from PythonCAD.Generic.segment import Segment
from PythonCAD.Generic.circle import Circle
from PythonCAD.Generic.arc import Arc
from PythonCAD.Generic.hcline import HCLine
from PythonCAD.Generic.vcline import VCLine
from PythonCAD.Generic.acline import ACLine
from PythonCAD.Generic.cline import CLine
from PythonCAD.Generic.ccircle import CCircle
from PythonCAD.Generic.dimension import LinearDimension
from PythonCAD.Generic.dimension import HorizontalDimension
from PythonCAD.Generic.dimension import VerticalDimension
from PythonCAD.Generic.dimension import RadialDimension
from PythonCAD.Generic.dimension import AngularDimension
from PythonCAD.Generic.text import TextStyle
import PythonCAD.Generic.globals

def select_region_end_cb(gtkimage, widget, event, tool):
    # print "called select_region_end_callback()"
    _x2, _y2 = gtkimage.getPoint()
    _y1 = tool.popObject()
    _x1 = tool.popObject()
    _xmin = min(_x1, _x2)
    _xmax = max(_x1, _x2)
    _ymin = min(_y1, _y2)
    _ymax = max(_y1, _y2)
    tool.delHandler("motion_notify")
    tool.setHandler("button_press", select_button_press_cb)
    _active_layer = gtkimage.getActiveLayer()
    _objs = _active_layer.objsInRegion(_xmin, _ymin, _xmax, _ymax)
    if len(_objs):
        for _obj in _objs:
            gtkimage.selectObject(_active_layer, _obj)
    select_mode_init(tool)

def select_motion_notify(gtkimage, widget, event, tool):
    _tx, _ty = tool.getLocation()
    _px, _py = gtkimage.coordToPixTransform(_tx, _ty)
    _width, _height = gtkimage.getSize()
    _gc = gtkimage.getGC()
    _x = int(event.x)
    _y = int(event.y)
    _cp = tool.getCurrentPoint()
    if _cp is not None:
        _xc, _yc = _cp
        _xmin = min(_xc, _px)
        _ymin = min(_yc, _py)
        _rw = abs(_xc - _px)
        _rh = abs(_yc - _py)
        widget.window.draw_rectangle(_gc, gtk.FALSE, _xmin, _ymin, _rw, _rh)
    tool.setCurrentPoint(_x, _y)
    _xmin = min(_x, _px)
    _ymin = min(_y, _py)
    _rw = abs(_x - _px)
    _rh = abs(_y - _py)
    widget.window.draw_rectangle(_gc, gtk.FALSE, _xmin, _ymin, _rw, _rh)

def select_button_press_cb(gtkimage, widget, event, tool):
    _x, _y = gtkimage.getPoint()
    # print "x: %g; y: %g" % (_x, _y)
    _active_layer = gtkimage.getActiveLayer()
    _tol = gtkimage.getTolerance()
    _pt = _active_layer.find('point', _x, _y, _tol)
    if _pt is not None:
        gtkimage.selectObject(_active_layer, _pt)
    else:
        _objs = []
        for _tb in _active_layer.getLayerEntities('text'):
            # print "testing tb: " + `_tb`
            _tx, _ty = _tb.getLocation()
            # print "tx: %g; ty: %g" % (_tx, _ty)
            _bounds = _tb.getBounds()
            if _bounds is not None:
                # print "has bounds ..."
                _w, _h = _bounds
                _align = _tb.getAlignment()
                if _align == TextStyle.ALIGN_LEFT:
                    _txmin = _tx
                    _txmax = _tx + _w
                elif _align == TextStyle.ALIGN_CENTER:
                    _off = _w/2.0
                    _txmin = _tx - _off 
                    _txmax = _tx + _off
                elif _align == TextStyle.ALIGN_RIGHT:
                    _txmin = _tx - _w
                    _txmax = _tx
                else:
                    raise ValueError, "Unexpected alignment: %d" % _align
                _tymin = _ty - _h
                _tymax = _ty
                # print "txmin: %g" % _txmin
                # print "tymin: %g" % _tymin
                # print "txmax: %g" % _txmax
                # print "tymax: %g" % _tymax
                if _txmin < _x < _txmax and _tymin < _y < _tymax:
                    _objs.append(_tb)
        for _obj, _pt in _active_layer.mapPoint((_x, _y), _tol):
            _objs.append(_obj)
        if len(_objs):
            # print "have objects ..."
            for _obj in _objs:
                gtkimage.selectObject(_active_layer, _obj)
        else:
            # print "no objects ..."
            gtkimage.setPrompt("Click on another point to select the region.")
            gc = gtkimage.getGC()
            gc.set_line_attributes(1, gtk.gdk.LINE_SOLID,
                                   gtk.gdk.CAP_BUTT, gtk.gdk.JOIN_MITER)
            gc.set_function(gtk.gdk.INVERT)
            tool.setLocation(_x, _y)
            tool.pushObject(_x)
            tool.pushObject(_y)
            tool.setHandler("motion_notify", select_motion_notify)
            tool.setHandler("button_press", select_region_end_cb)

def select_mode_init(tool):
    tool.initialize()
    tool.setHandler("button_press", select_button_press_cb)

def paste_button_press_cb(gtkimage, widget, event, tool):
    print "called paste_button_press_cb()"
    x, y = gtkimage.getPoint()
    print "x: %g; y: %g" % (x, y)
    active_layer = gtkimage.getActiveLayer()
    objs = PythonCAD.Generic.globals.selectobj.getObjects()
    objmap = {}
    for obj in objs:
        if isinstance(obj, Point):
            if not objmap.has_key('point'):
                objmap['point'] = {}
            try:
                cpt = obj.clone()
            except:
                raise
            cpt.move(x,y) # click point acts as an offset            
            ept = active_layer.findObject(cpt)
            if ept is None:
                cpt.reset() # reset the modified flag
                try:
                    active_layer.addObject(cpt)
                except:
                    raise StandardError, "Unable to add new point!"
                objmap['point'][obj] = cpt
            else:
                objmap['point'][obj] = ept
        elif isinstance(obj, Segment):
            if not objmap.has_key('segment'):
                objmap['segment'] = {}
            try:
                cseg = obj.clone()
            except:
                raise
            cseg.move(x, y)
            eseg = active_layer.findObject(cseg)
            if eseg is None:
                p1, p2 = cseg.getEndpoints()
                ep = active_layer.findObject(p1)
                if ep is None:
                    p1.reset()
                    try:
                        active_layer.addObject(p1)
                    except:
                        raise StandardError, "Unable to add Segment p1 point!"
                else:
                    cseg.setP1(ep)
                ep = active_layer.findObject(p2)
                if ep is None:
                    p2.reset()
                    try:
                        active_layer.addObject(p2)
                    except:
                        raise StandardError, "Unable to add Segment p2 point!"
                else:
                    cseg.setP2(ep)
                cseg.reset()
                try:
                    active_layer.addObject(cseg)
                except:
                    raise StandardError, "Unable to add Segment!"
            else:
                objmap['segment'][obj] = eseg
        elif isinstance(obj, (Circle, Arc, CCircle)):
            try:
                cc = obj.clone()
            except:
                raise
            cc.move(x, y)
            ec = active_layer.findObject(cc)
            if ec is None:
                cp = cc.getCenter()
                ep = active_layer.findObject(cp)
                if ep is None:
                    cp.reset()
                    try:
                        active_layer.addObject(cp)
                    except:
                        raise StandardError, "Unable to add circle center point!"
                else:
                    cc.setLocation(cp)
                cc.reset()
                try:
                    active_layer.addObject(cc)
                except:
                    raise StandardError, "Unable to add circle!"
        elif isinstance(obj, (HCLine, VCLine, ACLine)):
            try:
                ccl = obj.clone()
            except:
                raise
            ccl.move(x, y)
            ecl = active_layer.findObject(ccl)
            if ecl is None:
                lp = ccl.getLocation()
                ep = active_layer.findObject(lp)
                if ep is None:
                    lp.reset()
                    try:
                        active_layer.addObject(lp)
                    except:
                        raise StandardError, "Unable to add construction line location point!"
                else:
                    ccl.setLocation(ep)
                ccl.reset()
                try:
                    active_layer.addObject(ccl)
                except:
                    raise StandardError, "Unable to add construction line!"
        elif isinstance(obj, CLine):
            try:
                ccl = obj.clone()
            except:
                raise
            ccl.move(x, y)
            ecl = active_layer.findObject(ccl)
            if ecl is None:
                p1, p2 = ccl.getKeypoints()
                ep = active_layer.findObject(p1)
                if ep is None:
                    p1.reset()
                    try:
                        active_layer.addObject(p1)
                    except:
                        raise StandardError, "Unable to add CLine p1 point!"
                else:
                    ccl.setP1(ep)
                ep = active_layer.findObject(p2)
                if ep is None:
                    p2.reset()
                    try:
                        active_layer.addObject(p2)
                    except:
                        raise StandardError, "Unable to add CLine p2 point!"
                else:
                    ccl.setP2(ep)
                ccl.reset()
                try:
                    active_layer.addObject(ccl)
                except:
                    raise StandardError, "Unable to add CLine!"
        elif isinstance(obj, LinearDimension):
            if active_layer.findObject(obj) is None:
                l1, l2 = obj.getDimLayers()
                if gtkimage.hasLayer(l1) and \
                   gtkimage.hasLayer(l2):
                    p1, p2 = obj.getDimPoints()                    
                    ds = obj.getDimStyle()
                    if isinstance(obj, HorizontalDimension):
                        dimtype = HorizontalDimension
                    elif isinstance(obj, VerticalDimension):
                        dimtype = VerticalDimension
                    else:
                        dimtype = LinearDimension
                    try:
                        dim = dimtype(l1, p1, l2, p2, x, y, ds)
                        active_layer.addObject(dim)
                    except:
                        raise
        elif isinstance(obj, RadialDimension):
            if active_layer.findObject(obj) is None:
                lyr = obj.getDimLayer()
                if gtkimage.hasLayer(lyr):
                    dc = obj.getDimCircle()
                    ds = obj.getDimStyle()
                    try:
                        dim = RadialDimension(lyr, dc, x, y, ds)
                        active_layer.addObject(dim)
                    except:
                        raise
        elif isinstance(obj, AngularDimension):
            if active_layer.findObject(obj) is None:
                cl, l1, l2 = obj.getDimLayers()
                if gtkimage.hasLayer(cl) and \
                   gtkimage.hasLayer(l1) and \
                   gtkimage.hasLayer(l2):
                    cp, p1, p2 = obj.getDimPoints()
                    ds = obj.getDimStyle()
                    try:
                        dim = AngularDimension(cl, cp, l1, p1, l2, p2, x, y, ds)
                        active_layer.addObject(dim)
                    except:
                        raise
    gtkimage.redraw()
    
def paste_mode_init(tool):
    tool.initialize()
    tool.setHandler("button_press", paste_button_press_cb)
