#+TITLE: Python CAD Tutorial 10 - Extending the GTK interface  
#+DATE: 2013-10-10 12:00:00 UTC
#+DESCRIPTION: Add new GUI elements to initiate drawing of various shapes 
#+FILETAGS: GTK-3:python:cad:opengl
#+CATEGORY: python
#+SLUG: 10-cad-extending-the-interface
#+THUMBNAIL: ../../../images/cad/tut10-interface.png
#+BEGIN_COMMENT
.. title: Python CAD Tutorial 10 - Extending the GTK interface 
.. slug: 10-cad-extending-the-interface.org
.. date: 2013-10-10 12:00:00 UTC
.. tags: GTK-3, python, cad, opengl
.. category: python
.. description: Add new GUI elements to initiate drawing of various shapes 
.. type: text
#+END_COMMENT

[[https://code.launchpad.net/~oly/fabricad/tut10][View/Download Code]]


#+CAPTION: extended gui
[[../../../images/cad/tut10-interface.png]]

We have created some buttons in glade and connected the events so we can switch between the object types ie circle polygon and closed polygons.

Create a class for managing the treeview, this widget is very flexible and can be difficult to work with so abstract the details away. This will be used for showing the layers we have in the project and the objects under each layer.

#+BEGIN_SRC python
import os
import sys
from gi.repository import Gtk, GdkX11, Gdk


class objectList:
    treeview = None
    treemodel = None

    selected = 'workspace'

    def __init__(self, workspace, treeview):
        self.treeview = treeview
        self.workspace = workspace

        # connect the treeview events, capture row selection and row click
        self.treeview.connect('row-activated', self.selection)
        self.treeview.connect('button_press_event', self.show_menu)

        #add a tree store model so everything has a hierarchy
        self.treemodel = Gtk.TreeStore(str)
        self.treeview.set_model(self.treemodel)

        # append colmun headers to the treeview and cell renderer
        column = Gtk.TreeViewColumn("Objects")
        self.treeview.append_column(column)

        cell = Gtk.CellRendererText()
        column.pack_start(cell, False)
        column.add_attribute(cell, "text", 0)

        # populate the objects from the layers
        self.populate()
        self.menu()

    def populate(self):
        self.treemodel.clear()
        for layer in self.workspace.keys():
            tree_iter = self.append(layer)
            for part in self.workspace[layer]:
                self.append(part.name, tree_iter)

    def menu(self):
        self.layer_menu = Gtk.Menu()
        
        self.layer_menu_item = Gtk.MenuItem("Display")
        #self.layer_menu_item.connect("activate", self.toggle_value_handler, 'show')
        self.layer_menu.append(self.layer_menu_item)

        self.layer_menu_item = Gtk.MenuItem("Colour")
        self.layer_menu.append(self.layer_menu_item)

    def show_menu(self, tv, event):
        if event.button == 2:
            model = tv.get_model()
            treeiter = model.get_iter(treepath)
            self.selected = model.get_value(treeiter, 0)
        
        if event.button == 3:
            self.layer_menu.show_all()
            self.layer_menu.popup(None, None, None, None, 1, 0)

    def append(self, name, parent=None):
        myiter = self.treemodel.insert_after(parent, None)
        self.treemodel.set_value(myiter, 0, name)
        return myiter

    def selection(self, tv, treepath, tvcolumn):
        model = tv.get_model()
        treeiter = model.get_iter(treepath)
        self.selected = model.get_value(treeiter, 0)
#+END_SRC

The workspace class below is a management class. It will contain various methods for working with the visible objects. It will also manage our layers. For now we will add simple functions, for example 'append' (which will add objects to a layer).In the main mycad.py file, you can see that our new polygon is contained and updated through the shape class. Later on we will attach this to our GUI so we can dynamically add primitives as we need them.

#+BEGIN_SRC python
class objectList:
    treeview = None
    treemodel = None

    selected = 'workspace'

    def __init__(self, workspace, treeview):
        self.treeview = treeview
        self.workspace = workspace

        # connect the treeview events, capture row selection and row click
        self.treeview.connect('row-activated', self.selection)
        self.treeview.connect('button_press_event', self.show_menu)

        #add a tree store model so everything has a hierarchy
        self.treemodel = Gtk.TreeStore(str)
        self.treeview.set_model(self.treemodel)

        # append colmun headers to the treeview and cell renderer
        column = Gtk.TreeViewColumn("Objects")
        self.treeview.append_column(column)

        cell = Gtk.CellRendererText()
        column.pack_start(cell, False)
        column.add_attribute(cell, "text", 0)

        # populate the objects from the layers
        self.populate()
        self.menu()

    def populate(self):
        self.treemodel.clear()
        for layer in self.workspace.keys():
            tree_iter = self.append(layer)
            for part in self.workspace[layer]:
                self.append(part.name, tree_iter)

    def menu(self):
        self.layer_menu = Gtk.Menu()
        
        self.layer_menu_item = Gtk.MenuItem("Display")
        #self.layer_menu_item.connect("activate", self.toggle_value_handler, 'show')
        self.layer_menu.append(self.layer_menu_item)

        self.layer_menu_item = Gtk.MenuItem("Colour")
        self.layer_menu.append(self.layer_menu_item)

    def show_menu(self, tv, event):
        if event.button == 2:
            model = tv.get_model()
            treeiter = model.get_iter(treepath)
            self.selected = model.get_value(treeiter, 0)
        
        if event.button == 3:
            self.layer_menu.show_all()
            self.layer_menu.popup(None, None, None, None, 1, 0)

    def append(self, name, parent=None):
        myiter = self.treemodel.insert_after(parent, None)
        self.treemodel.set_value(myiter, 0, name)
        return myiter

    def selection(self, tv, treepath, tvcolumn):
        model = tv.get_model()
        treeiter = model.get_iter(treepath)
        self.selected = model.get_value(treeiter, 0)
#+END_SRC

