diff --git a/ApplicationView/ThemeConfig.cs b/ApplicationView/ThemeConfig.cs
index e68f13460..5b01e300f 100644
--- a/ApplicationView/ThemeConfig.cs
+++ b/ApplicationView/ThemeConfig.cs
@@ -60,7 +60,7 @@ namespace MatterHackers.MatterControl
public int DefaultFontSize { get; } = 12;
- private int shortButtonHeight = 25;
+ internal int shortButtonHeight = 25;
private int sideBarButtonWidth;
public int H1PointSize { get; set; } = 13;
@@ -90,12 +90,6 @@ namespace MatterHackers.MatterControl
public TextImageButtonFactory imageConverterExpandMenuOptionFactory;
- internal void SetPrinterTabStyles(MainTab printerTab)
- {
- printerTab.Margin = new BorderDouble(10, 0, 0, 5);
- printerTab.Padding = new BorderDouble(8, 4, 12, 6);
- }
-
public TextImageButtonFactory imageConverterButtonFactory;
public Color TabBodyBackground => new Color(ActiveTheme.Instance.TertiaryBackgroundColor, 175);
@@ -135,9 +129,9 @@ namespace MatterHackers.MatterControl
}
else
{
- restoreNormal = ColorCircle(size, new Color(128, 128, 128));
+ restoreNormal = ColorCircle(size, Color.Transparent);
}
- restoreHover = ColorCircle(size, new Color(200, 0, 0));
+ restoreHover = ColorCircle(size, new Color("#DB4437"));
restorePressed = ColorCircle(size, new Color(255, 0, 0));
}
@@ -412,9 +406,20 @@ namespace MatterHackers.MatterControl
ImageBuffer imageBuffer = new ImageBuffer(size, size);
Graphics2D normalGraphics = imageBuffer.NewGraphics2D();
Vector2 center = new Vector2(size / 2.0, size / 2.0);
- normalGraphics.Circle(center, size / 2.0, color);
- normalGraphics.Line(center + new Vector2(-size / 4.0, -size / 4.0), center + new Vector2(size / 4.0, size / 4.0), Color.White, 2 * GuiWidget.DeviceScale);
- normalGraphics.Line(center + new Vector2(-size / 4.0, size / 4.0), center + new Vector2(size / 4.0, -size / 4.0), Color.White, 2 * GuiWidget.DeviceScale);
+
+ Color barColor;
+ if (color != Color.Transparent)
+ {
+ normalGraphics.Circle(center, size / 2.0, color);
+ barColor = Color.White;
+ }
+ else
+ {
+ barColor = new Color("#999");
+ }
+
+ normalGraphics.Line(center + new Vector2(-size / 4.0, -size / 4.0), center + new Vector2(size / 4.0, size / 4.0), barColor, 2 * GuiWidget.DeviceScale);
+ normalGraphics.Line(center + new Vector2(-size / 4.0, size / 4.0), center + new Vector2(size / 4.0, -size / 4.0), barColor, 2 * GuiWidget.DeviceScale);
return imageBuffer;
}
diff --git a/ApplicationView/WidescreenPanel.cs b/ApplicationView/WidescreenPanel.cs
index 9524abd96..0aea24725 100644
--- a/ApplicationView/WidescreenPanel.cs
+++ b/ApplicationView/WidescreenPanel.cs
@@ -31,8 +31,10 @@ using MatterHackers.Agg;
using MatterHackers.Agg.Platform;
using MatterHackers.Agg.UI;
using MatterHackers.MatterControl.ConfigurationPage;
+using MatterHackers.MatterControl.CustomWidgets;
using MatterHackers.MatterControl.PartPreviewWindow;
using MatterHackers.MatterControl.PrintLibrary;
+using MatterHackers.VectorMath;
namespace MatterHackers.MatterControl
{
@@ -49,11 +51,13 @@ namespace MatterHackers.MatterControl
this.AnchorAll();
this.Name = "WidescreenPanel";
+ var theme = ApplicationController.Instance.Theme;
+
var library3DViewSplitter = new Splitter()
{
SplitterDistance = UserSettings.Instance.LibraryViewWidth,
- SplitterWidth = ApplicationController.Instance.Theme.SplitterWidth,
- SplitterBackground = ApplicationController.Instance.Theme.SplitterBackground
+ SplitterWidth = theme.SplitterWidth,
+ SplitterBackground = theme.SplitterBackground
};
library3DViewSplitter.AnchorAll();
@@ -67,12 +71,21 @@ namespace MatterHackers.MatterControl
var leftNav = new FlowLayoutWidget(FlowDirection.TopToBottom);
leftNav.AnchorAll();
- leftNav.AddChild(new BrandMenuButton()
+ var toolbar = new Toolbar(null, theme)
+ {
+ HAnchor = HAnchor.Stretch,
+ VAnchor = VAnchor.Fit,
+ MinimumSize = new Vector2(16, 16)
+ };
+ toolbar.SeparatorLine.BackgroundColor = ApplicationController.Instance.Theme.SlightShade;
+ toolbar.SeparatorLine.Height = 2;
+ toolbar.ActionBar.AddChild(new BrandMenuButton(theme)
{
MinimumSize = new VectorMath.Vector2(0, 34),
HAnchor = HAnchor.Stretch,
VAnchor = VAnchor.Fit
});
+ leftNav.AddChild(toolbar);
var partPreviewContent = new PartPreviewContent()
{
@@ -80,7 +93,7 @@ namespace MatterHackers.MatterControl
HAnchor = HAnchor.Left | HAnchor.Right
};
- leftNav.AddChild(new PrintLibraryWidget(partPreviewContent, ApplicationController.Instance.Theme));
+ leftNav.AddChild(new PrintLibraryWidget(partPreviewContent, theme));
// put in the left column
library3DViewSplitter.Panel1.AddChild(leftNav);
@@ -90,56 +103,40 @@ namespace MatterHackers.MatterControl
}
}
- public class BrandMenuButton : GuiWidget
+ public class BrandMenuButton : PopupButton
{
- public BrandMenuButton()
+ public BrandMenuButton(ThemeConfig theme)
{
- this.Padding = new BorderDouble(left: 2);
-
- Name = "MatterControl BrandMenuButton";
- var buttonView = new FlowLayoutWidget()
- {
- HAnchor = HAnchor.Stretch,
- VAnchor = VAnchor.Fit,
- Margin = 0
- };
-
- var buttonHeight = ApplicationController.Instance.Theme.ButtonHeight;
-
- var iconContainer = new GuiWidget()
- {
- Width = buttonHeight,
- Height = buttonHeight
- };
- iconContainer.AddChild(new ImageWidget(AggContext.StaticData.LoadIcon("mh-app-logo.png", IconColor.Theme))
- {
- VAnchor = VAnchor.Center,
- HAnchor = HAnchor.Center
- });
-
- buttonView.AddChild(iconContainer);
-
- buttonView.AddChild(new TextWidget(ApplicationController.Instance.ShortProductName, textColor: ActiveTheme.Instance.PrimaryTextColor)
- {
- Margin = 0,
- VAnchor = VAnchor.Center
- });
-
- var popupButton = new PopupButton(buttonView)
- {
- VAnchor = VAnchor.Center,
- HAnchor = HAnchor.Stretch,
- Margin = 0
- };
- popupButton.PopupContent = new ApplicationSettingsWidget(ApplicationController.Instance.Theme.MenuButtonFactory)
+ this.Name = "MatterControl BrandMenuButton";
+ this.VAnchor = VAnchor.Stretch;
+ this.HAnchor = HAnchor.Stretch;
+ this.Margin = 0;
+ this.PopupContent = new ApplicationSettingsWidget(theme.MenuButtonFactory)
{
HAnchor = HAnchor.Absolute,
- VAnchor = VAnchor.Fit,
+ VAnchor = VAnchor.Center,
Width = 500,
BackgroundColor = Color.White
};
- this.AddChild(popupButton);
+ var row = new FlowLayoutWidget()
+ {
+ HAnchor = HAnchor.Stretch,
+ VAnchor = VAnchor.Stretch,
+ };
+ this.AddChild(row);
+
+ row.AddChild(new IconButton(AggContext.StaticData.LoadIcon("mh-app-logo.png", IconColor.Theme), theme)
+ {
+ VAnchor = VAnchor.Center,
+ Margin = new BorderDouble(right: 4),
+ Selectable = false
+ });
+
+ row.AddChild(new TextWidget(ApplicationController.Instance.ShortProductName, textColor: ActiveTheme.Instance.PrimaryTextColor)
+ {
+ VAnchor = VAnchor.Center
+ });
}
}
diff --git a/Library/Widgets/ListView/IconListView.cs b/Library/Widgets/ListView/IconListView.cs
index f0d681e23..c0f6ee48d 100644
--- a/Library/Widgets/ListView/IconListView.cs
+++ b/Library/Widgets/ListView/IconListView.cs
@@ -194,41 +194,55 @@ namespace MatterHackers.MatterControl.CustomWidgets
{
this.VAnchor = VAnchor.Fit;
this.HAnchor = HAnchor.Fit;
- this.Padding = 4;
+ this.Padding = 2;
this.Margin = new BorderDouble(6, 0, 0, 6);
- var container = new FlowLayoutWidget(FlowDirection.TopToBottom);
- this.AddChild(container);
-
- imageWidget = new ImageWidget(thumbWidth, thumbHeight)
- {
- AutoResize = false,
- Name = "List Item Thumbnail",
- BackgroundColor = item.ListView.ThumbnailBackground,
- Margin = 0,
- };
- container.AddChild(imageWidget);
-
- this.SetItemThumbnail(loadingImage);
-
int maxWidth = thumbWidth - 4;
- var text = new TextWidget(item.Model.Name, 0, 0, 9, textColor: ActiveTheme.Instance.PrimaryTextColor)
+ if (thumbWidth < 75)
{
- AutoExpandBoundsToText = false,
- EllipsisIfClipped = true,
- HAnchor = HAnchor.Center,
- Margin = new BorderDouble(0, 0, 0, 3),
- };
+ imageWidget = new ImageWidget(thumbWidth, thumbHeight)
+ {
+ AutoResize = false,
+ Name = "List Item Thumbnail",
+ BackgroundColor = item.ListView.ThumbnailBackground,
+ Margin = 0,
+ };
+ this.AddChild(imageWidget);
+ }
+ else
+ {
+ var container = new FlowLayoutWidget(FlowDirection.TopToBottom);
+ this.AddChild(container);
- text.MaximumSize = new Vector2(maxWidth, 20);
- if (text.Printer.LocalBounds.Width > maxWidth)
- {
- text.Width = maxWidth;
- text.Text = item.Model.Name;
+ imageWidget = new ImageWidget(thumbWidth, thumbHeight)
+ {
+ AutoResize = false,
+ Name = "List Item Thumbnail",
+ BackgroundColor = item.ListView.ThumbnailBackground,
+ Margin = 0,
+ };
+ container.AddChild(imageWidget);
+
+ var text = new TextWidget(item.Model.Name, 0, 0, 9, textColor: ActiveTheme.Instance.PrimaryTextColor)
+ {
+ AutoExpandBoundsToText = false,
+ EllipsisIfClipped = true,
+ HAnchor = HAnchor.Center,
+ Margin = new BorderDouble(0, 0, 0, 3),
+ };
+
+ text.MaximumSize = new Vector2(maxWidth, 20);
+ if (text.Printer.LocalBounds.Width > maxWidth)
+ {
+ text.Width = maxWidth;
+ text.Text = item.Model.Name;
+ }
+
+ container.AddChild(text);
}
- container.AddChild(text);
+ this.SetItemThumbnail(loadingImage);
}
public override async void OnLoad(EventArgs args)
diff --git a/Library/Widgets/PrintLibraryWidget.cs b/Library/Widgets/PrintLibraryWidget.cs
index 483a8b5c9..2d38f6ae8 100644
--- a/Library/Widgets/PrintLibraryWidget.cs
+++ b/Library/Widgets/PrintLibraryWidget.cs
@@ -431,7 +431,7 @@ namespace MatterHackers.MatterControl.PrintLibrary
var bedConfig = new BedConfig();
var newTab = partPreviewContent.CreatePartTab(firstItem.Name, bedConfig, theme);
- if (newTab.TabPage is PartTabPage printerTab)
+ if (newTab.TabContent is PartTabPage printerTab)
{
bedConfig.Scene.Children.Modify(list =>
{
@@ -606,6 +606,29 @@ namespace MatterHackers.MatterControl.PrintLibrary
},
});
+ menuActions.Add(new PrintItemAction()
+ {
+ Title = "View XSmall Icons".Localize(),
+ AlwaysEnabled = true,
+ Action = (selectedLibraryItems, listView) =>
+ {
+ listView.ListContentView = new IconListView(18);
+ listView.Reload().ConfigureAwait(false);
+ },
+ });
+
+
+ menuActions.Add(new PrintItemAction()
+ {
+ Title = "View Small Icons".Localize(),
+ AlwaysEnabled = true,
+ Action = (selectedLibraryItems, listView) =>
+ {
+ listView.ListContentView = new IconListView(70);
+ listView.Reload().ConfigureAwait(false);
+ },
+ });
+
menuActions.Add(new PrintItemAction()
{
Title = "View Icons".Localize(),
diff --git a/MatterControl.csproj b/MatterControl.csproj
index aae1344d1..f923444ff 100644
--- a/MatterControl.csproj
+++ b/MatterControl.csproj
@@ -113,13 +113,14 @@
+
-
+
diff --git a/PartPreviewWindow/GCode2DWidget.cs b/PartPreviewWindow/GCode2DWidget.cs
index 31deebacd..44dd705cc 100644
--- a/PartPreviewWindow/GCode2DWidget.cs
+++ b/PartPreviewWindow/GCode2DWidget.cs
@@ -28,16 +28,11 @@ either expressed or implied, of the FreeBSD Project.
*/
using System;
-using System.Diagnostics;
-using System.Threading.Tasks;
using MatterHackers.Agg;
using MatterHackers.Agg.Transform;
using MatterHackers.Agg.UI;
using MatterHackers.Agg.VertexSource;
using MatterHackers.GCodeVisualizer;
-using MatterHackers.Localizations;
-using MatterHackers.MatterControl.SlicerConfiguration;
-using MatterHackers.MeshVisualizer;
using MatterHackers.RenderOpenGl;
using MatterHackers.RenderOpenGl.OpenGl;
using MatterHackers.VectorMath;
diff --git a/PartPreviewWindow/MainTab.cs b/PartPreviewWindow/MainTab.cs
index bf13c956a..fd36ddbed 100644
--- a/PartPreviewWindow/MainTab.cs
+++ b/PartPreviewWindow/MainTab.cs
@@ -27,38 +27,161 @@ of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
+using System;
+using System.Linq;
using MatterHackers.Agg;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.UI;
using MatterHackers.Agg.VertexSource;
-using MatterHackers.VectorMath;
+using MatterHackers.Localizations;
namespace MatterHackers.MatterControl.PartPreviewWindow
{
- public class MainTab : ThreeViewTab
+ public class MainTab : GuiWidget, ITab
{
+ public event EventHandler CloseClicked;
+
+ private SimpleTabs parentTabControl;
+
+ public MainTab(string tabLabel, SimpleTabs parentTabControl, GuiWidget tabContent, string tabImageUrl = null)
+ {
+ this.HAnchor = HAnchor.Fit;
+ this.VAnchor = VAnchor.Fit | VAnchor.Bottom;
+ this.Padding = 0;
+ this.Margin = 0;
+
+ this.TabContent = tabContent;
+ this.parentTabControl = parentTabControl;
+
+ this.AddChild(
+ new TabPill(tabLabel, ActiveTheme.Instance.PrimaryTextColor, tabImageUrl)
+ {
+ Margin = new BorderDouble(right: 16)
+ });
+
+ var closeButton = ApplicationController.Instance.Theme.CreateSmallResetButton();
+ closeButton.HAnchor = HAnchor.Right;
+ closeButton.Margin = new BorderDouble(right: 7, top: 1);
+ closeButton.Name = "Close Tab Button";
+ closeButton.ToolTipText = "Close".Localize();
+ closeButton.Click += (sender, e) =>
+ {
+ UiThread.RunOnIdle(() =>
+ {
+ this.CloseClicked?.Invoke(this, null);
+ });
+ };
+
+ this.AddChild(closeButton);
+ }
+
+ public GuiWidget TabContent { get; }
+
+ public static Color ActiveTabColor = ApplicationController.Instance.Theme.SlightShade;
+
+ public static Color InactiveTabColor = ApplicationController.Instance.Theme.PrimaryTabFillColor;
+
+ private static int tabInsetDistance = 14 / 2;
+
+ internal MainTab NextTab { get; set; }
+
+ internal MainTab PreviousTab { get; set; }
+
+ public override void OnDraw(Graphics2D graphics2D)
+ {
+ var rect = LocalBounds;
+ var centerY = rect.YCenter;
+
+ var siblings = this.Parent.Children.OfType().ToList();
+
+ int position = siblings.IndexOf(this);
+
+ //MainTab leftSibling = (position > 0) ? siblings[position - 1] : null;
+ //MainTab rightSibling = (position < siblings.Count - 1) ? siblings[position + 1] : null;
+
+ var activeTab = parentTabControl.ActiveTab;
+
+ bool isFirstTab = position == 0;
+ bool rightSiblingSelected = this.NextTab == activeTab;
+
+ // Tab - core
+ var tabShape = new VertexStorage();
+ tabShape.MoveTo(rect.Left, centerY);
+ tabShape.LineTo(rect.Left + tabInsetDistance, rect.Top);
+ tabShape.LineTo(rect.Right - tabInsetDistance, rect.Top);
+ tabShape.LineTo(rect.Right, centerY);
+ if (!rightSiblingSelected)
+ {
+ tabShape.LineTo(rect.Right, rect.Bottom);
+ }
+ tabShape.LineTo(rect.Right - tabInsetDistance, rect.Bottom);
+ tabShape.LineTo(rect.Left + tabInsetDistance, rect.Bottom);
+
+ if (isFirstTab)
+ {
+ tabShape.LineTo(rect.Left, rect.Bottom);
+ }
+
+ graphics2D.Render(
+ tabShape,
+ (this == activeTab) ? ActiveTabColor : InactiveTabColor);
+
+ if (!isFirstTab)
+ {
+ DrawTabLowerLeft(
+ graphics2D,
+ rect,
+ (this.PreviousTab == activeTab || this == activeTab) ? ActiveTabColor : InactiveTabColor);
+ }
+
+ if (rightSiblingSelected)
+ {
+ DrawTabLowerRight(graphics2D, rect, ActiveTabColor);
+ }
+
+ base.OnDraw(graphics2D);
+ }
+
+ public static void DrawTabLowerRight(Graphics2D graphics2D, RectangleDouble rect, Color color)
+ {
+ // Tab - right nub
+ var tabRight = new VertexStorage();
+ tabRight.MoveTo(rect.Right, rect.YCenter);
+ tabRight.LineTo(rect.Right, rect.Bottom);
+ tabRight.LineTo(rect.Right - tabInsetDistance, rect.Bottom);
+
+ graphics2D.Render(tabRight, color);
+ }
+
+ public static void DrawTabLowerLeft(Graphics2D graphics2D, RectangleDouble rect, Color color)
+ {
+ // Tab - left nub
+ var tabLeft = new VertexStorage();
+ tabLeft.MoveTo(rect.Left, rect.YCenter);
+ tabLeft.LineTo(rect.Left + tabInsetDistance, rect.Bottom);
+ tabLeft.LineTo(rect.Left, rect.Bottom);
+
+ graphics2D.Render(tabLeft, color);
+ }
+
private class TabPill : FlowLayoutWidget
{
private TextWidget label;
public TabPill(string tabTitle, Color textColor, string imageUrl = null)
{
- var imageWidget = new ImageWidget(new ImageBuffer(16, 16))
- {
- Margin = new BorderDouble(right: 6),
- VAnchor = VAnchor.Center
- };
- this.AddChild(imageWidget);
-
- label = new TextWidget(tabTitle)
- {
- TextColor = textColor,
- VAnchor = VAnchor.Center
- };
- this.AddChild(label);
+ this.Selectable = false;
+ this.Padding = new BorderDouble(10, 5, 10, 4);
if (!string.IsNullOrEmpty(imageUrl))
{
+ var imageWidget = new ImageWidget(new ImageBuffer(16, 16))
+ {
+ Margin = new BorderDouble(right: 6, bottom: 2),
+ VAnchor = VAnchor.Center
+ };
+ this.AddChild(imageWidget);
+
// Attempt to load image
try
{
@@ -67,11 +190,18 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
}
catch { }
}
+
+ label = new TextWidget(tabTitle)
+ {
+ TextColor = textColor,
+ VAnchor = VAnchor.Center
+ };
+ this.AddChild(label);
}
public Color TextColor
{
- get => label.TextColor;
+ get => label.TextColor;
set => label.TextColor = value;
}
@@ -81,46 +211,5 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
set => label.Text = value;
}
}
-
- public MainTab(string tabTitle, string tabName, TabPage tabPage, string tabImageUrl = null)
- : this(
- new TabPill(tabTitle, new Color(ActiveTheme.Instance.PrimaryTextColor, 140), tabImageUrl),
- new TabPill(tabTitle, ActiveTheme.Instance.PrimaryTextColor, tabImageUrl),
- new TabPill(tabTitle, ActiveTheme.Instance.PrimaryTextColor, tabImageUrl),
- tabName,
- tabPage)
- {
- }
-
- public MainTab(GuiWidget normalWidget, GuiWidget hoverWidget, GuiWidget pressedWidget, string tabName, TabPage tabPage)
- : base(tabName, normalWidget, hoverWidget, pressedWidget, tabPage)
- {
- this.HAnchor = HAnchor.Fit;
- this.VAnchor = VAnchor.Fit | VAnchor.Bottom;
- }
-
- public int BorderWidth { get; set; } = 1;
- public int borderRadius { get; set; } = 4;
-
- private Color activeTabColor = ApplicationController.Instance.Theme.SlightShade;
- private Color inactiveTabColor = ApplicationController.Instance.Theme.PrimaryTabFillColor;
-
- public override void OnDraw(Graphics2D graphics2D)
- {
- RectangleDouble borderRectangle = LocalBounds;
- borderRectangle.ExpandToInclude(new Vector2(0, -15));
-
- if (BorderWidth > 0)
- {
- var r = new RoundedRect(borderRectangle, this.borderRadius);
- r.normalize_radius();
-
- graphics2D.Render(
- r,
- selectedWidget.Visible ? activeTabColor : inactiveTabColor);
- }
-
- base.OnDraw(graphics2D);
- }
}
}
diff --git a/PartPreviewWindow/IconTab.cs b/PartPreviewWindow/NewTabButton.cs
similarity index 71%
rename from PartPreviewWindow/IconTab.cs
rename to PartPreviewWindow/NewTabButton.cs
index 7a7c60e78..9778b5ac1 100644
--- a/PartPreviewWindow/IconTab.cs
+++ b/PartPreviewWindow/NewTabButton.cs
@@ -27,6 +27,7 @@ of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
+using System.Linq;
using MatterHackers.Agg;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.UI;
@@ -34,27 +35,38 @@ using MatterHackers.MatterControl.CustomWidgets;
namespace MatterHackers.MatterControl.PartPreviewWindow
{
- public class IconTab : Tab
+ public class NewTabButton : GuiWidget
{
- private IconButton iconButton;
+ private SimpleTabs parentTabControl;
- public IconTab(string tabName, TabPage tabPage, ImageBuffer imageBuffer, ThemeConfig theme)
- : base(tabName, tabPage)
+ public IconButton IconButton { get; }
+
+ public NewTabButton(ImageBuffer imageBuffer, SimpleTabs parentTabControl, ThemeConfig theme)
{
- iconButton = new IconButton(imageBuffer, theme)
+ this.parentTabControl = parentTabControl;
+ this.HAnchor = HAnchor.Fit;
+
+ IconButton = new IconButton(imageBuffer, theme)
{
+ HAnchor = HAnchor.Left,
Height = theme.MicroButton.Options.FixedHeight,
Width = theme.MicroButton.Options.FixedHeight,
- Selectable = false
+ Margin = new BorderDouble(left: 10),
};
- this.AddChild(iconButton);
+ this.AddChild(IconButton);
}
- protected override void OnTabIndexChanged()
+ public ITab LastTab { get; set; }
+
+ public override void OnDraw(Graphics2D graphics2D)
{
- iconButton.BackgroundColor = (this.TabPage == TabBarContaningTab.GetActivePage()) ? ActiveTheme.Instance.TertiaryBackgroundColor : Color.Transparent;
- base.OnTabIndexChanged();
+ MainTab.DrawTabLowerLeft(
+ graphics2D,
+ this.LocalBounds,
+ (parentTabControl.ActiveTab == this.LastTab) ? MainTab.ActiveTabColor : MainTab.InactiveTabColor);
+
+ base.OnDraw(graphics2D);
}
}
}
\ No newline at end of file
diff --git a/PartPreviewWindow/PartPreviewContent.cs b/PartPreviewWindow/PartPreviewContent.cs
index e30804966..df02cbe98 100644
--- a/PartPreviewWindow/PartPreviewContent.cs
+++ b/PartPreviewWindow/PartPreviewContent.cs
@@ -30,13 +30,12 @@ either expressed or implied, of the FreeBSD Project.
using System;
using System.Linq;
using MatterHackers.Agg;
-using MatterHackers.Agg.Platform;
using MatterHackers.Agg.UI;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.AboutPage;
-using MatterHackers.MatterControl.CustomWidgets;
using MatterHackers.MatterControl.SettingsManagement;
using MatterHackers.MatterControl.SlicerConfiguration;
+using MatterHackers.VectorMath;
namespace MatterHackers.MatterControl.PartPreviewWindow
{
@@ -45,20 +44,33 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
private EventHandler unregisterEvents;
private MainTab printerTab = null;
- private TabControl tabControl;
+ private NewTabButton plusTabSelect;
+ private ChromeTabs tabControl;
public PartPreviewContent()
+ : base(FlowDirection.TopToBottom)
{
var printer = ApplicationController.Instance.ActivePrinter;
var theme = ApplicationController.Instance.Theme;
this.AnchorAll();
- tabControl = ApplicationController.Instance.Theme.CreateTabControl(2);
+ var extensionArea = new FlowLayoutWidget();
- tabControl.TabBar.TabIndexChanged += (s, e) =>
+ tabControl = new ChromeTabs(extensionArea, theme)
{
- if (tabControl.GetTabPage(tabControl.SelectedTabIndex) is PartTabPage tabPage)
+ VAnchor = VAnchor.Stretch,
+ HAnchor = HAnchor.Stretch,
+ BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor,
+ NewTabPage = () =>
+ {
+ return new PlusTabPage(this, tabControl, theme);
+ }
+ };
+
+ tabControl.ActiveTabChanged += (s, e) =>
+ {
+ if (this.tabControl.ActiveTab?.TabContent is PartTabPage tabPage)
{
var dragDropData = ApplicationController.Instance.DragDropData;
@@ -68,58 +80,27 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
}
};
- var separator = tabControl.Children().FirstOrDefault();
- separator.BackgroundColor = ApplicationController.Instance.Theme.SlightShade;
+ tabControl.TabBar.Padding = new BorderDouble(top: 4);
+ tabControl.TabBar.SeparatorLine.BackgroundColor = ApplicationController.Instance.Theme.SlightShade;
+ tabControl.TabBar.SeparatorLine.Height = 2;
- Color selectedTabColor;
- if (!UserSettings.Instance.IsTouchScreen)
- {
- tabControl.TabBar.BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;
- selectedTabColor = ActiveTheme.Instance.TabLabelSelected;
- }
- else
- {
- tabControl.TabBar.BackgroundColor = ActiveTheme.Instance.TransparentLightOverlay;
- selectedTabColor = ActiveTheme.Instance.SecondaryAccentColor;
- }
+ Color selectedTabColor = ActiveTheme.Instance.TabLabelSelected;
// Add a tab for the current printer
if (ActiveSliceSettings.Instance.PrinterSelected)
{
string tabTitle = ActiveSliceSettings.Instance.GetValue(SettingsKey.printer_name);
printerTab = CreatePrinterTab(printer, theme, tabTitle);
+
tabControl.AddTab(printerTab);
}
else
{
- this.CreatePartTab("New Part", printer.Bed, theme, 0);
+ this.CreatePartTab("New Part", printer.Bed, theme);
}
- // TODO: add in the printers and designs that are currently open (or were open last run).
- var plusTabSelect = new IconTab(
- "Create New",
- new TabPage(new PlusTabPage(this, printer, theme), "+"),
- AggContext.StaticData.LoadIcon("fa-plus_12.png", IconColor.Theme),
- theme);
-
- plusTabSelect.VAnchor = VAnchor.Bottom;
-
- plusTabSelect.MinimumSize = new VectorMath.Vector2(16, 16);
- plusTabSelect.Margin = new BorderDouble(left: 10, top: 6);
- plusTabSelect.Padding = 0;
- plusTabSelect.ToolTipText = "Create New".Localize();
- tabControl.AddTab(plusTabSelect);
-
- tabControl.TabBar.AddChild(new HorizontalSpacer());
-
// add in the update available button
- LinkButtonFactory linkButtonFactory = new LinkButtonFactory()
- {
- textColor = ActiveTheme.Instance.PrimaryTextColor,
- fontSize = 12,
- };
-
- Button updateAvailableButton = linkButtonFactory.Generate("Update Available");
+ Button updateAvailableButton = theme.LinkButtonFactory.Generate("Update Available");
updateAvailableButton.Name = "Update Available Link";
updateAvailableButton.Visible = UpdateControlData.Instance.UpdateStatus == UpdateControlData.UpdateStatusStates.UpdateAvailable;
updateAvailableButton.ToolTipText = "There is a new update available for download".Localize();
@@ -133,7 +114,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
DialogWindow.Show();
});
});
- tabControl.TabBar.AddChild(updateAvailableButton);
+
+ tabControl.AddChild(updateAvailableButton);
UpdateControlData.Instance.UpdateStatusChanged.RegisterEvent((s, e) =>
{
@@ -141,17 +123,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
}, ref unregisterEvents);
// this causes the update button to be centered
- tabControl.TabBar.AddChild(new HorizontalSpacer());
-
- // put in the login logout control
- var rightPanelArea = new FlowLayoutWidget()
- {
- VAnchor = VAnchor.Stretch
- };
-
- var extensionArea = new FlowLayoutWidget();
-
- rightPanelArea.AddChild(extensionArea);
+ //tabControl.TabBar.AddChild(new HorizontalSpacer());
//rightPanelArea.AddChild(
// new ImageWidget(
@@ -161,7 +133,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
// DebugShowBounds = true
// });
- tabControl.TabBar.AddChild(rightPanelArea);
+ //this.AddChild(tabControl);
this.AddChild(tabControl);
@@ -171,7 +143,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
&& stringEvent.Data == SettingsKey.printer_name
&& printerTab != null)
{
- printerTab.TabPage.Text = ActiveSliceSettings.Instance.GetValue(SettingsKey.printer_name);
+ printerTab.Text = ActiveSliceSettings.Instance.GetValue(SettingsKey.printer_name);
}
}, ref unregisterEvents);
@@ -187,38 +159,36 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
}, ref unregisterEvents);
}
- private static MainTab CreatePrinterTab(PrinterConfig printer, ThemeConfig theme, string tabTitle)
+ private MainTab CreatePrinterTab(PrinterConfig printer, ThemeConfig theme, string tabTitle)
{
string oemName = printer.Settings.GetValue(SettingsKey.make);
OemSettings.Instance.OemUrls.TryGetValue(oemName, out string oemUrl);
- var printerTab = new MainTab(
+ return new MainTab(
tabTitle,
- "3D View Tab",
+ tabControl,
new PrinterTabPage(printer, theme, tabTitle.ToUpper()),
- "https://www.google.com/s2/favicons?domain=" + oemUrl ?? "www.matterhackers.com");
- printerTab.ToolTipText = "Preview 3D Design".Localize();
-
- theme.SetPrinterTabStyles(printerTab);
- return printerTab;
+ "https://www.google.com/s2/favicons?domain=" + oemUrl ?? "www.matterhackers.com")
+ {
+ Name = "3D View Tab",
+ MinimumSize = new Vector2(120, theme.shortButtonHeight)
+ };
}
- internal MainTab CreatePartTab(string tabTitle, BedConfig sceneContext, ThemeConfig theme, int tabIndex = 1)
+ internal MainTab CreatePartTab(string tabTitle, BedConfig sceneContext, ThemeConfig theme)
{
var partTab = new MainTab(
tabTitle,
- "newPart" + tabControl.TabCount,
+ tabControl,
new PartTabPage(null, sceneContext, theme, "xxxxx"),
- "https://i.imgur.com/nkeYgfU.png");
+ "https://i.imgur.com/nkeYgfU.png")
+ {
+ Name = "newPart" + tabControl.AllTabs.Count(),
+ MinimumSize = new Vector2(120, theme.shortButtonHeight)
+ };
- theme.SetPrinterTabStyles(partTab);
-
- var margin = partTab.Margin;
- partTab.Margin = new BorderDouble(1, margin.Bottom, 1, margin.Top);
-
- tabControl.AddTab(partTab, tabPosition: tabIndex);
- tabControl.SelectedTabIndex = tabIndex;
+ tabControl.AddTab(partTab);
return partTab;
}
diff --git a/PartPreviewWindow/PartTabPage.cs b/PartPreviewWindow/PartTabPage.cs
index 7e4f2eb7c..3dffd5b44 100644
--- a/PartPreviewWindow/PartTabPage.cs
+++ b/PartPreviewWindow/PartTabPage.cs
@@ -71,7 +71,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
}
};
viewControls3D.OverflowMenu.DynamicPopupContent = this.GetViewControls3DOverflowMenu;
-
+
bool isPrinterType = this is PrinterTabPage;
// The 3D model view
diff --git a/PartPreviewWindow/PlusTabPage.cs b/PartPreviewWindow/PlusTabPage.cs
index ed5e94585..139a7996e 100644
--- a/PartPreviewWindow/PlusTabPage.cs
+++ b/PartPreviewWindow/PlusTabPage.cs
@@ -40,7 +40,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
{
public class PlusTabPage : FlowLayoutWidget
{
- public PlusTabPage(PartPreviewContent partPreviewContent, PrinterConfig printer, ThemeConfig theme)
+ public PlusTabPage(PartPreviewContent partPreviewContent, SimpleTabs simpleTabs, ThemeConfig theme)
: base(FlowDirection.TopToBottom)
{
this.HAnchor = HAnchor.Stretch;
@@ -58,7 +58,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
createItemsSection.AddChild(createPart);
createPart.Click += (s, e) =>
{
- partPreviewContent.CreatePartTab("New Part", new BedConfig(), theme);
+ UiThread.RunOnIdle(() =>
+ {
+ simpleTabs.RemoveTab(simpleTabs.ActiveTab);
+ partPreviewContent.CreatePartTab("New Part", new BedConfig(), theme);
+ });
};
var createPrinter = theme.ButtonFactory.Generate("Create Printer".Localize());
@@ -67,20 +71,20 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
createPrinter.HAnchor = HAnchor.Left;
createPrinter.Click += (s, e) =>
{
- if (ApplicationController.Instance.ActivePrinter.Connection.PrinterIsPrinting
+ UiThread.RunOnIdle(() =>
+ {
+ simpleTabs.RemoveTab(simpleTabs.ActiveTab);
+
+ if (ApplicationController.Instance.ActivePrinter.Connection.PrinterIsPrinting
|| ApplicationController.Instance.ActivePrinter.Connection.PrinterIsPaused)
- {
- UiThread.RunOnIdle(() =>
- StyledMessageBox.ShowMessageBox("Please wait until the print has finished and try again.".Localize(), "Can't add printers while printing".Localize())
- );
- }
- else
- {
- UiThread.RunOnIdle(() =>
+ {
+ StyledMessageBox.ShowMessageBox("Please wait until the print has finished and try again.".Localize(), "Can't add printers while printing".Localize());
+ }
+ else
{
DialogWindow.Show(PrinterSetup.GetBestStartPage(PrinterSetup.StartPageOptions.ShowMakeModel));
- });
- }
+ }
+ });
};
createItemsSection.AddChild(createPrinter);
@@ -99,6 +103,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
if (!string.IsNullOrEmpty(result.FileName)
&& File.Exists(result.FileName))
{
+ simpleTabs.RemoveTab(simpleTabs.ActiveTab);
ImportSettingsPage.ImportFromExisting(result.FileName);
}
});
@@ -122,8 +127,12 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
redeemDesignCode.HAnchor = HAnchor.Left;
redeemDesignCode.Click += (s, e) =>
{
- // Implementation already does RunOnIdle
- ApplicationController.Instance.RedeemDesignCode?.Invoke();
+ UiThread.RunOnIdle(() =>
+ {
+ simpleTabs.RemoveTab(simpleTabs.ActiveTab);
+ // Implementation already does RunOnIdle
+ ApplicationController.Instance.RedeemDesignCode?.Invoke();
+ });
};
otherItemsSection.AddChild(redeemDesignCode);
@@ -133,8 +142,13 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
redeemShareCode.HAnchor = HAnchor.Left;
redeemShareCode.Click += (s, e) =>
{
- // Implementation already does RunOnIdle
- ApplicationController.Instance.EnterShareCode?.Invoke();
+ UiThread.RunOnIdle(() =>
+ {
+ simpleTabs.RemoveTab(simpleTabs.ActiveTab);
+
+ // Implementation already does RunOnIdle
+ ApplicationController.Instance.EnterShareCode?.Invoke();
+ });
};
otherItemsSection.AddChild(redeemShareCode);
@@ -147,17 +161,22 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
shopButton.Margin = buttonSpacing;
shopButton.Click += (sender, e) =>
{
- double activeFilamentDiameter = 0;
- if (ActiveSliceSettings.Instance.PrinterSelected)
+ UiThread.RunOnIdle(() =>
{
- activeFilamentDiameter = 3;
- if (ActiveSliceSettings.Instance.GetValue(SettingsKey.filament_diameter) < 2)
- {
- activeFilamentDiameter = 1.75;
- }
- }
+ simpleTabs.RemoveTab(simpleTabs.ActiveTab);
- MatterControlApplication.Instance.LaunchBrowser("http://www.matterhackers.com/mc/store/redirect?d={0}&clk=mcs&a={1}".FormatWith(activeFilamentDiameter, OemSettings.Instance.AffiliateCode));
+ double activeFilamentDiameter = 0;
+ if (ActiveSliceSettings.Instance.PrinterSelected)
+ {
+ activeFilamentDiameter = 3;
+ if (ActiveSliceSettings.Instance.GetValue(SettingsKey.filament_diameter) < 2)
+ {
+ activeFilamentDiameter = 1.75;
+ }
+ }
+
+ MatterControlApplication.Instance.LaunchBrowser("http://www.matterhackers.com/mc/store/redirect?d={0}&clk=mcs&a={1}".FormatWith(activeFilamentDiameter, OemSettings.Instance.AffiliateCode));
+ });
};
otherItemsSection.AddChild(shopButton);
}
diff --git a/PartPreviewWindow/PrinterTabPage.cs b/PartPreviewWindow/PrinterTabPage.cs
index 06e078197..42234eff1 100644
--- a/PartPreviewWindow/PrinterTabPage.cs
+++ b/PartPreviewWindow/PrinterTabPage.cs
@@ -53,7 +53,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
private DoubleSolidSlider layerRenderRatioSlider;
private SystemWindow parentSystemWindow;
private SliceLayerSelector layerScrollbar;
- private PrinterConfig printer;
+ internal PrinterConfig printer;
internal GCode3DWidget gcode3DWidget;
public PrinterTabPage(PrinterConfig printer, ThemeConfig theme, string tabTitle)
@@ -281,7 +281,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
{
Visible = (this.ViewMode == PartViewMode.Layers2D)
};
- view3DContainer.AddChild(gcode2DWidget);
+ view3DWidget.InteractionLayer.AddChild(gcode2DWidget);
viewControls3D.Layers2DButton.Enabled = true;
}
diff --git a/PartPreviewWindow/Toolbar.cs b/PartPreviewWindow/Toolbar.cs
new file mode 100644
index 000000000..d2871e8a8
--- /dev/null
+++ b/PartPreviewWindow/Toolbar.cs
@@ -0,0 +1,268 @@
+/*
+Copyright (c) 2017, Lars Brubaker
+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.Linq;
+using MatterHackers.Agg.Platform;
+using MatterHackers.Agg.UI;
+using MatterHackers.Localizations;
+using MatterHackers.MatterControl.CustomWidgets;
+using MatterHackers.VectorMath;
+
+namespace MatterHackers.MatterControl.PartPreviewWindow
+{
+ ///
+ /// A toolbar with an optional right anchored element and an ActionBar child to add actions to the bar
+ ///
+ public class Toolbar : Bar
+ {
+ public FlowLayoutWidget ActionBar { get; }
+
+ public HorizontalLine SeparatorLine { get; }
+
+ public Toolbar(GuiWidget rightAnchorItem, ThemeConfig theme, bool bottomBorder = true)
+ : base(rightAnchorItem, theme)
+ {
+ GuiWidget context = this;
+
+ this.ActionBar = new FlowLayoutWidget()
+ {
+ HAnchor = HAnchor.Stretch
+ };
+
+ if (bottomBorder)
+ {
+ var column = new FlowLayoutWidget(FlowDirection.TopToBottom)
+ {
+ HAnchor = HAnchor.Stretch,
+ VAnchor = VAnchor.Fit
+ };
+ this.AddChild(column, 0);
+
+ column.AddChild(this.ActionBar);
+ column.AddChild(this.SeparatorLine = new HorizontalLine(40));
+ }
+ else
+ {
+ this.AddChild(this.ActionBar, 0);
+ }
+ }
+ }
+
+ public interface ITab
+ {
+ GuiWidget TabContent { get; }
+ }
+
+ ///
+ /// A toolbar like item with an optional right anchored element
+ ///
+ public class Bar : GuiWidget
+ {
+ public Bar(GuiWidget rightAnchorItem, ThemeConfig theme)
+ {
+ if (rightAnchorItem != null)
+ {
+ rightAnchorItem.HAnchor |= HAnchor.Right;
+ this.AddChild(rightAnchorItem);
+ }
+ }
+ }
+
+ ///
+ /// A toolbar and associated tab body
+ ///
+ public class SimpleTabs : FlowLayoutWidget
+ {
+ public Toolbar TabBar { get; }
+
+ private GuiWidget body;
+
+ public SimpleTabs(GuiWidget rightAnchorItem, ThemeConfig theme, bool bottomBorder = true)
+ : base(FlowDirection.TopToBottom)
+ {
+ this.AddChild(TabBar = new Toolbar(rightAnchorItem, theme, bottomBorder)
+ {
+ HAnchor = HAnchor.Stretch,
+ VAnchor = VAnchor.Fit
+ });
+
+ this.AddChild(body = new GuiWidget()
+ {
+ HAnchor = HAnchor.Stretch,
+ VAnchor = VAnchor.Stretch,
+ });
+ }
+
+ public event EventHandler ActiveTabChanged;
+
+ private List _allTabs = new List();
+
+ public IEnumerable AllTabs => _allTabs;
+
+ public void AddTab(GuiWidget tabWidget, int position)
+ {
+ var iTab = tabWidget as ITab;
+
+ _allTabs.Add(tabWidget as ITab);
+
+ tabWidget.Click += TabWidget_Click;
+
+ this.TabBar.ActionBar.AddChild(tabWidget, position);
+
+ this.body.AddChild(iTab.TabContent);
+ }
+
+ private void TabWidget_Click(object sender, MouseEventArgs e)
+ {
+ this.ActiveTab = sender as ITab;
+ }
+
+ internal void RemoveTab(ITab tab)
+ {
+ _allTabs.Remove(tab);
+
+ TabBar.ActionBar.RemoveChild(tab as GuiWidget);
+ body.RemoveChild(tab.TabContent);
+
+ ActiveTab = _allTabs.LastOrDefault();
+ }
+
+ private ITab _activeTab;
+ public ITab ActiveTab
+ {
+ get => _activeTab;
+ set
+ {
+ if (_activeTab != value)
+ {
+ _activeTab = value;
+
+ var clickedWidget = value as GuiWidget;
+
+ foreach (var tab in _allTabs)
+ {
+ tab.TabContent.Visible = (tab == clickedWidget);
+ }
+
+ this.OnActiveTabChanged();
+ }
+ }
+ }
+
+ protected virtual void OnActiveTabChanged()
+ {
+ this.ActiveTabChanged?.Invoke(this, null);
+ }
+ }
+
+ public class ChromeTabs : SimpleTabs
+ {
+ private NewTabButton plusTabButton;
+
+ public ChromeTabs(GuiWidget rightAnchorItem, ThemeConfig theme)
+ : base(rightAnchorItem, theme)
+ {
+ // TODO: add in the printers and designs that are currently open (or were open last run).
+ var leadingTabAdornment = new GuiWidget()
+ {
+ MinimumSize = new VectorMath.Vector2(16, theme.shortButtonHeight),
+ VAnchor = VAnchor.Bottom
+ };
+ leadingTabAdornment.AfterDraw += (s, e) =>
+ {
+ var firstItem = this.AllTabs.OfType().FirstOrDefault();
+ MainTab.DrawTabLowerRight(e.graphics2D, leadingTabAdornment.LocalBounds, (firstItem == this.ActiveTab) ? MainTab.ActiveTabColor : MainTab.InactiveTabColor);
+ };
+ this.TabBar.ActionBar.AddChild(leadingTabAdornment);
+
+ // TODO: add in the printers and designs that are currently open (or were open last run).
+ plusTabButton = new NewTabButton(
+ AggContext.StaticData.LoadIcon("fa-plus_12.png", IconColor.Theme),
+ this,
+ theme)
+ {
+ VAnchor = VAnchor.Bottom,
+ MinimumSize = new Vector2(16, theme.shortButtonHeight),
+ ToolTipText = "Create New".Localize()
+ };
+ plusTabButton.IconButton.Click += (s, e) =>
+ {
+ this.AddTab(
+ new MainTab("New Tab".Localize(), this, this.NewTabPage())
+ {
+ MinimumSize = new Vector2(0, theme.shortButtonHeight)
+ });
+ };
+
+ this.TabBar.ActionBar.AddChild(plusTabButton);
+ }
+
+ public void AddTab(GuiWidget tab)
+ {
+ var position = this.TabBar.ActionBar.GetChildIndex(plusTabButton);
+
+ if (tab is MainTab mainTab)
+ {
+ mainTab.PreviousTab = this.AllTabs.OfType().LastOrDefault();
+ if (mainTab.PreviousTab != null)
+ {
+ mainTab.PreviousTab.NextTab = mainTab;
+ }
+
+ this.AddTab(tab, position);
+
+ mainTab.CloseClicked += MainTab_CloseClicked;
+ this.ActiveTab = mainTab;
+ }
+ }
+
+ private void MainTab_CloseClicked(object sender, EventArgs e)
+ {
+ if (sender is ITab tab)
+ {
+ this.RemoveTab(sender as ITab);
+
+ if (tab.TabContent is PrinterTabPage printerTab)
+ {
+ printerTab.printer.Settings.Helpers.SetMarkedForDelete(true);
+ }
+ }
+ }
+
+ public Func NewTabPage { get; set; }
+
+ protected override void OnActiveTabChanged()
+ {
+ plusTabButton.LastTab = this.AllTabs.LastOrDefault();
+ base.OnActiveTabChanged();
+ }
+ }
+}
\ No newline at end of file
diff --git a/PartPreviewWindow/View3D/SlicePopupMenu.cs b/PartPreviewWindow/View3D/SlicePopupMenu.cs
index b4cfc80cd..6f75112c1 100644
--- a/PartPreviewWindow/View3D/SlicePopupMenu.cs
+++ b/PartPreviewWindow/View3D/SlicePopupMenu.cs
@@ -30,15 +30,12 @@ either expressed or implied, of the FreeBSD Project.
using System;
using System.Diagnostics;
using System.Linq;
-using System.Threading;
using System.Threading.Tasks;
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
using MatterHackers.GCodeVisualizer;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.CustomWidgets;
-using MatterHackers.MatterControl.PrintQueue;
-using MatterHackers.MatterControl.SlicerConfiguration;
namespace MatterHackers.MatterControl.PartPreviewWindow
{