Пример #1
0
 public TGContextMenuEventArgs(TabGroupLeaf tgl, Controls.TabControl tc,
                               Controls.TabPage tp, PopupMenu contextMenu)
     : base(tgl, tc, tp)
 {
     // Definie initial state
     _contextMenu = contextMenu;
 }
Пример #2
0
        internal void MovePageToLeaf(TabGroupLeaf leaf)
        {
            // Remember original auto compact mode
            bool autoCompact = _tabbedGroups.AutoCompact;

            // Turn mode off as it interferes with reorganisation
            _tabbedGroups.AutoCompact = false;

            // Get the requested tab page to be moved to new leaf
            TabPage tp = _tabControl.SelectedTab;

            // Remove page from ourself
            _tabControl.TabPages.Remove(tp);

            // Add into the new leaf
            leaf.TabPages.Add(tp);

            // Make new leaf the active one
            _tabbedGroups.ActiveLeaf = leaf;

            TabControl tc = leaf.GroupControl as Controls.TabControl;

            // Select the newly added page
            tc.SelectedTab = tp;

            // Reset compacting mode as we have updated the structure
            _tabbedGroups.AutoCompact = autoCompact;

            // Do we need to compact?
            if (_tabbedGroups.AutoCompact)
            {
                _tabbedGroups.Compact();
            }
        }
 public TGContextMenuEventArgs(TabGroupLeaf tgl, Controls.TabControl tc, 
     Controls.TabPage tp, PopupMenu contextMenu)
     : base(tgl, tc, tp)
 {
     // Definie initial state
     _contextMenu = contextMenu;
 }
Пример #4
0
		protected bool SelectPreviousTab() {
			// If no active leaf...
			if (_activeLeaf == null)
				SelectLastPage();
			else {
				bool selectLast = false;
				TabGroupLeaf startLeaf = _activeLeaf;
				TabGroupLeaf thisLeaf = startLeaf;
                
				do {
					// Access to the embedded tab control
					Controls.TabControl tc = thisLeaf.GroupControl as Controls.TabControl;
                
					// Does it have any pages?
					if (tc.TabPages.Count > 0) {
						// Are we allowed to select the last page?
						if (selectLast) {
							// Do it and exit loop
							tc.SelectedIndex = tc.TabPages.Count - 1;
                            
							// Must ensure this becomes the active leaf
							if (thisLeaf != _activeLeaf)
								ActiveLeaf = thisLeaf;
                                
							break;
						}
						else {
							// Is there another page before the selected one?
							if (tc.SelectedIndex > 0) {
								// Select previous page and exit loop
								tc.SelectedIndex = tc.SelectedIndex - 1;
								break;
							}         
						}           
					}
                    
					selectLast = true;
                    
					// Find the previous leaf in sequence
					thisLeaf = PreviousLeaf(thisLeaf);
                    
					// No more leafs, wrap back to first
					if (thisLeaf == null)
						thisLeaf = LastLeaf();

					// Back at starting leaf?
					if (thisLeaf == startLeaf) {
						// If it was not the first page that we started from
						if (tc.SelectedIndex == 0) {
							// Then we have circles all the way around, select last page
							tc.SelectedIndex = tc.TabPages.Count - 1;
						}
					}

				} while(thisLeaf != startLeaf);
			}
            
			return true;
		}
Пример #5
0
 public TGCloseRequestEventArgs(TabGroupLeaf tgl, Controls.TabControl tc, Controls.TabPage tp)
 {
     // Definie initial state
     _tgl    = tgl;
     _tc     = tc;
     _tp     = tp;
     _cancel = false;
 }
Пример #6
0
 public Target(Rectangle hotRect, Rectangle drawRect, TabGroupLeaf leaf, TargetActions action)
 {
     // Define state
     _hotRect  = hotRect;
     _drawRect = drawRect;
     _leaf     = leaf;
     _action   = action;
 }
Пример #7
0
 public Target(Rectangle hotRect, Rectangle drawRect, TabGroupLeaf leaf, TargetActions action)
 {
     // Define state
     _hotRect = hotRect;
     _drawRect = drawRect;
     _leaf = leaf;
     _action = action;
 }
 public TGCloseRequestEventArgs(TabGroupLeaf tgl, Controls.TabControl tc, Controls.TabPage tp)
 {
     // Definie initial state
     _tgl = tgl;
     _tc = tc;
     _tp = tp;
     _cancel = false;
 }
Пример #9
0
		public TabGroupLeaf PreviousLeaf(TabGroupLeaf current) {
			// Get parent of the provided leaf
			TabGroupSequence tgs = current.Parent as TabGroupSequence;
            
			// Must have a valid parent sequence
			if (tgs != null)
				return RecursiveFindLeafInSequence(tgs, current, false);
			else
				return null;
		}
Пример #10
0
        internal void OnMovePrevious(object sender, EventArgs e)
        {
            // Find the previous leaf node
            TabGroupLeaf prev = _tabbedGroups.PreviousLeaf(this);

            // Must always be valid!
            if (prev != null)
            {
                MovePageToLeaf(prev);
            }
        }
Пример #11
0
        internal void OnMoveNext(object sender, EventArgs e)
        {
            // Find the previous leaf node
            TabGroupLeaf next = _tabbedGroups.NextLeaf(this);

            // Must always be valid!
            if (next != null)
            {
                MovePageToLeaf(next);
            }
        }
Пример #12
0
        internal void NewHorizontalGroup(TabGroupLeaf sourceLeaf, bool before)
        {
            TabGroupSequence tgs = this.Parent as TabGroupSequence;

            // We must have a parent sequence!
            if (tgs != null)
            {
                tgs.Direction = Direction.Horizontal;
                AddGroupToSequence(tgs, sourceLeaf, before);
            }
        }
Пример #13
0
        protected void AddGroupToSequence(TabGroupSequence tgs, TabGroupLeaf sourceLeaf, bool before)
        {
            // Remember original auto compact mode
            bool autoCompact = _tabbedGroups.AutoCompact;

            // Turn mode off as it interferes with reorganisation
            _tabbedGroups.AutoCompact = false;

            // Find our index into parent collection
            int pos = tgs.IndexOf(this);

            TabGroupLeaf newGroup = null;

            // New group inserted before existing one?
            if (before)
            {
                newGroup = tgs.InsertNewLeaf(pos);
            }
            else
            {
                // No, are we at the end of the collection?
                if (pos == (tgs.Count - 1))
                {
                    newGroup = tgs.AddNewLeaf();
                }
                else
                {
                    newGroup = tgs.InsertNewLeaf(pos + 1);
                }
            }

            // Get tab control for source leaf
            Controls.TabControl tc = sourceLeaf.GroupControl as Controls.TabControl;

            TabPage tp = tc.SelectedTab;

            // Remove page from ourself
            tc.TabPages.Remove(tp);

            // Add into the new leaf
            newGroup.TabPages.Add(tp);

            // Reset compacting mode as we have updated the structure
            _tabbedGroups.AutoCompact = autoCompact;

            // Do we need to compact?
            if (_tabbedGroups.AutoCompact)
            {
                _tabbedGroups.Compact();
            }
        }
Пример #14
0
        public override bool ContainsProminent(bool recurse)
        {
            // Cache the currently selected prominent group
            TabGroupLeaf prominent = _tabbedGroups.ProminentLeaf;

            // Valid value to test against?
            if (prominent != null)
            {
                return(this == prominent);
            }
            else
            {
                return(false);
            }
        }
Пример #15
0
        private void ExternalDrop(Crownwood.Magic.Controls.TabbedGroups tg,
                                  Crownwood.Magic.Controls.TabGroupLeaf tgl,
                                  Crownwood.Magic.Controls.TabControl tc,
                                  Crownwood.Magic.Controls.TabbedGroups.DragProvider dp)
        {
            // Create a new tab page
            Crownwood.Magic.Controls.TabPage tp = NewTabPage();

            // Define the text in this control
            (tp.Control as RichTextBox).Text = "Dragged from node '" + (string)dp.Tag + "'";

            // We want the new page to become selected
            tp.Selected = true;

            // Add new page into the destination tab control
            tgl.TabPages.Add(tp);
        }
Пример #16
0
		protected TabGroupLeaf RecursiveFindLeafInSequence(TabGroupSequence tgs, bool forwards) {
			int count = tgs.Count;
        
			for(int i=0; i<count; i++) {
				// Index depends on which direction we are processing
				int index = (forwards == true) ? i : (tgs.Count - i - 1);
                
				// Is this the needed leaf node?
				if (tgs[index].IsLeaf)
					return tgs[index] as TabGroupLeaf;
				else {
					// Need to make a recursive check inside group
					TabGroupLeaf leaf = RecursiveFindLeafInSequence(tgs[index] as TabGroupSequence, forwards);

					if (leaf != null)
						return leaf;
				}
			}
            
			// Still no luck
			return null;
		}
Пример #17
0
		protected TabGroupLeaf RecursiveFindLeafInSequence(TabGroupSequence tgs, TabGroupBase tgb, bool forwards) {
			int count = tgs.Count;
			int index = tgs.IndexOf(tgb);
        
			// Are we look for entries after the provided one?
			if (forwards) {
				for(int i=index+1; i<count; i++) {
					// Is this the needed leaf node?
					if (tgs[i].IsLeaf)
						return tgs[i] as TabGroupLeaf;
					else {
						TabGroupLeaf leaf = RecursiveFindLeafInSequence(tgs[i] as TabGroupSequence, forwards);
                    
						if (leaf != null)
							return leaf;
					}
				}
			}
			else {
				// Now try each entry before that given
				for(int i=index-1; i>=0; i--) {
					// Is this the needed leaf node?
					if (tgs[i].IsLeaf)
						return tgs[i] as TabGroupLeaf;
					else {
						TabGroupLeaf leaf = RecursiveFindLeafInSequence(tgs[i] as TabGroupSequence, forwards);
                    
						if (leaf != null)
							return leaf;
					}
				}
			}
                        
			// Still no luck, try our own parent
			if (tgs.Parent != null)
				return RecursiveFindLeafInSequence(tgs.Parent as TabGroupSequence, tgs, forwards);
			else
				return null;
		}
Пример #18
0
        public TargetManager(TabbedGroups host, TabGroupLeaf leaf, Controls.TabControl source)
        {
            // Define state
            _host       = host;
            _leaf       = leaf;
            _source     = source;
            _lastTarget = null;

            // Create collection to hold generated targets
            _targets = new TargetCollection();

            // Process each potential leaf in turn
            TabGroupLeaf tgl = host.FirstLeaf();

            while (tgl != null)
            {
                // Create all possible targets for this leaf
                CreateTargets(tgl);

                // Enumerate all leafs
                tgl = host.NextLeaf(tgl);
            }
        }
Пример #19
0
 public void ResetActiveLeaf()
 {
     ActiveLeaf = null;
 }
Пример #20
0
 public void ResetProminentLeaf()
 {
     ProminentLeaf = null;
 }
Пример #21
0
 public virtual void OnExternalDrop(TabGroupLeaf tgl, Controls.TabControl tc, DragProvider dp)
 {
     // Has anyone registered for the event?
     if (ExternalDrop != null)
         ExternalDrop(this, tgl, tc, dp);
 }
Пример #22
0
		public void ResetProminentLeaf() {
			ProminentLeaf = null;
		}
        protected void AddGroupToSequence(TabGroupSequence tgs, TabGroupLeaf sourceLeaf, bool before)
        {
            // Remember original auto compact mode
            bool autoCompact = _tabbedGroups.AutoCompact;

            // Turn mode off as it interferes with reorganisation
            _tabbedGroups.AutoCompact = false;

            // Find our index into parent collection
            int pos = tgs.IndexOf(this);

            TabGroupLeaf newGroup = null;

            // New group inserted before existing one?
            if (before)
                newGroup = tgs.InsertNewLeaf(pos);
            else
            {
                // No, are we at the end of the collection?
                if (pos == (tgs.Count - 1))
                    newGroup = tgs.AddNewLeaf();
                else
                    newGroup = tgs.InsertNewLeaf(pos + 1);
            }

            // Get tab control for source leaf
            Controls.TabControl tc = sourceLeaf.GroupControl as Controls.TabControl;

            TabPage tp = tc.SelectedTab;

            // Remove page from ourself
            tc.TabPages.Remove(tp);

            // Add into the new leaf
            newGroup.TabPages.Add(tp);

            // Reset compacting mode as we have updated the structure
            _tabbedGroups.AutoCompact = autoCompact;

            // Do we need to compact?
            if (_tabbedGroups.AutoCompact)
                _tabbedGroups.Compact();
        }
Пример #24
0
        protected void CreateTargets(TabGroupLeaf leaf)
        {
            // Grab the underlying tab control
            Controls.TabControl tc = leaf.GroupControl as Controls.TabControl;

            // Get the total size of the tab control itself in screen coordinates
            Rectangle totalSize = tc.RectangleToScreen(tc.ClientRectangle);

            // We do not allow a page to be transfered to its own leaf!
            if (leaf != _leaf)
            {
                Rectangle tabsSize = tc.RectangleToScreen(tc.TabsAreaRect);

                // Give priority to the tabs area being used to transfer page
                _targets.Add(new Target(tabsSize, totalSize, leaf, Target.TargetActions.Transfer));
            }

            // Can only create new groups if moving relative to a new group
            // or we have more than one page in the originating group
            if ((leaf != _leaf) || ((leaf == _leaf) && _leaf.TabPages.Count > 1))
            {
                int horzThird = totalSize.Width / 3;
                int vertThird = totalSize.Height / 3;

                // Create the four spacing rectangle
                Rectangle leftRect = new Rectangle(totalSize.X, totalSize.Y, horzThird, totalSize.Height);
                Rectangle rightRect = new Rectangle(totalSize.Right - horzThird, totalSize.Y, horzThird, totalSize.Height);
                Rectangle topRect = new Rectangle(totalSize.X, totalSize.Y, totalSize.Width, vertThird);
                Rectangle bottomRect = new Rectangle(totalSize.X, totalSize.Bottom - vertThird, totalSize.Width, vertThird);

                TabGroupSequence tgs = _leaf.Parent as TabGroupSequence;

                // Can only create new groups in same direction, unless this is the only leaf
                if (tgs.Count <= 1)
                {
                    // Add each new target
                    _targets.Add(new Target(leftRect, leftRect, leaf, Target.TargetActions.GroupLeft));
                    _targets.Add(new Target(rightRect, rightRect, leaf, Target.TargetActions.GroupRight));
                    _targets.Add(new Target(topRect, topRect, leaf, Target.TargetActions.GroupTop));
                    _targets.Add(new Target(bottomRect, bottomRect, leaf, Target.TargetActions.GroupBottom));
                }
                else
                {
                    if (tgs.Direction == Direction.Vertical)
                    {
                        _targets.Add(new Target(topRect, topRect, leaf, Target.TargetActions.GroupTop));
                        _targets.Add(new Target(bottomRect, bottomRect, leaf, Target.TargetActions.GroupBottom));
                    }
                    else
                    {
                        _targets.Add(new Target(leftRect, leftRect, leaf, Target.TargetActions.GroupLeft));
                        _targets.Add(new Target(rightRect, rightRect, leaf, Target.TargetActions.GroupRight));
                    }
                }
            }

            // We do not allow a page to be transfered to its own leaf!
            if (leaf != _leaf)
            {
                // Any remaining space is used to
                _targets.Add(new Target(totalSize, totalSize, leaf, Target.TargetActions.Transfer));
            }
        }
        internal void MovePageToLeaf(TabGroupLeaf leaf)
        {
            // Remember original auto compact mode
            bool autoCompact = _tabbedGroups.AutoCompact;

            // Turn mode off as it interferes with reorganisation
            _tabbedGroups.AutoCompact = false;

            // Get the requested tab page to be moved to new leaf
            TabPage tp = _tabControl.SelectedTab;

            // Remove page from ourself
            _tabControl.TabPages.Remove(tp);

            // Add into the new leaf
            leaf.TabPages.Add(tp);

            // Make new leaf the active one
            _tabbedGroups.ActiveLeaf = leaf;

            TabControl tc = leaf.GroupControl as Controls.TabControl;

            // Select the newly added page
            tc.SelectedTab = tp;

            // Reset compacting mode as we have updated the structure
            _tabbedGroups.AutoCompact = autoCompact;

            // Do we need to compact?
            if (_tabbedGroups.AutoCompact)
                _tabbedGroups.Compact();
        }
        internal void NewVerticalGroup(TabGroupLeaf sourceLeaf, bool before)
        {
            TabGroupSequence tgs = this.Parent as TabGroupSequence;

            // We must have a parent sequence!
            if (tgs != null)
            {
                tgs.Direction = Direction.Vertical;
                AddGroupToSequence(tgs, sourceLeaf, before);
            }
        }
Пример #27
0
        public override void LoadFromXml(XmlTextReader xmlIn)
        {
            // Grab the expected attributes
            string rawCount = xmlIn.GetAttribute(0);
            string rawUnique = xmlIn.GetAttribute(1);
            string rawSpace = xmlIn.GetAttribute(2);
            string rawDirection = xmlIn.GetAttribute(3);

            // Convert to correct types
            int count = Convert.ToInt32(rawCount);
            int unique = Convert.ToInt32(rawUnique);
            Decimal space = Convert.ToDecimal(rawSpace);
            Direction direction = (rawDirection == "Horizontal" ? Direction.Horizontal :
                                                                  Direction.Vertical);

            // Update myself with new values
            _unique = unique;
            _space = space;
            _direction = direction;

            // Load each of the children
            for(int i=0; i<count; i++)
            {
                // Read the next Element
                if (!xmlIn.Read())
                    throw new ArgumentException("An element was expected but could not be read in");

                TabGroupBase newElement = null;

                // Is it another sequence?
                if (xmlIn.Name == "Sequence")
                    newElement = new TabGroupSequence(_tabbedGroups, this);
                else if (xmlIn.Name == "Leaf")
                    newElement = new TabGroupLeaf(_tabbedGroups, this);
                else
                    throw new ArgumentException("Unknown element was encountered");

                bool expectEndElement = !xmlIn.IsEmptyElement;

                // Load its config
                newElement.LoadFromXml(xmlIn);

                // Add new element to the collection
                Add(newElement);

                // Do we expect and end element to occur?
                if (expectEndElement)
                {
                    // Move past the end element
                    if (!xmlIn.Read())
                        throw new ArgumentException("Could not read in next expected node");

                    // Check it has the expected name
                    if (xmlIn.NodeType != XmlNodeType.EndElement)
                        throw new ArgumentException("EndElement expected but not found");
                }
            }
        }
Пример #28
0
        public TabGroupLeaf InsertNewLeaf(int index)
        {
            // Range check index
            if (index < 0)
                throw new ArgumentOutOfRangeException("index", index, "Insert index must be at least 0");

            if (index >= _children.Count)
                throw new ArgumentOutOfRangeException("index", index, "Cannot insert after end of current entries");

            // Create a new leaf instance with correct back references
            TabGroupLeaf tgl = new TabGroupLeaf(_tabbedGroups, this);

            // Insert into correct collection position
            Insert(index, tgl);

            // Return its position in collection
            return tgl;
        }
Пример #29
0
		public void LoadConfigFromStream(Stream stream) {
			XmlTextReader xmlIn = new XmlTextReader(stream); 

			// Ignore whitespace, not interested
			xmlIn.WhitespaceHandling = WhitespaceHandling.None;

			// Moves the reader to the root element.
			xmlIn.MoveToContent();

			// Double check this has the correct element name
			if (xmlIn.Name != "TabbedGroups")
				throw new ArgumentException("Root element must be 'TabbedGroups'");

			// Load the format version number
			string version = xmlIn.GetAttribute(0);
			string rawActiveLeaf = xmlIn.GetAttribute(1);

			// Convert format version from string to double
			int formatVersion = (int)Convert.ToDouble(version);
			int activeLeaf = Convert.ToInt32(rawActiveLeaf);
            
			// We can only load 1 upward version formats
			if (formatVersion < 1)
				throw new ArgumentException("Can only load Version 1 and upwards TabbedGroups Configuration files");

			try {
				// Prevent compacting and reposition of children
				BeginInit();
                
				// Remove all existing contents
				_root.Clear();
                
				// Read to custom data element
				if (!xmlIn.Read())
					throw new ArgumentException("An element was expected but could not be read in");

				if (xmlIn.Name != "CustomGlobalData")
					throw new ArgumentException("Expected 'CustomData' element was not found");

				bool finished = xmlIn.IsEmptyElement;

				// Give handlers chance to reload custom saved data
				OnGlobalLoading(xmlIn);

				// Read everything until we get the end of custom data marker
				while(!finished) {
					// Check it has the expected name
					if (xmlIn.NodeType == XmlNodeType.EndElement)
						finished = (xmlIn.Name == "CustomGlobalData");

					if (!finished) {
						if (!xmlIn.Read())
							throw new ArgumentException("An element was expected but could not be read in");
					}
				} 

				// Read the next well known lement
				if (!xmlIn.Read())
					throw new ArgumentException("An element was expected but could not be read in");

				// Is it the expected element?
				if (xmlIn.Name != "Sequence")
					throw new ArgumentException("Element 'Sequence' was expected but not found");
                
				// Reload the root sequence
				_root.LoadFromXml(xmlIn);

				// Move past the end element
				if (!xmlIn.Read())
					throw new ArgumentException("Could not read in next expected node");

				// Check it has the expected name
				if (xmlIn.NodeType != XmlNodeType.EndElement)
					throw new ArgumentException("EndElement expected but not found");
			}
			finally {
				TabGroupLeaf newActive = null;
            
				// Reset the active leaf correctly
				TabGroupLeaf current = FirstLeaf();
                
				while(current != null) {
					// Default to the first leaf if we cannot find a match
					if (newActive == null)
						newActive = current;
                        
					// Find an exact match?
					if (current.Unique == activeLeaf) {
						newActive = current;
						break;
					}
                    
					current = NextLeaf(current);
				}
                
				// Reinstate the active leaf indication
				if (newActive != null)
					ActiveLeaf = newActive;
            
				// Allow normal operation
				EndInit();
			}
                        
			xmlIn.Close();			
            
			// Just loaded, so cannot be dirty
			if (_autoCalculateDirty)
				_dirty = false;
		}
Пример #30
0
 public TabGroupLeaf PreviousLeaf(TabGroupLeaf current)
 {
     // Get parent of the provided leaf
     TabGroupSequence tgs = current.Parent as TabGroupSequence;
     
     // Must have a valid parent sequence
     if (tgs != null)
         return RecursiveFindLeafInSequence(tgs, current, false);
     else
         return null;
 }
Пример #31
0
        public TargetManager(TabbedGroups host, TabGroupLeaf leaf, Controls.TabControl source)
        {
            // Define state
            _host = host;
            _leaf = leaf;
            _source = source;
            _lastTarget = null;

            // Create collection to hold generated targets
            _targets = new TargetCollection();

            // Process each potential leaf in turn
            TabGroupLeaf tgl = host.FirstLeaf();

            while(tgl != null)
            {
                // Create all possible targets for this leaf
                CreateTargets(tgl);

                // Enumerate all leafs
                tgl = host.NextLeaf(tgl);
            }
        }
Пример #32
0
        internal void GroupRemoved(TabGroupBase tgb)
        {
            // Only modify leaf count when not suspended
            if (_suspendLeafCount == 0)
            {
                // Decrease count of leafs entries for each leaf that exists
                // which in the hierarchy that is being removed

                if (tgb.IsLeaf)
                {
                    _numLeafs--;

                    // Was last leaf removed?
                    if (_numLeafs == 0)
                    {
                        // If at least one leaf then set the value manually so that when the
                        // new one is created and set as active it does not try to process the
                        // old value that has already been destroyed.
                        if (_atLeastOneLeaf)
                        {
                            // Need to get rid of active leaf value
                            _activeLeaf = null;
                        }
                    }
                }
                else
                {
                    TabGroupSequence tgs = tgb as TabGroupSequence;

                    // Recurse into processing each child item
                    for(int i=0; i<tgs.Count; i++)
                        GroupRemoved(tgs[i]);
                }

                // Dispose of the group resources
                tgb.Dispose();

                // Mark layout as dirty
                if (_autoCalculateDirty)
                    _dirty = true;
            }
        }
Пример #33
0
		public virtual void OnExternalDrop(TabGroupLeaf tgl, Controls.TabControl tc, DragProvider dp) {
			// Has anyone registered for the event?
			if (ExternalDrop != null)
				ExternalDrop(this, tgl, tc, dp);
		}
Пример #34
0
		public void ResetActiveLeaf() {
			ActiveLeaf = null;
		}
Пример #35
0
        public TabGroupLeaf AddNewLeaf()
        {
            // Create a new leaf instance with correct back references
            TabGroupLeaf tgl = new TabGroupLeaf(_tabbedGroups, this);

            // Add into the collection
            Add(tgl);

            // Return its position in collection
            return tgl;
        }
Пример #36
0
        protected void CreateTargets(TabGroupLeaf leaf)
        {
            // Grab the underlying tab control
            Controls.TabControl tc = leaf.GroupControl as Controls.TabControl;

            // Get the total size of the tab control itself in screen coordinates
            Rectangle totalSize = tc.RectangleToScreen(tc.ClientRectangle);

            // We do not allow a page to be transfered to its own leaf!
            if (leaf != _leaf)
            {
                Rectangle tabsSize = tc.RectangleToScreen(tc.TabsAreaRect);

                // Give priority to the tabs area being used to transfer page
                _targets.Add(new Target(tabsSize, totalSize, leaf, Target.TargetActions.Transfer));
            }

            // Can only create new groups if moving relative to a new group
            // or we have more than one page in the originating group
            if ((leaf != _leaf) || ((leaf == _leaf) && _leaf.TabPages.Count > 1))
            {
                int horzThird = totalSize.Width / 3;
                int vertThird = totalSize.Height / 3;

                // Create the four spacing rectangle
                Rectangle leftRect   = new Rectangle(totalSize.X, totalSize.Y, horzThird, totalSize.Height);
                Rectangle rightRect  = new Rectangle(totalSize.Right - horzThird, totalSize.Y, horzThird, totalSize.Height);
                Rectangle topRect    = new Rectangle(totalSize.X, totalSize.Y, totalSize.Width, vertThird);
                Rectangle bottomRect = new Rectangle(totalSize.X, totalSize.Bottom - vertThird, totalSize.Width, vertThird);

                TabGroupSequence tgs = _leaf.Parent as TabGroupSequence;

                // Can only create new groups in same direction, unless this is the only leaf
                if (tgs.Count <= 1)
                {
                    // Add each new target
                    _targets.Add(new Target(leftRect, leftRect, leaf, Target.TargetActions.GroupLeft));
                    _targets.Add(new Target(rightRect, rightRect, leaf, Target.TargetActions.GroupRight));
                    _targets.Add(new Target(topRect, topRect, leaf, Target.TargetActions.GroupTop));
                    _targets.Add(new Target(bottomRect, bottomRect, leaf, Target.TargetActions.GroupBottom));
                }
                else
                {
                    if (tgs.Direction == Direction.Vertical)
                    {
                        _targets.Add(new Target(topRect, topRect, leaf, Target.TargetActions.GroupTop));
                        _targets.Add(new Target(bottomRect, bottomRect, leaf, Target.TargetActions.GroupBottom));
                    }
                    else
                    {
                        _targets.Add(new Target(leftRect, leftRect, leaf, Target.TargetActions.GroupLeft));
                        _targets.Add(new Target(rightRect, rightRect, leaf, Target.TargetActions.GroupRight));
                    }
                }
            }

            // We do not allow a page to be transfered to its own leaf!
            if (leaf != _leaf)
            {
                // Any remaining space is used to
                _targets.Add(new Target(totalSize, totalSize, leaf, Target.TargetActions.Transfer));
            }
        }