context: 
  using System;
  using System.Collections;
  using Stetic.Wrapper;
  using Mono.Unix;
  
  namespace Stetic
  {
  	internal class ActionGroupToolbar: Gtk.Toolbar
  	{
  		Wrapper.ActionGroupCollection actionGroups;
  		Gtk.ComboBox combo;
  		bool updating;
  		ActionGroup currentGroup;
  		ArrayList internalButtons = new ArrayList ();
  		bool singleGroupMode;
  		bool allowBinding;
  		ActionGroupDesignerFrontend frontend;
  		Editor.ActionGroupEditor agroupEditor;
  		Gtk.ToolButton addButton;
  		Gtk.ToolButton removeButton;
  		
  		public event ActionGroupEventHandler ActiveGroupChanged;
  		public event ActionGroupEventHandler ActiveGroupCreated;
  		
  		public ActionGroupToolbar (ActionGroupDesignerFrontend frontend, bool singleGroupMode)
  		{
  			Initialize (frontend, null, singleGroupMode);
  		}
  		
  		public ActionGroupToolbar (ActionGroupDesignerFrontend frontend, Wrapper.ActionGroup actionGroup)
  		{
  			currentGroup = actionGroup;
  			Initialize (frontend, null, true);
  		}
  		
  		public ActionGroupToolbar (ActionGroupDesignerFrontend frontend, Wrapper.ActionGroupCollection actionGroups)
  		{
  			Initialize (frontend, actionGroups, false);
  		}
  		
  		public bool AllowActionBinding {
  			get { return allowBinding; }
  			set { allowBinding = value; }
  		}
  		
  		void Initialize (ActionGroupDesignerFrontend frontend, Wrapper.ActionGroupCollection actionGroups, bool singleGroupMode)
  		{
  			this.frontend = frontend;
  			this.singleGroupMode = singleGroupMode;
  			IconSize = Gtk.IconSize.SmallToolbar;
  			Orientation = Gtk.Orientation.Horizontal;
  			ToolbarStyle = Gtk.ToolbarStyle.BothHoriz;
  			
  			combo = Gtk.ComboBox.NewText ();
  			
  			if (!singleGroupMode) {
  				combo.Changed += OnActiveChanged;
  
  				Gtk.ToolItem comboItem = new Gtk.ToolItem ();
  				Gtk.HBox cbox = new Gtk.HBox ();
  				cbox.PackStart (new Gtk.Label (Catalog.GetString ("Action Group:") + " "), false, false, 3);
  				cbox.PackStart (combo, true, true, 3);
  				comboItem.Add (cbox);
  				comboItem.ShowAll ();
  				Insert (comboItem, -1);
  				internalButtons.Add (comboItem);
  				
  				addButton = new Gtk.ToolButton (Gtk.Stock.Add);
  				addButton.Clicked += OnAddGroup;
  				Insert (addButton, -1);
  				internalButtons.Add (addButton);
  				
  				removeButton = new Gtk.ToolButton (Gtk.Stock.Remove);
  				removeButton.Clicked += OnRemoveGroup;
  				Insert (removeButton, -1);
  				internalButtons.Add (removeButton);
  				
  				ActionGroups = actionGroups;
  				
  				if (actionGroups != null && actionGroups.Count > 0)
  					combo.Active = 0;
  			} else {
  				UpdateActionCommands (null);
  			}
  
  			ShowAll ();
  		}
  		
  		public override void Dispose ()
  		{
  			if (combo == null)
  				return;
  
  			combo.Changed -= OnActiveChanged;
  			combo = null;
  			if (addButton != null) {
  				addButton.Clicked -= OnAddGroup;
  				removeButton.Clicked -= OnRemoveGroup;
  			}
  				
  			if (agroupEditor != null) {
  				agroupEditor.SelectionChanged -= OnEditorSelectionChanged;
  				agroupEditor = null;
  			}
  			
  			if (!singleGroupMode)
  				ActionGroups = null;
  			base.Dispose ();
  		}
  		
  		public Wrapper.ActionGroupCollection ActionGroups {
  			get { return actionGroups; }
  			set {
  				if (singleGroupMode)
  					throw new InvalidOperationException ("ActionGroups can't be set in single group mode");
  
  				if (actionGroups != null) {
  					actionGroups.ActionGroupAdded -= OnCollectionChanged;
  					actionGroups.ActionGroupRemoved -= OnCollectionChanged;
  					actionGroups.ActionGroupChanged -= OnCollectionChanged;
  				}
  				
  				this.actionGroups = value;
  				
  				if (actionGroups != null) {
  					actionGroups.ActionGroupAdded += OnCollectionChanged;
  					actionGroups.ActionGroupRemoved += OnCollectionChanged;
  					actionGroups.ActionGroupChanged += OnCollectionChanged;
  				}
  				Refresh ();
  			}
  		}
  		
  		public void Bind (Editor.ActionGroupEditor agroupEditor)
  		{
  			this.agroupEditor = agroupEditor;
  			agroupEditor.SelectionChanged += OnEditorSelectionChanged;
  			agroupEditor.ActionGroup = ActiveGroup;
  		}
  		
  		public void OnEditorSelectionChanged (object s, EventArgs a)
  		{
  			UpdateActionCommands (agroupEditor.SelectedAction);
  		}
  		
  		public ActionGroup ActiveGroup {
  			get {
  				return currentGroup;
  			}
  			set {
  				if (singleGroupMode) {
  					currentGroup = value;
  					UpdateActionCommands (null);
  					NotifyActiveGroupChanged ();
  				} else {
  					int i = actionGroups.IndexOf (value);
  					if (i != -1)
  						combo.Active = i;
  				}
  			}
  		}
  		
  		void Refresh ()
  		{
  			if (singleGroupMode || combo == null)
  				return;
  
  			while (combo.Model.IterNChildren () > 0)
  				combo.RemoveText (0);
  			if (actionGroups != null) {
  				foreach (ActionGroup group in actionGroups)
  					combo.AppendText (group.Name);
  			}
  		}
  		
  		void OnCollectionChanged (object s, ActionGroupEventArgs args)
  		{
  			// Avoid firing the selection change event if the selected
  			// group is the same after the refresh
  			ActionGroup oldGroup = currentGroup;
  			updating = true;
  			
  			int i = combo.Active;
  			Refresh ();
  			if (actionGroups.Count == 0) {
  				combo.Sensitive = false;
  				currentGroup = null;
  			}
  			else {
  				combo.Sensitive = true;
  				if (i == -1)
  					i = 0;
  				if (i < actionGroups.Count)
  					combo.Active = i;
  				else
  					combo.Active = actionGroups.Count - 1;
  				currentGroup = (ActionGroup) actionGroups [combo.Active];
  			}
  			updating = false;
  			if (currentGroup != oldGroup)
  				OnActiveChanged (null, null);
  			frontend.NotifyModified ();
  		}
  		
  		void OnAddGroup (object s, EventArgs args)
  		{
  			ActionGroup group = new ActionGroup ();
  			group.Name = Catalog.GetString ("New Action Group");
  			actionGroups.Add (group);
  			combo.Active = actionGroups.Count - 1;
  			if (ActiveGroupCreated != null)
  				ActiveGroupCreated (this, new ActionGroupEventArgs (ActiveGroup));
  			
  			if (agroupEditor != null)
  				agroupEditor.StartEditing ();
  		}
  		
  		void OnRemoveGroup (object s, EventArgs args)
  		{
  			if (combo.Active != -1)
  				actionGroups.RemoveAt (combo.Active);
  		}
  		
  		void OnActiveChanged (object s, EventArgs args)
  		{
  			if (!updating) {
  				UpdateActionCommands (null);
  				if (combo.Active != -1)
  					currentGroup = (ActionGroup) actionGroups [combo.Active];
  				else
  					currentGroup = null;
  				NotifyActiveGroupChanged ();
  			}
  		}
  		
  		void NotifyActiveGroupChanged ()
  		{
  			if (agroupEditor != null)
  				agroupEditor.ActionGroup = ActiveGroup;
  			if (ActiveGroupChanged != null)
  				ActiveGroupChanged (this, new ActionGroupEventArgs (ActiveGroup));
  		}
  		
  		void UpdateActionCommands (Wrapper.Action action)
  		{
  			foreach (Gtk.Widget w in Children) {
  				if (!internalButtons.Contains (w)) {
  					Remove (w);
  					w.Destroy ();
  				}
  			}
  			AddActionCommands (action);
  				
  			if (internalButtons.Count > 0 && internalButtons.Count != Children.Length) {
  
gt: 				Insert (new Gtk.SeparatorToolItem (), internalButtons.Count);