Index: gazpacho/util.py
===================================================================
--- gazpacho/util.py	(revision 996)
+++ gazpacho/util.py	(working copy)
@@ -48,6 +48,45 @@
 
     return None
 
+def circle_select(leaf_gtk_widget):
+    """Select the parent of the selected widget. If the selected
+    widget is a toplevel widget or there isn't a selected widget in
+    the current branch of the tree, select the leaf widget.
+    """
+    parent_gwidget = get_parent(leaf_gtk_widget)
+
+    # If the leaf widget doesn't have a parent select it.
+    if not parent_gwidget:
+        project.selection_set(leaf_gtk_widget, True)
+        return
+
+    # If there is no or multiple selections, select the leaf widget.
+    project = parent_gwidget.project
+    if not project.selection or len(project.selection) != 1:
+        project.selection_set(leaf_gtk_widget, True)
+        return
+
+    selected = project.selection[0]
+
+    # If the leaf widget is selected, select its parent
+    if leaf_gtk_widget is selected:
+        project.selection_set(parent_gwidget.gtk_widget, True)
+        return
+
+    # Circle through the tree
+    new_selection = leaf_gtk_widget
+    while parent_gwidget:
+        if parent_gwidget.gtk_widget is selected:
+            # Choose the placeholder if selected is toplevel
+            if parent_gwidget.is_toplevel():
+                new_selection = leaf_gtk_widget
+            # otherwise choose the parent
+            else:
+                new_selection = parent_gwidget.get_parent().gtk_widget
+            break
+        parent_gwidget = parent_gwidget.get_parent()
+    project.selection_set(new_selection, True)
+
 def _get_window_positioned_in(widget):
     """This returns the window that the given widget's position is relative to.
     Usually this is the widget's parent's window. But if the widget is a
Index: gazpacho/placeholder.py
===================================================================
--- gazpacho/placeholder.py	(revision 996)
+++ gazpacho/placeholder.py	(working copy)
@@ -114,13 +114,11 @@
                 self._app.command_manager.create(self._app.add_class, self,
                                                  None)
 
-                
-            # Select the parent if shift is pressed
+            # Shift clicking circles through the widget tree by
+            # choosing the parent of the currently selected widget.
             elif event.state & gtk.gdk.SHIFT_MASK:
-                gwidget = util.get_parent(self)
-                if gwidget is not None:
-                    gwidget.project.selection_set(gwidget.gtk_widget, True)
-                    
+                util.circle_select(self)
+
             # otherwise we should be able to select placeholder
             # for paste operations  
             else:
@@ -131,7 +129,7 @@
             popup.pop(event)
 
         return True
-                
+
     def do_popup_menu(self):
         popup = PlaceholderPopup(self._app, self)
         popup.pop(None)
Index: gazpacho/widget.py
===================================================================
--- gazpacho/widget.py	(revision 996)
+++ gazpacho/widget.py	(working copy)
@@ -418,15 +418,22 @@
                                                     top_x, top_y)
         
     def _button_press_event(self, widget, event):
-        glade_widget = self._retrieve_from_position(widget,
-                                                    int(event.x),
-                                                    int(event.y))
-        widget = glade_widget.gtk_widget
+        gwidget = self._retrieve_from_position(widget,
+                                               int(event.x),
+                                               int(event.y))
+        widget = gwidget.gtk_widget
         # Make sure to grab focus, since we may stop default handlers
         if widget.flags() & gtk.CAN_FOCUS:
             widget.grab_focus()
 
         if event.button == 1:
+
+            # Shift clicking circles through the widget tree by
+            # choosing the parent of the currently selected widget.
+            if event.state & gtk.gdk.SHIFT_MASK:
+                util.circle_select(widget)
+                return True
+
             # if it's already selected don't stop default handlers,
             # e.g toggle button
             if util.has_nodes(widget):
@@ -436,7 +443,7 @@
             return True
         elif event.button == 3:
             app = self.project._app
-            popup = Popup(app, glade_widget)
+            popup = Popup(app, gwidget)
             popup.pop(event)
             return True
 
