private bool FindTabPageCollection( TabGroupSequence nodeGroup, Crownwood.DotNetMagic.Controls.TabPage tabPage, out TabPageCollection containingCollection) { for (var i = 0; i < nodeGroup.Count; i++) { var node = nodeGroup[i]; if (node.IsSequence) { var found = FindTabPageCollection(node as TabGroupSequence, tabPage, out containingCollection); if (found) { return(true); } } if (node.IsLeaf) { var leaf = (TabGroupLeaf)node; if (leaf.TabPages.Contains(tabPage)) { containingCollection = leaf.TabPages; return(true); } } } containingCollection = null; return(false); }
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]); } // Mark layout as dirty if (_autoCalculateDirty) _dirty = true; } }
protected void InternalConstruct(VisualStyle style) { // Prevent flicker with double buffering and all painting inside WM_PAINT SetStyle(ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true); // We want to act as a drop target this.AllowDrop = true; // Remember parameters _style = style; // Define initial state _numLeafs = 0; _compacting = false; _initializing = false; _suspendLeafCount = 0; // Create the root sequence that always exists _root = new TabGroupSequence(this); // Define default settings ResetProminentLeaf(); ResetResizeBarVector(); ResetResizeBarColor(); ResetResizeBarLock(); ResetLayoutLock(); ResetCompactOptions(); ResetDefaultGroupMinimumWidth(); ResetDefaultGroupMinimumHeight(); ResetActiveLeaf(); ResetAutoCompact(); ResetAtLeastOneLeaf(); ResetCloseMenuText(); ResetProminentMenuText(); ResetRebalanceMenuText(); ResetMovePreviousMenuText(); ResetMoveNextMenuText(); ResetNewVerticalMenuText(); ResetNewHorizontalMenuText(); ResetCloseShortcut(); ResetProminentShortcut(); ResetRebalanceShortcut(); ResetMovePreviousShortcut(); ResetMoveNextShortcut(); ResetSplitVerticalShortcut(); ResetSplitHorizontalShortcut(); ResetImageList(); ResetDisplayTabMode(); ResetSaveControls(); ResetAutoCalculateDirty(); ResetDirty(); ResetPageCloseWhenEmpty(); // Add ourself to the application filtering list // (to snoop for shortcut combinations) Application.AddMessageFilter(this); }
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; }
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); } }
/// <summary> /// Set the Space of this item so it occupies the specified number of pixels, if possible. /// </summary> /// <param name="pixelSize">Pixel length requested.</param> public void SetPixelLength(int pixelSize) { // Must use parent sequence to actually perform operation if (_parent != null) { // Parent must always be a sequence TabGroupSequence tgs = _parent as TabGroupSequence; // Resizing this object is requires knowledge of other siblings tgs.SetPixelLengthOfChild(this, pixelSize); } }
internal static void DebugStructure(TabGroupSequence tgs, int indent) { int parentId = -1; if (tgs.Parent != null) { parentId = tgs.Parent.Unique; } Decimal total = 0; for (int l = 0; l < tgs.Count; l++) { total += tgs[l].Space; } for (int k = 0; k < indent; k++) { Console.Write(" "); } Console.WriteLine("Sequence({0}) %:{1} ID:{2} P:{3} nChild:{4} Dir:{5}", total, tgs.Space, tgs.Unique, parentId, tgs.Count, tgs.Direction); indent++; for (int i = 0; i < tgs.Count; i++) { TabGroupBase tgb = tgs[i]; if (tgb is TabGroupSequence) { DebugStructure(tgb as TabGroupSequence, indent); } else { if (tgb.Parent != null) { parentId = tgb.Parent.Unique; } for (int j = 0; j < indent; j++) { Console.Write(" "); } Console.WriteLine("Leaf %:{0} ID:{1} P:{2} nChild:{3}", tgb.Space, tgb.Unique, parentId, (tgb.GroupControl as TabControl).TabPages.Count); } } }
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(); } }
internal void MoveActiveToNearestFromLeaf(TabGroupBase oldLeaf) { // Must have a reference to begin movement if (oldLeaf != null) { // Find the parent sequence of leaf, remember that a // leaf must be contained within a sequence instance TabGroupSequence tgs = oldLeaf.Parent as TabGroupSequence; // Must be valid, but had better check anyway if (tgs != null) { // Move relative to given base in the sequence MoveActiveInSequence(tgs, oldLeaf); } } }
internal void MoveActiveToNearestFromSequence(TabGroupSequence tgs) { // Is active leaf being moved from root sequence if (_root == tgs) { // Then make nothing active ActiveLeaf = null; } else { // Find the parent sequence of given sequence TabGroupSequence tgsParent = tgs.Parent as TabGroupSequence; // Must be valid, but had better check anyway if (tgs != null) { // Move relative to given base in the sequence MoveActiveInSequence(tgsParent, tgs); } } }
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; }
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; }
protected void MoveActiveInSequence(TabGroupSequence tgs, TabGroupBase child) { int count = tgs.Count; int index = tgs.IndexOf(child); // First try each entry after that given for(int i=index+1; i<count; i++) { // Is this the needed leaf node? if (tgs[i].IsLeaf) { // Make it active, and finish ActiveLeaf = tgs[i] as TabGroupLeaf; return; } else { // Need to make a recursive check inside group if (RecursiveActiveInSequence(tgs[i] as TabGroupSequence, true)) return; } } // 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) { // Make it active, and finish ActiveLeaf = tgs[i] as TabGroupLeaf; return; } else { // Need to make a recursive check inside group if (RecursiveActiveInSequence(tgs[i] as TabGroupSequence, false)) return; } } // Still no luck, try our own parent if (tgs.Parent != null) MoveActiveInSequence(tgs.Parent as TabGroupSequence, tgs); }
internal static void DebugSpace(TabGroupSequence tgs) { Decimal total = 0; for (int l = 0; l < tgs.Count; l++) { total += tgs[l].Space; } if ((total != 100m) && (total != 0m)) { Console.WriteLine("** ERROR ** Inaccurate Space = {0}", total); for (int l = 0; l < tgs.Count; l++) { Console.WriteLine("Base %:{0} ID:{1}", tgs[l].Space, tgs[l].Unique); } Console.WriteLine(""); System.Diagnostics.Debug.Assert(false); } }
protected bool RecursiveActiveInSequence(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) { // Make it active, and finish ActiveLeaf = tgs[index] as TabGroupLeaf; return true; } else { // Need to make a recursive check inside group if (RecursiveActiveInSequence(tgs[index] as TabGroupSequence, forwards)) return true; } } // Still no luck return false; }
internal void SetRootSequence(TabGroupSequence tgs) { // Use the new sequence as the root _root = tgs; }
internal static void DebugStruct(TabGroupSequence tgs, string title) { Console.WriteLine("Structure {0}", title); DebugStructure(tgs, 0); Console.WriteLine(""); }
protected void OnPopupMenuDisplay(object sender, CancelEventArgs e) { // Remove all existing menu items _tabControl.ContextPopupMenu.MenuCommands.Clear(); // Add our standard set of menus _tabControl.ContextPopupMenu.MenuCommands.AddRange(new MenuCommand[] { _mcClose, _mcSep1, _mcProm, _mcReba, _mcSep2, _mcHorz, _mcVert, _mcNext, _mcPrev }); if (!_tabbedGroups.LayoutLock) { // Are any pages selected bool valid = (_tabControl.SelectedIndex != -1); // Define the latest text string _mcClose.Text = _tabbedGroups.CloseMenuText; _mcProm.Text = _tabbedGroups.ProminentMenuText; _mcReba.Text = _tabbedGroups.RebalanceMenuText; _mcPrev.Text = _tabbedGroups.MovePreviousMenuText; _mcNext.Text = _tabbedGroups.MoveNextMenuText; _mcVert.Text = _tabbedGroups.NewVerticalMenuText; _mcHorz.Text = _tabbedGroups.NewHorizontalMenuText; // Only need to close option if the tab has close defined _mcClose.Visible = _tabControl.ShowClose && valid; _mcSep1.Visible = _tabControl.ShowClose && valid; // Update the radio button for prominent _mcProm.Checked = (_tabbedGroups.ProminentLeaf == this); // Can only create new group if at least two pages exist bool split = valid && (_tabControl.TabPages.Count > 1); bool vertSplit = split; bool horzSplit = split; TabGroupSequence tgs = _parent as TabGroupSequence; // If we are not the only leaf, then can only split in // the same direction as the group we are in if (tgs.Count > 1) { if (tgs.Direction == Direction.Vertical) { vertSplit = false; } else { horzSplit = false; } } _mcVert.Visible = vertSplit; _mcHorz.Visible = horzSplit; // Can only how movement if group exists in that direction _mcNext.Visible = valid && (_tabbedGroups.NextLeaf(this) != null); _mcPrev.Visible = valid && (_tabbedGroups.PreviousLeaf(this) != null); _mcSep2.Visible = _mcNext.Visible | _mcPrev.Visible | vertSplit | horzSplit; } else { // Make sure that none of the menu commands are visible _mcClose.Visible = false; _mcProm.Visible = false; _mcReba.Visible = false; _mcPrev.Visible = false; _mcNext.Visible = false; _mcVert.Visible = false; _mcHorz.Visible = false; _mcSep1.Visible = false; _mcSep2.Visible = false; } TGContextMenuEventArgs tge = new TGContextMenuEventArgs(this, _tabControl, _tabControl.SelectedTab, _tabControl.ContextPopupMenu); // Generate event so handlers can add/remove/cancel menu _tabbedGroups.OnPageContextMenu(tge); int visibleCommands = 0; // Count how many visible commands left foreach (MenuCommand mc in _tabControl.ContextPopupMenu.MenuCommands) { if (mc.Visible) { visibleCommands++; } } // Pass back cancel value or always cancel if no commands are visible e.Cancel = (tge.Cancel || (visibleCommands == 0)); }
private bool FindTabPageCollection( TabGroupSequence nodeGroup, Crownwood.DotNetMagic.Controls.TabPage tabPage, out TabPageCollection containingCollection) { for (var i = 0; i < nodeGroup.Count; i++) { var node = nodeGroup[i]; if (node.IsSequence) { var found = FindTabPageCollection(node as TabGroupSequence, tabPage, out containingCollection); if (found) return true; } if (node.IsLeaf) { var leaf = (TabGroupLeaf)node; if (leaf.TabPages.Contains(tabPage)) { containingCollection = leaf.TabPages; return true; } } } containingCollection = null; return false; }
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)); } }