#
# Copyright (c) 2002, 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
#
#
# layer handling in GTK
#

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

from PythonCAD.Generic.layer import Layer

#
# layer display callbacks
#

def layer_visibility_toggle(menuitem, gtkimage):
    _layer = menuitem.get_data("layer")
    #
    # fixme - add startAction()/endAction() block
    if _layer.isVisible():
        _layer.setVisibility(False)
    else:
        _layer.setVisibility(True)
    gtkimage.redraw()
    return gtk.FALSE

def layer_hide_children(menuitem, gtkimage):
    _layer = menuitem.get_data("layer")
    _layers = _layer.getSublayers()
    while len(_layers):
        _layer = _layers.pop()
        _layer.hide()
        _layers.extend(_layer.getSublayers())
    gtkimage.redraw()
    return gtk.FALSE

def layer_show_children(menuitem, gtkimage):
    _layer = menuitem.get_data("layer")
    _layers = _layer.getSublayers()
    while len(_layers):
        _layer = _layers.pop()
        _layer.show()
        _layers.extend(_layer.getSublayers())
    gtkimage.redraw()
    return gtk.FALSE

def layer_rename(menuitem, gtkimage):
    _layer = menuitem.get_data("layer")
    _name = _layer.getName()
    _window = gtkimage.getWindow()
    _dialog = gtk.Dialog("Rename Layer", _window,
                         gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                         (gtk.STOCK_OK, gtk.RESPONSE_OK,
                          gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
    _hbox = gtk.HBox(gtk.FALSE, 2)
    _hbox.set_border_width(2)
    _dialog.vbox.pack_start(_hbox, gtk.FALSE, gtk.FALSE, 0)
    
    _label = gtk.Label("Name:")
    _hbox.pack_start(_label, gtk.FALSE, gtk.FALSE, 0)

    _entry = gtk.Entry()
    _entry.set_text(_name)
    _hbox.pack_start(_entry, gtk.TRUE, gtk.TRUE, 0)
    _dialog.show_all()
    _response = _dialog.run()
    if _response == gtk.RESPONSE_OK:
        _name = _entry.get_text()
        if len(_name):
            gtkimage.startAction()
            try:
                _layer.setName(_name)
            finally:
                gtkimage.endAction()
            # gtkimage.renameLayer(_layer)
    _dialog.destroy()
    return gtk.FALSE

def layer_add_child(menuitem, gtkimage):
    _layer = menuitem.get_data("layer")
    _window = gtkimage.getWindow()
    _dialog = gtk.Dialog("Add New Child Layer", _window,
                         gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                         (gtk.STOCK_OK, gtk.RESPONSE_OK,
                          gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
    _hbox = gtk.HBox(gtk.FALSE, 2)
    _hbox.set_border_width(2)
    _dialog.vbox.pack_start(_hbox, gtk.FALSE, gtk.FALSE, 0)
    
    _label = gtk.Label("Name:")
    _hbox.pack_start(_label, gtk.FALSE, gtk.FALSE, 0)
    _entry = gtk.Entry()
    _entry.set_text("NewChildLayer")
    _hbox.pack_start(_entry, gtk.TRUE, gtk.TRUE, 0)
    _dialog.show_all()
    _response = _dialog.run()
    if _response == gtk.RESPONSE_OK:
        _name = _entry.get_text()
        if len(_name):
            _new_layer = Layer(_name)
            gtkimage.startAction()
            try:
                gtkimage.addChildLayer(_new_layer, _layer)
            finally:
                gtkimage.endAction()
            gtkimage.redraw()
    _dialog.destroy()
    return gtk.FALSE

def layer_clear(menuitem, gtkimage):
    _layer = menuitem.get_data("layer")
    gtkimage.startAction()
    try:
        _layer.clear()
    finally:
        gtkimage.endAction()
    gtkimage.redraw()
    return gtk.FALSE

def layer_delete(menuitem, gtkimage):
    #
    # fixme - needs rework
    #
    _layer = menuitem.get_data("layer")
    # _parent = _layer.getParentLayer()
    gtkimage.startAction()
    try:
        gtkimage.delLayer(_layer)
    finally:
        gtkimage.endAction()
    _layer.clear()
    return gtk.FALSE

def make_layer_menu(gtkimage, lyr):
    menu = gtk.Menu()
    item = gtk.MenuItem("Rename")
    item.set_data("layer", lyr) # this is somewhat hackish ...
    item.connect("activate", layer_rename, gtkimage)
    menu.append(item)
    if lyr.isVisible():
        item = gtk.MenuItem("Hide")
    else:
        item = gtk.MenuItem("Show")
    item.set_data("layer", lyr) # so is this ...        
    item.connect("activate", layer_visibility_toggle, gtkimage)
    menu.append(item)
    item = gtk.MenuItem("Add Child Layer")
    item.set_data("layer", lyr) # and this ...
    item.connect("activate", layer_add_child, gtkimage)
    menu.append(item)
    if lyr.hasSublayers():
        item = gtk.MenuItem("Hide Children")
        item.set_data("layer", lyr) # and this ...
        item.connect("activate", layer_hide_children, gtkimage)
        menu.append(item)
        item = gtk.MenuItem("Show Children")
        item.set_data("layer", lyr) # and this ...
        item.connect("activate", layer_show_children, gtkimage)
        menu.append(item)
    else:
        if lyr.getParentLayer() is not None:
            #
            # could also check for external references
            item = gtk.MenuItem("Delete")
            item.set_data("layer", lyr) # and this ...
            item.connect("activate", layer_delete, gtkimage)
            menu.append(item)
    item = gtk.MenuItem("Clear Layer")
    item.set_data("layer", lyr) # and this too ...
    item.connect("activate", layer_clear, gtkimage)
    menu.append(item)
    menu.show_all()
    return menu

def rename_layer(gtkimage):
    active = gtkimage.getActiveLayer()
    window = gtkimage.getWindow()
    name = active.getName()
    dialog = gtk.Dialog("Rename Layer", window,
                        gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                        (gtk.STOCK_OK, gtk.RESPONSE_OK,
                        gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
    hbox = gtk.HBox(gtk.FALSE, 2)
    hbox.set_border_width(2)
    dialog.vbox.pack_start(hbox, gtk.FALSE, gtk.FALSE, 0)
    
    label = gtk.Label("Name:")
    hbox.pack_start(label, gtk.FALSE, gtk.FALSE, 0)

    entry = gtk.Entry()
    entry.set_text(name)
    hbox.pack_start(entry, gtk.TRUE, gtk.TRUE, 0)
    dialog.show_all()
    response = dialog.run()
    if response == gtk.RESPONSE_OK:
        name = entry.get_text()
        if len(name):
            active.setName(name)
    dialog.destroy()

def add_layer(gtkimage):
    window = gtkimage.getWindow()
    dialog = gtk.Dialog("Add New Layer", window,
                        gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                        (gtk.STOCK_OK, gtk.RESPONSE_OK,
                        gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
    hbox = gtk.HBox(gtk.FALSE, 2)
    hbox.set_border_width(2)
    dialog.vbox.pack_start(hbox, gtk.FALSE, gtk.FALSE, 0)
    
    label = gtk.Label("Name:")
    hbox.pack_start(label, gtk.FALSE, gtk.FALSE, 0)
    entry = gtk.Entry()
    entry.set_text("NewLayer")
    hbox.pack_start(entry, gtk.TRUE, gtk.TRUE, 0)
    dialog.show_all()
    response = dialog.run()
    if response == gtk.RESPONSE_OK:
        name = entry.get_text()
        if len(name):
            new_layer = Layer(name)
            gtkimage.addLayer(new_layer)
    dialog.destroy()

def add_child_layer(gtkimage):
    window = gtkimage.getWindow()
    dialog = gtk.Dialog("Add New Child Layer", window,
                        gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                        (gtk.STOCK_OK, gtk.RESPONSE_OK,
                        gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
    hbox = gtk.HBox(gtk.FALSE, 2)
    hbox.set_border_width(2)
    dialog.vbox.pack_start(hbox, gtk.FALSE, gtk.FALSE, 0)
    
    label = gtk.Label("Name:")
    hbox.pack_start(label, gtk.FALSE, gtk.FALSE, 0)
    entry = gtk.Entry()
    entry.set_text("NewChildLayer")
    hbox.pack_start(entry, gtk.TRUE, gtk.TRUE, 0)
    dialog.show_all()
    response = dialog.run()
    if response == gtk.RESPONSE_OK:
        name = entry.get_text()
        if len(name):
            new_layer = Layer(name)
            gtkimage.addChildLayer(new_layer)
    dialog.destroy()

def tree_select_cb(selection, model):
    print "in tree_select_cb()"
    store, iter = selection.get_selected()
    print "store: " + `store`
    print "iter: " + `iter`

class LayerTreeModel(gtk.GenericTreeModel):
    def __init__(self, toplayer):
        gtk.GenericTreeModel.__init__(self)
        self.__toplayer = toplayer
        
    def on_get_flags(self):
        return 0
    
    def on_get_n_columns(self):
        return 1

    def on_get_column_type(self, index):
        return gobject.TYPE_STRING

    def on_get_path(self, node): # FIXME
        # print "on_get_path()"
        # print "node: " + str(node)
        parent = node.getParentLayer()
        child = node
        idx = []
        while parent is not None:
            children = parent.getSublayers()
            for i in range(len(children)):
                if child is children[i]:
                    idx.append(i)
                    child = parent
                    parent = parent.getParentLayer()
        idx.append(0)
        idx.reverse()
        return tuple(idx)
            
    def on_get_iter(self, path):
        '''returns the node corresponding to the given path.
        '''
        # print "on_get_iter()"
        # print "path: " + str(path)
        node = self.__toplayer
        for i in range(1, len(path)):
            idx = path[i]
            children = node.getSublayers()
            node = children[idx]
        return node

    def on_get_tree_path(self, node):
        return self.on_get_path(node)
    
    def on_get_value(self, node, column):
        return node.getName()

    def on_iter_next(self, node):
        '''returns the next node at this level of the tree'''
        parent = node.getParentLayer()
        next = None
        if parent is not None:
            children = parent.getSublayers()
            count = len(children)
            idx = None
            for i in range(len(children)):
                child = children[i]
                if child is node:
                    idx = i + 1
                    break
            if idx is not None and idx < count:
                next = children[idx]
        return next

    def on_iter_children(self, node):
        '''returns the first child of this node'''
        children = node.getSublayers()
        assert len(children), "No sublayers in on_iter_children()!"
        return children[0]
    
    def on_iter_has_child(self, node):
        '''returns true if this node has children'''
        return node.hasSublayers()

    def on_iter_n_children(self, node):
        '''returns the number of sublayers of this node'''
        return len(node.getSublayers())

    def on_iter_nth_child(self, node, n):
        '''returns the nth child of this node'''
        child = None
        if node is not None:
            children = node.getSublayers()
            assert len(children), "No sublayers in on_iter_nth_child()"
            child = children[n]
        return child

    def on_iter_parent(self, node):
        '''returns the parent of this node'''
        return node.getParentLayer()

def activate_layer(gtkimage):
    print "called activate_layer()"
    window = gtkimage.getWindow()
    dialog = gtk.Dialog("Activate Layer", window,
                        gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                        (gtk.STOCK_OK, gtk.RESPONSE_OK,
                        gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
    dialog.vbox.set_size_request(200,300)
    
    sw = gtk.ScrolledWindow()
    sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
    dialog.vbox.pack_start(sw, gtk.TRUE, gtk.TRUE, 2)

    model = LayerTreeModel(gtkimage.getTopLayer())
    tree_view = gtk.TreeView(model)
    select = tree_view.get_selection()
    select.set_mode(gtk.SELECTION_SINGLE)
    select.connect("changed", tree_select_cb, model)
    cell = gtk.CellRendererText()
    column = gtk.TreeViewColumn("Layers", cell, text=0)
    tree_view.append_column(column)
    
    sw.add(tree_view)

    dialog.show_all()
    response = dialog.run()
    if response == gtk.RESPONSE_OK:
        model, iter = tree_view.get_selection().get_selected()
        path = model.get_path(iter)
        layer = model.on_get_iter(path)
        gtkimage.setActiveLayer(layer)
    dialog.destroy()
    
