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