diff --git a/ui/lib/panels.js b/ui/lib/panels.js
index cb8618a9..aa2f0df8 100755
--- a/ui/lib/panels.js
+++ b/ui/lib/panels.js
@@ -84,6 +84,13 @@ function _resetSortedElem(elem){
 }
 
 
+function isPanelVisible(panel){
+	return panel.prop('open')
+			&& (panel.parents('.panel').prop('open')
+				|| panel.parents('.side-panel').width() > 20)
+}
+
+
 // wrap a sub-panel with a new panel...
 // 
 function wrapWithPanel(panel, parent, offset){
@@ -98,11 +105,17 @@ function wrapWithPanel(panel, parent, offset){
 
 // close the panel and fire close events on it and all sub-panels...
 //
+// XXX do we need a panelRemoved event???
+// 		...and a symmetrical panelCreated??
 function closePanel(panel){
-	panel.find('.sub-panel')
-		.trigger('panelClosing')
+	panel.find('.sub-panel').each(function(){
+		var p = $(this)
+		if(p.prop('open')){
+			p.trigger('panelClosing', p)
+		}
+	})
 	panel
-		.trigger('panelClosing')
+		.trigger('panelClosing', panel)
 		.remove()
 }
 
@@ -124,7 +137,7 @@ function makePanel(title, parent, open, keep_empty, close_button){
 	var panel = $('
')
 		.addClass('side-panel panel-content ' + side)
 		.attr('autohide', autohide)
+		// XXX trigger open/close events on hide/show..
+		// XXX
 		// toggle auto-hide...
 		.dblclick(function(e){
 			var elem = $(this)
@@ -278,6 +314,9 @@ function makeSidePanel(side, parent, autohide){
 		panel.appendTo(parent)
 	}
 
+	// NOTE: no need to call the panelOpening event here as at this point
+	// 		no one had the chance to bind a handler...
+
 	return panel
 }
 
@@ -302,7 +341,16 @@ function makeSubPanel(title, content, parent, open, content_resizable){
 	var sub_panel = $('