moving gui elements to base agg

This commit is contained in:
Lars Brubaker 2022-10-06 17:59:31 -07:00
parent 182d02a793
commit 4adc22561f
6 changed files with 27 additions and 1088 deletions

View file

@ -40,15 +40,17 @@ using MatterHackers.VectorMath;
namespace MatterHackers.MatterControl
{
public partial class InspectForm : WinformsSystemWindow.FormInspector
using WinTreeNode = System.Windows.Forms.TreeNode;
public partial class InspectForm : WinformsSystemWindow.FormInspector
{
private TreeNode activeTreeNode;
private WinTreeNode activeTreeNode;
private GuiWidget inspectedSystemWindow;
private Vector2 mousePosition;
private Dictionary<GuiWidget, TreeNode> aggTreeNodes = new Dictionary<GuiWidget, TreeNode>();
private Dictionary<IObject3D, TreeNode> sceneTreeNodes = new Dictionary<IObject3D, TreeNode>();
private Dictionary<GuiWidget, WinTreeNode> aggTreeNodes = new Dictionary<GuiWidget, WinTreeNode>();
private Dictionary<IObject3D, WinTreeNode> sceneTreeNodes = new Dictionary<IObject3D, WinTreeNode>();
private InteractiveScene scene;
private View3DWidget view3DWidget;
@ -145,7 +147,7 @@ namespace MatterHackers.MatterControl
activeTreeNode.Checked = false;
}
if (aggTreeNodes.TryGetValue(_inspectedWidget, out TreeNode treeNode))
if (aggTreeNodes.TryGetValue(_inspectedWidget, out WinTreeNode treeNode))
{
aggTreeView.SelectedNode = treeNode;
@ -182,14 +184,14 @@ namespace MatterHackers.MatterControl
}
}
private void AddItemEnsureAncestors(GuiWidget widget, string text = null, TreeNode childNode = null, bool showAllParents = true)
private void AddItemEnsureAncestors(GuiWidget widget, string text = null, WinTreeNode childNode = null, bool showAllParents = true)
{
if (text == null)
{
text = BuildDefaultName(widget);
}
if (aggTreeNodes.TryGetValue(widget, out TreeNode existingNode))
if (aggTreeNodes.TryGetValue(widget, out WinTreeNode existingNode))
{
if (childNode != null)
{
@ -199,7 +201,7 @@ namespace MatterHackers.MatterControl
}
else
{
var node = new TreeNode(text)
var node = new WinTreeNode(text)
{
Tag = widget
};
@ -230,9 +232,9 @@ namespace MatterHackers.MatterControl
}
}
private TreeNode AddItem(GuiWidget widget, TreeNode parentNode)
private WinTreeNode AddItem(GuiWidget widget, WinTreeNode parentNode)
{
var node = new TreeNode(BuildDefaultName(widget))
var node = new WinTreeNode(BuildDefaultName(widget))
{
Tag = widget
};
@ -252,9 +254,9 @@ namespace MatterHackers.MatterControl
return node;
}
private TreeNode AddItem(IObject3D item, TreeNode parentNode)
private WinTreeNode AddItem(IObject3D item, WinTreeNode parentNode)
{
var node = new TreeNode(BuildDefaultName(item))
var node = new WinTreeNode(BuildDefaultName(item))
{
Tag = item
};
@ -275,7 +277,7 @@ namespace MatterHackers.MatterControl
return node;
}
private void AddTree(GuiWidget widget, TreeNode parent)
private void AddTree(GuiWidget widget, WinTreeNode parent)
{
var node = AddItem(widget, parent);
@ -285,7 +287,7 @@ namespace MatterHackers.MatterControl
}
}
private void AddTree(IObject3D item, TreeNode parent)
private void AddTree(IObject3D item, WinTreeNode parent)
{
var node = AddItem(item, parent);
@ -348,7 +350,7 @@ namespace MatterHackers.MatterControl
public void MoveUpTree()
{
if (activeTreeNode?.Parent is TreeNode parent)
if (activeTreeNode?.Parent is WinTreeNode parent)
{
this.InspectedWidget = parent.Tag as GuiWidget;
}
@ -356,7 +358,7 @@ namespace MatterHackers.MatterControl
public void MoveDownTree()
{
if (activeTreeNode?.Nodes.Cast<TreeNode>().FirstOrDefault() is TreeNode firstChild)
if (activeTreeNode?.Nodes.Cast<WinTreeNode>().FirstOrDefault() is WinTreeNode firstChild)
{
this.InspectedWidget = firstChild.Tag as GuiWidget;
}
@ -502,11 +504,11 @@ namespace MatterHackers.MatterControl
private void InspectForm_Load(object sender, EventArgs e1)
{
var rootNode = new TreeNode("Theme");
var rootNode = new WinTreeNode("Theme");
var themeNode = new TreeNode("Theme");
var themeNode = new WinTreeNode("Theme");
var menuThemeNode = new TreeNode("MenuTheme");
var menuThemeNode = new WinTreeNode("MenuTheme");
rootNode.Nodes.Add(themeNode);
rootNode.Nodes.Add(menuThemeNode);

View file

@ -1,612 +0,0 @@
/*
Copyright (c) 2018, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using MatterHackers.Agg;
using MatterHackers.Agg.Font;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.Platform;
using MatterHackers.Agg.UI;
using MatterHackers.ImageProcessing;
using MatterHackers.VectorMath;
namespace MatterHackers.MatterControl.CustomWidgets
{
public class TreeNode : FlowLayoutWidget, ICheckbox
{
private readonly GuiWidget content;
private TreeView _treeView;
private ImageBuffer _image = null;
private readonly TextWidget textWidget;
private readonly TreeExpandWidget expandWidget;
private readonly ImageWidget imageWidget;
private bool isDirty;
public TreeNode(ThemeConfig theme, bool useIcon = true, TreeNode nodeParent = null)
: base(FlowDirection.TopToBottom)
{
this.HAnchor = HAnchor.Fit | HAnchor.Left;
this.VAnchor = VAnchor.Fit;
this.NodeParent = nodeParent;
this.TitleBar = new FlowLayoutWidget();
this.TitleBar.Click += (s, e) =>
{
if (TreeView != null)
{
TreeView.SelectedNode = this;
TreeView.NotifyItemClicked(TitleBar, e);
}
};
TreeNode hitNode = null;
this.TitleBar.MouseDown += (s, e) =>
{
if (TreeView != null && e.Button == MouseButtons.Left)
{
if (e.Clicks == 1)
{
hitNode = this;
}
else if (e.Clicks == 2)
{
// Nodes can move around in the tree between clicks.
// Make sure we're hitting the same node twice.
if (this != hitNode)
{
return;
}
TreeView.SelectedNode = this;
if (this.Nodes.Count > 0)
{
this.Expanded = !this.Expanded;
}
else
{
this.TreeView.NotifyItemDoubleClicked(TitleBar, e);
}
}
}
};
this.AddChild(this.TitleBar);
// add a check box
expandWidget = new TreeExpandWidget(theme)
{
Expandable = GetNodeCount(false) != 0,
VAnchor = VAnchor.Fit | VAnchor.Center,
Height = 16,
Width = 16
};
expandWidget.Click += (s, e) =>
{
this.Expanded = !this.Expanded;
expandWidget.Expanded = this.Expanded;
};
this.TitleBar.AddChild(expandWidget);
this.HighlightRegion = new FlowLayoutWidget()
{
VAnchor = VAnchor.Fit,
HAnchor = HAnchor.Fit,
Padding = useIcon ? new BorderDouble(2) : new BorderDouble(4, 2),
Selectable = false
};
this.TitleBar.AddChild(this.HighlightRegion);
// add a check box
if (useIcon)
{
_image = new ImageBuffer(16, 16);
this.HighlightRegion.AddChild(imageWidget = new ImageWidget(this.Image, listenForImageChanged: false)
{
VAnchor = VAnchor.Center,
Margin = new BorderDouble(right: 4),
Selectable = false
});
}
this.HighlightRegion.AddChild(textWidget = new TextWidget(this.Text, pointSize: theme.DefaultFontSize, textColor: theme.TextColor)
{
Selectable = false,
AutoExpandBoundsToText = true,
VAnchor = VAnchor.Center
});
content = new FlowLayoutWidget(FlowDirection.TopToBottom)
{
HAnchor = HAnchor.Fit | HAnchor.Left,
Visible = false, // content starts out not visible
Name = "content",
Margin = new BorderDouble(12, 3),
};
this.AddChild(content);
// Register listeners
this.Nodes.CollectionChanged += this.Nodes_CollectionChanged;
}
public override void OnKeyDown(KeyEventArgs keyEvent)
{
base.OnKeyDown(keyEvent);
var restoreFocus = Focused;
if (!keyEvent.Handled)
{
switch (keyEvent.KeyCode)
{
case Keys.Right:
this.Expanded = true;
keyEvent.Handled = true;
break;
case Keys.Left:
if (!this.Expanded)
{
if (this.NodeParent != null)
{
// navigate back up to the parent of this node
TreeView.SelectedNode = this.NodeParent;
TreeView.NotifyItemClicked(TreeView, new MouseEventArgs(MouseButtons.Left, 1, 0, 0, 0));
}
restoreFocus = false;
}
else
{
this.Expanded = false;
}
keyEvent.Handled = true;
break;
}
}
if (restoreFocus && !Focused)
{
Focus();
}
}
private void Nodes_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
// Assign NodeParent when items are added
foreach (var item in e.NewItems)
{
if (item is TreeNode treeNode)
{
treeNode.NodeParent = this;
}
}
}
isDirty = true;
}
public FlowLayoutWidget TitleBar { get; }
public FlowLayoutWidget HighlightRegion { get; }
// **** Not implemented ****
public void BeginEdit() => throw new NotImplementedException();
public void Collapse(bool collapseChildren) => throw new NotImplementedException();
public void Collapse() => throw new NotImplementedException();
public void EndEdit(bool cancel) => throw new NotImplementedException();
public void EnsureVisible() => throw new NotImplementedException();
public void ExpandAll() => throw new NotImplementedException();
public void Remove() => throw new NotImplementedException();
public int GetNodeCount(bool includeSubTrees)
{
if (includeSubTrees)
{
return this.Descendants<TreeNode>().Count();
}
return content?.Children.Where((c) => c is TreeNode).Count() ?? 0;
}
public bool AlwaysExpandable
{
get => expandWidget.AlwaysExpandable;
set => expandWidget.AlwaysExpandable = value;
}
public override void OnDraw(Graphics2D graphics2D)
{
if (isDirty)
{
// doing this during draw will often result in a enumeration changed
RebuildContentSection();
}
base.OnDraw(graphics2D);
}
public override void OnTextChanged(EventArgs e)
{
if (textWidget != null)
{
textWidget.Text = this.Text;
}
base.OnTextChanged(e);
}
public override void OnClosed(EventArgs e)
{
// Unregister listeners
this.Nodes.CollectionChanged -= this.Nodes_CollectionChanged;
base.OnClosed(e);
}
public void Toggle()
{
content.Visible = !content.Visible;
}
public IEnumerable<TreeNode> Ancestors()
{
var context = this.NodeParent;
while (context != null)
{
yield return context;
context = context.NodeParent;
}
}
private void RebuildContentSection()
{
// Remove but don't close all the current nodes
content.RemoveChildren();
using (content.LayoutLock())
{
// Then add them back in (after the change)
foreach (var node in Nodes)
{
node.NodeParent = this;
node.ClearRemovedFlag();
content.AddChild(node);
}
}
content.PerformLayout();
// If the node count is ending at 0 we removed content and need to rebuild the title bar so it will net have a + in it
expandWidget.Expandable = GetNodeCount(false) != 0;
isDirty = false;
}
public override string ToString()
{
return textWidget?.Text ?? "";
}
public bool Checked { get; set; }
public bool Editing { get; }
public bool Expandable
{
get => expandWidget.Expandable;
set => expandWidget.Expandable = value;
}
public bool ReserveIconSpace
{
get => expandWidget.ReserveIconSpace;
set => expandWidget.ReserveIconSpace = value;
}
private bool _expanded;
public bool Expanded
{
get => _expanded;
set
{
if (_expanded != value || content.Visible != value)
{
_expanded = value;
expandWidget.Expanded = _expanded;
content.Visible = _expanded && this.Nodes.Count > 0;
ExpandedChanged?.Invoke(this, null);
}
}
}
public TreeNode FirstNode { get; }
public ImageBuffer Image
{
get
{
return _image;
}
set
{
if (_image != value)
{
_image = value;
if (imageWidget != null)
{
imageWidget.Image = _image;
}
OnImageChanged(null);
}
}
}
public TreeNode LastNode { get; }
/// <summary>
/// Gets the zero-based depth of the tree node in the TreeView control.
/// </summary>
public int Level { get; }
// Summary:
// Gets the next sibling tree node.
//
// Returns:
// A TreeNode that represents the next sibling tree node.
public TreeNode NextNode { get; }
// Summary:
// Gets the next visible tree node.
//
// Returns:
// A TreeNode that represents the next visible tree node.
public TreeNode NextVisibleNode { get; }
// Summary:
// Gets or sets the font that is used to display the text on the tree node label.
//
// Returns:
// The StyledTypeFace that is used to display the text on the tree node label.
public StyledTypeFace NodeFont { get; set; }
// Summary:
// Gets the parent tree node of the current tree node.
//
// Returns:
// A TreeNode that represents the parent of the current tree
// node.
public TreeNode NodeParent { get; protected set; }
public ObservableCollection<TreeNode> Nodes { get; } = new ObservableCollection<TreeNode>();
public int PointSize { get; set; }
// Summary:
// Gets the previous sibling tree node.
//
// Returns:
// A TreeNode that represents the previous sibling tree node.
public TreeNode PrevNode { get; }
// Summary:
// Gets the previous visible tree node.
//
// Returns:
// A TreeNode that represents the previous visible tree node.
public TreeNode PrevVisibleNode { get; }
// Summary:
// Gets a value indicating whether the tree node is in the selected state.
//
// Returns:
// true if the tree node is in the selected state; otherwise, false.
public bool Selected
{
get
{
if (TreeView != null)
{
return TreeView.SelectedNode == this;
}
return false;
}
}
// Summary:
// Gets or sets the image list index value of the image that is displayed when the
// tree node is in the selected state.
//
// Returns:
// A zero-based index value that represents the image position in an ImageList.
public ImageBuffer SelectedImage { get; set; }
// Summary:
// Gets or sets the index of the image that is used to indicate the state of the
// TreeNode when the parent TreeView has
// its TreeView.CheckBoxes property set to false.
//
// Returns:
// The index of the image that is used to indicate the state of the TreeNode.
//
// Exceptions:
// T:System.ArgumentOutOfRangeException:
// The specified index is less than -1 or greater than 14.
public ImageBuffer StateImage { get; set; }
// Summary:
// Gets or sets the object that contains data about the tree node.
//
// Returns:
// An System.Object that contains data about the tree node. The default is null.
public object Tag { get; set; }
public Color TextColor { get; set; }
// Summary:
// Gets the parent tree view that the tree node is assigned to.
//
// Returns:
// A TreeView that represents the parent tree view that the
// tree node is assigned to, or null if the node has not been assigned to a tree
// view.
public virtual TreeView TreeView
{
get => _treeView ?? NodeParent.TreeView;
set => _treeView = value;
}
private void OnImageChanged(EventArgs args)
{
ImageChanged?.Invoke(this, null);
}
public event EventHandler CheckedStateChanged;
public event EventHandler ExpandedChanged;
public event EventHandler ImageChanged;
private class TreeExpandWidget : FlowLayoutWidget
{
private readonly ImageBuffer arrowRight;
private readonly ImageBuffer arrowDown;
private readonly ImageBuffer placeholder;
private readonly ThemedIconButton imageButton = null;
public TreeExpandWidget(ThemeConfig theme)
{
arrowRight = StaticData.Instance.LoadIcon("fa-angle-right_12.png", 12, 12).SetToColor(theme.TextColor);
arrowDown = StaticData.Instance.LoadIcon("fa-angle-down_12.png", 12, 12).SetToColor(theme.TextColor);
placeholder = new ImageBuffer(16, 16);
this.Margin = new BorderDouble(right: 4);
imageButton = new ThemedIconButton(placeholder, theme)
{
MinimumSize = new Vector2(16 * DeviceScale, 16 * DeviceScale),
VAnchor = VAnchor.Center,
Selectable = false,
Width = 16 * DeviceScale,
Height = 16 * DeviceScale
};
this.AddChild(imageButton);
}
private bool _alwaysExpandable;
public bool AlwaysExpandable
{
get => _alwaysExpandable;
set
{
imageButton.SetIcon(_expanded ? arrowDown : arrowRight);
_alwaysExpandable = value;
}
}
private bool? _expandable = null;
public bool Expandable
{
get => _expandable == true || this.AlwaysExpandable;
set
{
if (_expandable != value)
{
_expandable = value;
}
this.EnsureExpansionState();
}
}
private bool _expanded;
public bool Expanded
{
get => _expanded;
set
{
if (_expanded != value)
{
_expanded = value;
this.EnsureExpansionState();
}
}
}
private void EnsureExpansionState()
{
if (!this.Expandable)
{
if (this.ReserveIconSpace)
{
imageButton.SetIcon(placeholder);
}
imageButton.Visible = this.ReserveIconSpace;
}
else
{
imageButton.Visible = true;
imageButton.SetIcon(_expanded ? arrowDown : arrowRight);
}
}
public bool ReserveIconSpace { get; set; } = true;
}
}
}

View file

@ -1,455 +0,0 @@
/*
Copyright (c) 2018, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using System.Collections;
using System.Linq;
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
using MatterHackers.VectorMath;
namespace MatterHackers.MatterControl.CustomWidgets
{
public class TreeView : ScrollableWidget
{
protected ThemeConfig theme;
public TreeView(ThemeConfig theme)
: this(0, 0, theme)
{
}
public TreeView(int width, int height, ThemeConfig theme)
: base(width, height)
{
this.theme = theme;
this.AutoScroll = true;
this.HAnchor = HAnchor.Stretch;
this.VAnchor = VAnchor.Stretch;
}
#region Events
public event EventHandler AfterCheck;
public event EventHandler AfterCollapse;
public event EventHandler AfterExpand;
public event EventHandler AfterLabelEdit;
public event EventHandler<TreeNode> AfterSelect;
public event EventHandler BeforeCheck;
internal void NotifyItemClicked(GuiWidget sourceWidget, MouseEventArgs e)
{
this.NodeMouseClick?.Invoke(sourceWidget, e);
}
internal void NotifyItemDoubleClicked(GuiWidget sourceWidget, MouseEventArgs e)
{
this.NodeMouseDoubleClick?.Invoke(sourceWidget, e);
}
public event EventHandler BeforeCollapse;
public event EventHandler BeforeExpand;
public event EventHandler BeforeLabelEdit;
public event EventHandler<TreeNode> BeforeSelect;
public event EventHandler NodeMouseClick;
public event EventHandler NodeMouseDoubleClick;
public event EventHandler NodeMouseHover;
#endregion Events
#region Properties
// Summary:
// Gets or sets a value indicating whether check boxes are displayed next to the
// tree nodes in the tree view control.
//
// Returns:
// true if a check box is displayed next to each tree node in the tree view control;
// otherwise, false. The default is false.
public bool CheckBoxes { get; set; }
// Summary:
// Gets or sets a value indicating whether the selection highlight spans the width
// of the tree view control.
//
// Returns:
// true if the selection highlight spans the width of the tree view control; otherwise,
// false. The default is false.
public bool FullRowSelect { get; set; }
// Summary:
// Gets or sets a value indicating whether the selected tree node remains highlighted
// even when the tree view has lost the focus.
//
// Returns:
// true if the selected tree node is not highlighted when the tree view has lost
// the focus; otherwise, false. The default is true.
public bool HideSelection { get; set; }
// Summary:
// Gets or sets the distance to indent each child tree node level.
//
// Returns:
// The distance, in pixels, to indent each child tree node level. The default value
// is 19.
//
// Exceptions:
// T:System.ArgumentOutOfRangeException:
// The assigned value is less than 0 (see Remarks).-or- The assigned value is greater
// than 32,000.
public int Indent { get; set; }
// Summary:
// Gets or sets the height of each tree node in the tree view control.
//
// Returns:
// The height, in pixels, of each tree node in the tree view.
//
// Exceptions:
// T:System.ArgumentOutOfRangeException:
// The assigned value is less than one.-or- The assigned value is greater than the
// System.Int16.MaxValue value.
public int ItemHeight { get; set; }
// Summary:
// Gets or sets a value indicating whether the label text of the tree nodes can
// be edited.
//
// Returns:
// true if the label text of the tree nodes can be edited; otherwise, false. The
// default is false.
public bool LabelEdit { get; set; }
// Summary:
// Gets or sets the color of the lines connecting the nodes of the TreeView
// control.
//
// Returns:
// The System.Drawing.Color of the lines connecting the tree nodes.
public Color LineColor { get; set; }
// Summary:
// Gets or sets the delimiter string that the tree node path uses.
//
// Returns:
// The delimiter string that the tree node TreeNode.FullPath
// property uses. The default is the backslash character (\).
public string PathSeparator { get; set; }
public Color TextColor { get; set; } = Color.Black;
public double PointSize { get; set; } = 12;
// Summary:
// Gets or sets a value indicating whether the tree view control displays scroll
// bars when they are needed.
//
// Returns:
// true if the tree view control displays scroll bars when they are needed; otherwise,
// false. The default is true.
public bool Scrollable { get; set; }
// Summary:
// Gets or sets the tree node that is currently selected in the tree view control.
//
// Returns:
// The TreeNode that is currently selected in the tree view
// control.
private TreeNode _selectedNode;
public void Clear()
{
this.ScrollArea.CloseChildren();
// Release held reference
_selectedNode = null;
}
public override void OnKeyDown(KeyEventArgs keyEvent)
{
if (!keyEvent.Handled)
{
switch (keyEvent.KeyCode)
{
case Keys.Up:
var prev = PreviousVisibleTreeNode(SelectedNode);
if (prev != null)
{
SelectedNode = prev;
keyEvent.Handled = true;
prev.TreeView.NotifyItemClicked(prev.TreeView, new MouseEventArgs(MouseButtons.Left, 1, 0, 0, 0));
}
break;
case Keys.Down:
var next = NextVisibleTreeNode(SelectedNode);
if (next != null)
{
SelectedNode = next;
keyEvent.Handled = true;
next.TreeView.NotifyItemClicked(next.TreeView, new MouseEventArgs(MouseButtons.Left, 1, 0, 0, 0));
}
break;
}
}
base.OnKeyDown(keyEvent);
}
private TreeNode NextVisibleTreeNode(TreeNode treeNode)
{
var nodes = this.Descendants<TreeNode>((child) => child.Visible).ToList();
var selectedIndex = nodes.IndexOf(SelectedNode);
if (selectedIndex < nodes.Count - 1)
{
return nodes[selectedIndex + 1];
}
return null;
}
private TreeNode PreviousVisibleTreeNode(TreeNode treeNode)
{
var nodes = this.Descendants<TreeNode>((child) => child.Visible).ToList();
var selectedIndex = nodes.IndexOf(SelectedNode);
if (selectedIndex > 0)
{
return nodes[selectedIndex - 1];
}
return null;
}
public TreeNode SelectedNode
{
get => _selectedNode;
set
{
if (value != _selectedNode)
{
OnBeforeSelect(null);
var hadFocus = false;
// if the current selection (before change) is !null than clear its background color
if (_selectedNode != null)
{
hadFocus = _selectedNode.ContainsFocus;
_selectedNode.HighlightRegion.BackgroundColor = Color.Transparent;
}
// change the selection
_selectedNode = value;
if (_selectedNode != null)
{
// Ensure tree is expanded, walk backwards to the root, reverse, expand back to this node
foreach (var ancestor in _selectedNode.Ancestors().Reverse())
{
ancestor.Expanded = true;
}
}
if (_selectedNode != null)
{
_selectedNode.HighlightRegion.BackgroundColor = theme.AccentMimimalOverlay;
}
this.ScrollIntoView(_selectedNode);
if (hadFocus)
{
_selectedNode?.Focus();
}
OnAfterSelect(null);
}
}
}
public bool ShowLines { get; set; }
public bool ShowNodeToolTips { get; set; }
public bool ShowPlusMinus { get; set; }
public bool ShowRootLines { get; set; }
public bool Sorted { get; set; }
public IComparer TreeViewNodeSorter { get; set; }
// Summary:
// Gets the number of tree nodes that can be fully visible in the tree view control.
//
// Returns:
// The number of TreeNode items that can be fully visible in
// the TreeView control.
public int VisibleCount { get; }
#endregion Properties
// Summary:
// Disables any redrawing of the tree view.
public void BeginUpdate()
{
throw new NotImplementedException();
}
// Summary:
// Collapses all the tree nodes.
public void CollapseAll()
{
throw new NotImplementedException();
}
// Summary:
// Enables the redrawing of the tree view.
public void EndUpdate()
{
throw new NotImplementedException();
}
// Summary:
// Expands all the tree nodes.
public void ExpandAll()
{
throw new NotImplementedException();
}
// Summary:
// Retrieves the tree node that is at the specified point.
//
// Parameters:
// pt:
// The System.Drawing.Point to evaluate and retrieve the node from.
//
// Returns:
// The TreeNode at the specified point, in tree view (client)
// coordinates, or null if there is no node at that location.
public TreeNode GetNodeAt(Vector2 pt)
{
throw new NotImplementedException();
}
/// <summary>
/// Retrieves the number of tree nodes, optionally including those in all subtrees,
/// assigned to the tree view control.
/// </summary>
/// <param name="includeSubTrees">true to count the TreeNode items that the subtrees contain;
/// otherwise, false.</param>
/// <returns>The number of tree nodes, optionally including those in all subtrees, assigned
/// to the tree view control.</returns>
public int GetNodeCount(bool includeSubTrees)
{
throw new NotImplementedException();
}
public void Sort()
{
throw new NotImplementedException();
}
protected internal virtual void OnAfterCollapse(EventArgs e)
{
throw new NotImplementedException();
}
protected internal virtual void OnBeforeCollapse(EventArgs e)
{
throw new NotImplementedException();
}
protected virtual void OnAfterCheck(EventArgs e)
{
throw new NotImplementedException();
}
protected virtual void OnAfterExpand(EventArgs e)
{
throw new NotImplementedException();
}
protected virtual void OnAfterLabelEdit(EventArgs e)
{
throw new NotImplementedException();
}
protected virtual void OnAfterSelect(TreeNode e)
{
AfterSelect?.Invoke(this, e);
}
protected virtual void OnBeforeCheck(EventArgs e)
{
throw new NotImplementedException();
}
protected virtual void OnBeforeExpand(EventArgs e)
{
throw new NotImplementedException();
}
protected virtual void OnBeforeLabelEdit(EventArgs e)
{
throw new NotImplementedException();
}
protected virtual void OnBeforeSelect(TreeNode e)
{
BeforeSelect?.Invoke(this, e);
}
protected virtual void OnNodeMouseClick(EventArgs e)
{
throw new NotImplementedException();
}
protected virtual void OnNodeMouseDoubleClick(EventArgs e)
{
throw new NotImplementedException();
}
}
}

View file

@ -47,7 +47,10 @@ namespace MatterHackers.MatterControl
private TypeFacePrinter typeFacePrinter = null;
private PrinterConfig printer = null;
private int forceStartLine = -1;
/// <summary>
/// The first line to show from the existing visible lines. If -1 then show to the bottom of the list.
/// </summary>
private int forceStartLine = -1;
private Func<TerminalLine, string> _lineFilterFunction;

View file

@ -28,6 +28,7 @@ either expressed or implied, of the FreeBSD Project.
*/
using System;
using MatterHackers.Agg.UI;
using MatterHackers.MatterControl.CustomWidgets;
using MatterHackers.MatterControl.Library.Widgets;
using MatterHackers.MatterControl.SlicerConfiguration;

@ -1 +1 @@
Subproject commit 39d47369081d0434eb7ae0610bc76b71c4e0c210
Subproject commit f1d2d2113baa4373ded9b08e9fde7fd5c80ea1ef