#
# 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

import Generic.point
import Generic.segment
import Generic.circle
import Generic.arc
import Generic.hcline
import Generic.vcline
import Generic.acline
import Generic.cline
import Generic.ccircle
import Generic.dimension
import 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 = event.x
    y = 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()
    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 = active_layer.mapPoint((x, y), tol)
        if len(objs):
            for obj, pt in objs:
                gtkimage.selectObject(active_layer, obj)
        else:
            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 _get_border(objs):
    _xmin = None
    _ymin = None
    _xmax = None
    _ymax = None
    for obj in objs:
        if isinstance(obj, Generic.point.Point):
            x, y = obj.getCoords()
            if _xmin is None or x < _xmin:
                _xmin = x
            if _ymin is None or y < _ymin:
                _ymin = y
            if _xmax is None or x > _xmax:
                _xmax = x
            if _ymax is None or y > _ymax:
                _ymax = y
        elif isinstance(obj, Generic.segment.Segment):
            for pt in obj.getEndpoints():
                x, y = pt.getCoords()
                if _xmin is None or x < _xmin:
                    _xmin = x
                if _ymin is None or y < _ymin:
                    _ymin = y
                if _xmax is None or x > _xmax:
                    _xmax = x
                if _ymax is None or y > _ymax:
                    _ymax = y
        elif isinstance(obj, Generic.circle.Circle):
            x, y = obj.getCenter().getCoords()
            r = obj.getRadius()
            cxmin = x - r
            cymin = y - r
            cxmax = x + r
            cymax = y + r
            if _xmin is None or cxmin < _xmin:
                _xmin = cxmin
            if _ymin is None or cymin < _ymin:
                _ymin = cymin
            if _xmax is None or cxmax > _xmax:
                _xmax = cxmax
            if _ymax is None or cymax > _ymax:
                _ymax = cymax
    return (_xmin, _ymin, _xmax, _ymax)

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 = Generic.globals.selectobj.getObjects()
    objmap = {}
    for obj in objs:
        if isinstance(obj, Generic.point.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, Generic.segment.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, (Generic.circle.Circle,
                              Generic.arc.Arc,
                              Generic.ccircle.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, (Generic.hcline.HCLine,
                              Generic.vcline.VCLine,
                              Generic.acline.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, Generic.cline.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, Generic.dimension.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, dimension.HorizontalDimension):
                        dimtype = dimension.HorizontalDimension
                    elif isinstance(obj, dimension.VerticalDimension):
                        dimtype = dimension.VerticalDimension
                    else:
                        dimtype = dimension.LinearDimension
                    try:
                        dim = dimtype(l1, p1, l2, p2, x, y, ds)
                        active_layer.addObject(dim)
                    except:
                        raise
        elif isinstance(obj, Generic.dimension.RadialDimension):
            if active_layer.findObject(obj) is None:
                lyr = obj.getDimLayer()
                if gtkimage.hasLayer(lyr):
                    dc = obj.getDimCircle()
                    ds = obj.getDimStyle()
                    try:
                        dim = dimension.RadialDimension(lyr, dc, x, y, ds)
                        active_layer.addObject(dim)
                    except:
                        raise
        elif isinstance(obj, Generic.dimension.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 = dimension.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)
