Move to new library model and view
- Add new listview control for library content - Migrate library providers to containers - Cloud, Sqlite, Directories, Queue, History - Migrate SideBar components to containers - Primatives, Text, Braille, ImageConverter - Create new library container types - Zip files, Calibration parts, Printer SDCards - Reduce leftnav to Library, Settings, Controls, Options - Add DragDrop support for image content
This commit is contained in:
parent
b0b249e0c3
commit
03a593f1b5
129 changed files with 7643 additions and 10331 deletions
69
Library/Widgets/ListView.cd
Normal file
69
Library/Widgets/ListView.cd
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ClassDiagram MajorVersion="1" MinorVersion="1">
|
||||
<Class Name="MatterHackers.MatterControl.CustomWidgets.ListViewItem">
|
||||
<Position X="9" Y="1.75" Width="2.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAgAIAAAAAABAAABAAAAAAAAAAAAAAABlAgASAAAAAA=</HashCode>
|
||||
<FileName>LibraryProviders\ListView\ListViewItem.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="MatterHackers.MatterControl.CustomWidgets.ListViewItemBase" Collapsed="true">
|
||||
<Position X="4.25" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAQAIEAECAAAABQAEAACBABEYIBKgAASAAKAEk=</HashCode>
|
||||
<FileName>LibraryProviders\ListView\ListViewItemBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="MatterHackers.MatterControl.CustomWidgets.IconListView">
|
||||
<Position X="5.25" Y="3" Width="2" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAQAAAAAAAIAAgAAAAwAACAAAAABAAAAAAAAA=</HashCode>
|
||||
<FileName>LibraryProviders\ListView\IconListView.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="MatterHackers.MatterControl.CustomWidgets.IconViewItem" Collapsed="true">
|
||||
<Position X="2.75" Y="1.75" Width="2" />
|
||||
<InheritanceLine Type="MatterHackers.MatterControl.CustomWidgets.ListViewItemBase" FixedFromPoint="true">
|
||||
<Path>
|
||||
<Point X="4.25" Y="0.938" />
|
||||
<Point X="3.5" Y="0.938" />
|
||||
<Point X="3.5" Y="1.75" />
|
||||
</Path>
|
||||
</InheritanceLine>
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAACCAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>LibraryProviders\ListView\IconListView.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="MatterHackers.MatterControl.CustomWidgets.RowListView">
|
||||
<Position X="2.75" Y="3" Width="2" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAgAAAAwAAAAAAAABAAAAAAAAA=</HashCode>
|
||||
<FileName>LibraryProviders\ListView\RowListView.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="MatterHackers.MatterControl.CustomWidgets.RowViewItem" Collapsed="true">
|
||||
<Position X="5.25" Y="1.75" Width="2" />
|
||||
<InheritanceLine Type="MatterHackers.MatterControl.CustomWidgets.ListViewItemBase" FixedFromPoint="true">
|
||||
<Path>
|
||||
<Point X="5.75" Y="0.938" />
|
||||
<Point X="6.5" Y="0.938" />
|
||||
<Point X="6.5" Y="1.75" />
|
||||
</Path>
|
||||
</InheritanceLine>
|
||||
<TypeIdentifier>
|
||||
<HashCode>QAEAAAAAAIEYAAACAAAACQgCAAAAAIAQAQAAQwAAAAE=</HashCode>
|
||||
<FileName>LibraryProviders\ListView\RowListView.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Interface Name="MatterHackers.MatterControl.CustomWidgets.IListContentView">
|
||||
<Position X="0.5" Y="3" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAgAAAAwAAAAAAAABAAAAAAAAA=</HashCode>
|
||||
<FileName>LibraryProviders\ListView\IListContentView.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Font Name="Segoe UI" Size="9" />
|
||||
</ClassDiagram>
|
||||
40
Library/Widgets/ListView/IListContentView.cs
Normal file
40
Library/Widgets/ListView/IListContentView.cs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
|
||||
namespace MatterHackers.MatterControl.CustomWidgets
|
||||
{
|
||||
public interface IListContentView
|
||||
{
|
||||
int ThumbWidth { get; }
|
||||
int ThumbHeight { get; }
|
||||
void AddItem(ListViewItem item);
|
||||
void ClearItems();
|
||||
}
|
||||
}
|
||||
172
Library/Widgets/ListView/IconListView.cs
Normal file
172
Library/Widgets/ListView/IconListView.cs
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
Copyright (c) 2017, 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 MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Image;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.MatterControl.Library;
|
||||
using MatterHackers.VectorMath;
|
||||
|
||||
namespace MatterHackers.MatterControl.CustomWidgets
|
||||
{
|
||||
public class IconListView : FlowLayoutWidget, IListContentView
|
||||
{
|
||||
public int ThumbWidth { get; set; } = 128;
|
||||
public int ThumbHeight { get; set; } = 128;
|
||||
|
||||
private FlowLayoutWidget rowButtonContainer = null;
|
||||
|
||||
public IconListView()
|
||||
: base(FlowDirection.TopToBottom)
|
||||
{
|
||||
}
|
||||
|
||||
private int cellIndex = 0;
|
||||
|
||||
int columnCount = 1;
|
||||
|
||||
public override void OnBoundsChanged(EventArgs e)
|
||||
{
|
||||
columnCount = (int)Math.Floor(this.LocalBounds.Width / ThumbWidth);
|
||||
base.OnBoundsChanged(e);
|
||||
}
|
||||
|
||||
public void AddItem(ListViewItem item)
|
||||
{
|
||||
var iconView = new IconViewItem(item, this.ThumbWidth, this.ThumbHeight);
|
||||
item.ViewWidget = iconView;
|
||||
|
||||
if (rowButtonContainer == null)
|
||||
{
|
||||
rowButtonContainer = new FlowLayoutWidget(FlowDirection.LeftToRight);
|
||||
rowButtonContainer.HAnchor = HAnchor.ParentLeftRight;
|
||||
|
||||
rowButtonContainer.AddChild(iconView);
|
||||
this.AddChild(rowButtonContainer);
|
||||
cellIndex = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rowButtonContainer.AddChild(iconView);
|
||||
|
||||
if (cellIndex++ >= columnCount - 1)
|
||||
{
|
||||
rowButtonContainer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearItems()
|
||||
{
|
||||
rowButtonContainer = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class IconViewItem : ListViewItemBase
|
||||
{
|
||||
public IconViewItem(ListViewItem item, int thumbWidth, int thumbHeight)
|
||||
: base(item, thumbWidth, thumbHeight)
|
||||
{
|
||||
this.VAnchor = VAnchor.FitToChildren;
|
||||
this.HAnchor = HAnchor.FitToChildren;
|
||||
this.Padding = 4;
|
||||
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,
|
||||
};
|
||||
|
||||
imageWidget.Click += (sender, e) =>
|
||||
{
|
||||
if (listViewItem.Model is ILibraryContentItem)
|
||||
{
|
||||
if (this.IsSelected)
|
||||
{
|
||||
listViewItem.ListView.SelectedItems.Remove(listViewItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Keyboard.IsKeyDown(Keys.ControlKey))
|
||||
{
|
||||
listViewItem.ListView.SelectedItems.Clear();
|
||||
}
|
||||
|
||||
listViewItem.ListView.SelectedItems.Add(listViewItem);
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
};
|
||||
|
||||
container.AddChild(imageWidget);
|
||||
|
||||
int maxWidth = thumbWidth - 4;
|
||||
|
||||
var text = new TextWidget(item.Model.Name, 0, 0, 9, textColor: ActiveTheme.Instance.PrimaryTextColor)
|
||||
{
|
||||
AutoExpandBoundsToText = false,
|
||||
EllipsisIfClipped = true,
|
||||
HAnchor = HAnchor.ParentCenter,
|
||||
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);
|
||||
}
|
||||
|
||||
public override async void OnLoad(EventArgs args)
|
||||
{
|
||||
base.OnLoad(args);
|
||||
await this.LoadItemThumbnail();
|
||||
}
|
||||
|
||||
public override RGBA_Bytes BackgroundColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.IsSelected ? ActiveTheme.Instance.PrimaryAccentColor : RGBA_Bytes.Transparent;
|
||||
}
|
||||
set { }
|
||||
}
|
||||
}
|
||||
}
|
||||
357
Library/Widgets/ListView/ListView.cs
Normal file
357
Library/Widgets/ListView/ListView.cs
Normal file
|
|
@ -0,0 +1,357 @@
|
|||
/*
|
||||
Copyright (c) 2017, 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.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Image;
|
||||
using MatterHackers.Agg.PlatformAbstract;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.MatterControl.Library;
|
||||
using MatterHackers.VectorMath;
|
||||
|
||||
namespace MatterHackers.MatterControl.CustomWidgets
|
||||
{
|
||||
|
||||
|
||||
public class ListView : ScrollableWidget
|
||||
{
|
||||
private EventHandler unregisterEvents;
|
||||
|
||||
private bool editMode = false;
|
||||
|
||||
internal GuiWidget contentView;
|
||||
|
||||
private ILibraryContext LibraryContext;
|
||||
|
||||
public ListView(ILibraryContext context)
|
||||
{
|
||||
this.LibraryContext = context;
|
||||
|
||||
// Set Display Attributes
|
||||
this.MinimumSize = new Vector2(0, 200);
|
||||
this.AnchorAll();
|
||||
this.BackgroundColor = ActiveTheme.Instance.TertiaryBackgroundColor;
|
||||
this.AutoScroll = true;
|
||||
this.ScrollArea.Padding = new BorderDouble(3);
|
||||
|
||||
// AddWatermark
|
||||
string imagePath = Path.Combine("OEMSettings", "watermark.png");
|
||||
if (StaticData.Instance.FileExists(imagePath))
|
||||
{
|
||||
this.AddChildToBackground(new ImageWidget(StaticData.Instance.LoadImage(imagePath))
|
||||
{
|
||||
VAnchor = VAnchor.ParentCenter,
|
||||
HAnchor = HAnchor.ParentCenter
|
||||
});
|
||||
}
|
||||
|
||||
this.ScrollArea.HAnchor = HAnchor.ParentLeftRight;
|
||||
|
||||
AutoScroll = true;
|
||||
|
||||
this.ListContentView = new IconListView();
|
||||
context.ContainerChanged += ActiveContainer_Changed;
|
||||
context.ContainerReloaded += ActiveContainer_Reloaded;
|
||||
}
|
||||
|
||||
public ILibraryContainer ActiveContainer => this.LibraryContext.ActiveContainer;
|
||||
|
||||
public RGBA_Bytes ThumbnailBackground { get; } = ActiveTheme.Instance.TertiaryBackgroundColor.AdjustLightness(1.1).GetAsRGBA_Bytes();
|
||||
public RGBA_Bytes ThumbnailForeground { get; set; } = ActiveTheme.Instance.PrimaryAccentColor;
|
||||
|
||||
private GuiWidget stashedView = null;
|
||||
|
||||
private void ActiveContainer_Changed(object sender, ContainerChangedEventArgs e)
|
||||
{
|
||||
var activeContainer = e.ActiveContainer;
|
||||
|
||||
var containerDefaultView = activeContainer?.DefaultView;
|
||||
|
||||
if (containerDefaultView != null
|
||||
&& containerDefaultView != this.ListContentView)
|
||||
{
|
||||
stashedView = this.contentView;
|
||||
// Critical that assign to the contentView backing field and not the ListContentView property that uses it
|
||||
this.SetContentView(activeContainer.DefaultView);
|
||||
}
|
||||
else if (stashedView != null)
|
||||
{
|
||||
this.SetContentView(stashedView);
|
||||
stashedView = null;
|
||||
}
|
||||
|
||||
DisplayContainerContent(activeContainer);
|
||||
}
|
||||
|
||||
private void ActiveContainer_Reloaded(object sender, EventArgs e)
|
||||
{
|
||||
DisplayContainerContent(ActiveContainer);
|
||||
}
|
||||
|
||||
private List<ListViewItem> items = new List<ListViewItem>();
|
||||
|
||||
public IEnumerable<ListViewItem> Items => items;
|
||||
|
||||
/*
|
||||
* bool isTraceable = listViewItem.Model is ILibraryPrintItem;
|
||||
bool hasID = !string.IsNullOrEmpty(listViewItem.Model.ID);
|
||||
List<ListViewItem> acquireItems,
|
||||
if (hasID
|
||||
&& isTraceable
|
||||
&& thumbnail == null)
|
||||
{
|
||||
// Schedule for collection, display default thumb until then
|
||||
acquireItems.Add(listViewItem);
|
||||
}
|
||||
*/
|
||||
/// <summary>
|
||||
/// Empties the list children and repopulates the list with the source container content
|
||||
/// </summary>
|
||||
/// <param name="sourceContainer">The container to load</param>
|
||||
/// <returns>Async Task</returns>
|
||||
private async Task DisplayContainerContent(ILibraryContainer sourceContainer)
|
||||
{
|
||||
if (sourceContainer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var itemsNeedingLoad = new List<ListViewItem>();
|
||||
|
||||
this.items.Clear();
|
||||
|
||||
this.SelectedItems.Clear();
|
||||
contentView.CloseAllChildren();
|
||||
|
||||
var itemsContentView = contentView as IListContentView;
|
||||
itemsContentView.ClearItems();
|
||||
|
||||
int width = itemsContentView.ThumbWidth;
|
||||
int height = itemsContentView.ThumbHeight;
|
||||
|
||||
// TODO: Disabled to consider upfolder on breadcrumb bar
|
||||
if (sourceContainer.Parent != null && false)
|
||||
{
|
||||
var icon = LibraryProviderHelpers.LoadInvertIcon("FileDialog", "up_folder.png");
|
||||
icon = ResizeCanvas(icon, width, height);
|
||||
|
||||
// Up folder item
|
||||
var item = new DynamicContainerLink("..", icon, null);
|
||||
var listViewItem = new ListViewItem(item, this)
|
||||
{
|
||||
Text = "..",
|
||||
};
|
||||
|
||||
listViewItem.DoubleClick += listViewItem_DoubleClick;
|
||||
|
||||
items.Add(listViewItem);
|
||||
itemsContentView.AddItem(listViewItem);
|
||||
}
|
||||
|
||||
// Folder items
|
||||
foreach (var childContainer in sourceContainer.ChildContainers.Where(c => c.IsVisible))
|
||||
{
|
||||
var listViewItem = new ListViewItem(childContainer, this);
|
||||
listViewItem.DoubleClick += listViewItem_DoubleClick;
|
||||
|
||||
items.Add(listViewItem);
|
||||
itemsContentView.AddItem(listViewItem);
|
||||
}
|
||||
|
||||
// List items
|
||||
foreach (var item in sourceContainer.Items.Where(i => i.IsVisible))
|
||||
{
|
||||
var listViewItem = new ListViewItem(item, this);
|
||||
listViewItem.DoubleClick += listViewItem_DoubleClick;
|
||||
|
||||
items.Add(listViewItem);
|
||||
itemsContentView.AddItem(listViewItem);
|
||||
}
|
||||
}
|
||||
|
||||
public enum ViewMode
|
||||
{
|
||||
Icons,
|
||||
List
|
||||
}
|
||||
|
||||
private void SetContentView(GuiWidget contentView)
|
||||
{
|
||||
this.ScrollArea.CloseAllChildren();
|
||||
|
||||
this.contentView = contentView;
|
||||
this.contentView.HAnchor = HAnchor.ParentLeftRight;
|
||||
this.contentView.Name = "Library ListView";
|
||||
this.AddChild(this.contentView);
|
||||
}
|
||||
|
||||
public GuiWidget ListContentView
|
||||
{
|
||||
get { return contentView; }
|
||||
set
|
||||
{
|
||||
if (value is IListContentView)
|
||||
{
|
||||
SetContentView(value);
|
||||
|
||||
// Allow some time for layout to occur and contentView to become sized before loading content
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
DisplayContainerContent(ActiveContainer);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FormatException("ListContentView must be assignable from IListContentView");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal ImageBuffer LoadCachedImage(ListViewItem listViewItem)
|
||||
{
|
||||
string cachePath = ApplicationController.Instance.CachePath(listViewItem.Model);
|
||||
|
||||
bool isCached = !string.IsNullOrEmpty(cachePath) && File.Exists(cachePath);
|
||||
if (isCached)
|
||||
{
|
||||
ImageBuffer thumbnail = new ImageBuffer();
|
||||
ImageIO.LoadImageData(cachePath, thumbnail);
|
||||
thumbnail.SetRecieveBlender(new BlenderPreMultBGRA());
|
||||
|
||||
return thumbnail.MultiplyWithPrimaryAccent();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO: ResizeCanvas is also colorizing thumbnails as a proof of concept
|
||||
public ImageBuffer ResizeCanvas(ImageBuffer originalImage, int width, int height)
|
||||
{
|
||||
var destImage = new ImageBuffer(width, height, 32, originalImage.GetRecieveBlender());
|
||||
|
||||
var renderGraphics = destImage.NewGraphics2D();
|
||||
renderGraphics.Clear(this.ThumbnailBackground);
|
||||
|
||||
var x = width / 2 - originalImage.Width / 2;
|
||||
var y = height / 2 - originalImage.Height / 2;
|
||||
|
||||
var center = new RectangleInt(x, y + originalImage.Height, x + originalImage.Width, y);
|
||||
//renderGraphics.FillRectangle(center, this.ThumbnailForeground);
|
||||
|
||||
renderGraphics.ImageRenderQuality = Graphics2D.TransformQuality.Best;
|
||||
|
||||
//originalImage = originalImage.Multiply(this.ThumbnailBackground);
|
||||
|
||||
renderGraphics.Render(originalImage, width /2 - originalImage.Width /2, height /2 - originalImage.Height /2);
|
||||
|
||||
renderGraphics.FillRectangle(center, RGBA_Bytes.Transparent);
|
||||
|
||||
return destImage;
|
||||
}
|
||||
|
||||
private void listViewItem_DoubleClick(object sender, MouseEventArgs e)
|
||||
{
|
||||
UiThread.RunOnIdle(async () =>
|
||||
{
|
||||
var listViewItem = sender as ListViewItem;
|
||||
var itemModel = listViewItem.Model;
|
||||
|
||||
if (listViewItem?.Text == "..")
|
||||
{
|
||||
// Up folder tiem
|
||||
if (ActiveContainer?.Parent != null)
|
||||
{
|
||||
LoadContainer(ActiveContainer.Parent);
|
||||
}
|
||||
}
|
||||
else if (itemModel is ILibraryContainerLink)
|
||||
{
|
||||
// Container items
|
||||
var containerLink = itemModel as ILibraryContainerLink;
|
||||
if (containerLink != null)
|
||||
{
|
||||
var container = await containerLink.GetContainer(null);
|
||||
container.Parent = ActiveContainer;
|
||||
|
||||
LoadContainer(container);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// List items
|
||||
var contentModel = itemModel as ILibraryContentStream;
|
||||
if (contentModel != null)
|
||||
{
|
||||
listViewItem.StartProgress();
|
||||
|
||||
var result = contentModel.CreateContent(listViewItem.ProgressReporter);
|
||||
if (result.Object3D != null)
|
||||
{
|
||||
var scene = MatterControlApplication.Instance.ActiveView3DWidget.Scene;
|
||||
|
||||
scene.ModifyChildren(children =>
|
||||
{
|
||||
children.Add(result.Object3D);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
listViewItem.EndProgress();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void LoadContainer(ILibraryContainer temp)
|
||||
{
|
||||
this.LibraryContext.ActiveContainer = temp;
|
||||
}
|
||||
|
||||
public ObservableCollection<ListViewItem> SelectedItems { get; } = new ObservableCollection<ListViewItem>();
|
||||
|
||||
public ListViewItem DragSourceRowItem { get; set; }
|
||||
|
||||
public override void OnClosed(ClosedEventArgs e)
|
||||
{
|
||||
if (this.LibraryContext != null)
|
||||
{
|
||||
this.LibraryContext.ContainerChanged -= this.ActiveContainer_Changed;
|
||||
this.LibraryContext.ContainerReloaded -= this.ActiveContainer_Reloaded;
|
||||
}
|
||||
|
||||
unregisterEvents?.Invoke(this, null);
|
||||
base.OnClosed(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
108
Library/Widgets/ListView/ListViewItem.cs
Normal file
108
Library/Widgets/ListView/ListViewItem.cs
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
Copyright (c) 2017, 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 MatterHackers.Agg;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.Localizations;
|
||||
using MatterHackers.MatterControl.Library;
|
||||
|
||||
namespace MatterHackers.MatterControl.CustomWidgets
|
||||
{
|
||||
public class ListViewItem
|
||||
{
|
||||
public ILibraryItem Model { get; }
|
||||
public ListView ListView { get; }
|
||||
public string Text { get; internal set; }
|
||||
|
||||
public GuiWidget ProgressTarget { get; internal set; }
|
||||
|
||||
public ListViewItemBase ViewWidget { get; set; }
|
||||
|
||||
ProgressControl processingProgressControl;
|
||||
|
||||
internal void ProgressReporter(double progress0To1, string processingState, out bool continueProcessing)
|
||||
{
|
||||
continueProcessing = true;
|
||||
|
||||
if (processingProgressControl == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
processingProgressControl.Visible = progress0To1 != 0;
|
||||
processingProgressControl.RatioComplete = progress0To1;
|
||||
processingProgressControl.ProcessType = processingState;
|
||||
|
||||
if (progress0To1 == 1)
|
||||
{
|
||||
EndProgress();
|
||||
}
|
||||
}
|
||||
|
||||
public ListViewItem(ILibraryItem listItemData, ListView dragConsumer)
|
||||
{
|
||||
this.ListView = dragConsumer;
|
||||
this.Model = listItemData;
|
||||
}
|
||||
|
||||
public event EventHandler<MouseEventArgs> DoubleClick;
|
||||
|
||||
internal void OnDoubleClick()
|
||||
{
|
||||
DoubleClick?.Invoke(this, null);
|
||||
}
|
||||
|
||||
public void StartProgress()
|
||||
{
|
||||
processingProgressControl = new ProgressControl("Loading...".Localize(), RGBA_Bytes.Black, ActiveTheme.Instance.SecondaryAccentColor, (int)(100 * GuiWidget.DeviceScale), 5, 0)
|
||||
{
|
||||
PointSize = 8,
|
||||
Margin = 0,
|
||||
Visible = true
|
||||
};
|
||||
|
||||
ProgressTarget?.AddChild(processingProgressControl);
|
||||
}
|
||||
|
||||
public void EndProgress()
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
if (processingProgressControl == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
processingProgressControl.Close();
|
||||
processingProgressControl = null;
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
338
Library/Widgets/ListView/ListViewItemBase.cs
Normal file
338
Library/Widgets/ListView/ListViewItemBase.cs
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
/*
|
||||
Copyright (c) 2017, 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.Threading.Tasks;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Image;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.Agg.VertexSource;
|
||||
using MatterHackers.MatterControl.Library;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using MatterHackers.VectorMath;
|
||||
|
||||
namespace MatterHackers.MatterControl.CustomWidgets
|
||||
{
|
||||
public class ListViewItemBase : GuiWidget
|
||||
{
|
||||
private static ImageBuffer defaultFolderIcon = LibraryProviderHelpers.LoadInvertIcon("FileDialog", "folder.png");
|
||||
private static ImageBuffer defaultItemIcon = LibraryProviderHelpers.LoadInvertIcon("FileDialog", "file.png");
|
||||
private static ImageBuffer generatingThumbnailIcon = LibraryProviderHelpers.LoadInvertIcon("building_thumbnail_40x40.png");
|
||||
|
||||
protected ListViewItem listViewItem;
|
||||
protected View3DWidget view3DWidget;
|
||||
protected bool mouseInBounds = false;
|
||||
private bool mouseDownInBounds = false;
|
||||
private Vector2 mouseDownAt;
|
||||
|
||||
protected ImageWidget imageWidget;
|
||||
protected int thumbWidth;
|
||||
protected int thumbHeight;
|
||||
|
||||
public ListViewItemBase(ListViewItem listViewItem, int width, int height)
|
||||
{
|
||||
this.listViewItem = listViewItem;
|
||||
this.thumbWidth = width;
|
||||
this.thumbHeight = height;
|
||||
}
|
||||
|
||||
protected async Task LoadItemThumbnail()
|
||||
{
|
||||
var listView = listViewItem.ListView;
|
||||
|
||||
var thumbnail = listView.LoadCachedImage(listViewItem);
|
||||
if (thumbnail != null)
|
||||
{
|
||||
SetItemThumbnail(thumbnail);
|
||||
return;
|
||||
}
|
||||
|
||||
var itemModel = listViewItem.Model;
|
||||
|
||||
if (thumbnail == null)
|
||||
{
|
||||
// Ask the container - allows the container to provide its own interpretation of the item thumbnail
|
||||
thumbnail = await listView.ActiveContainer.GetThumbnail(itemModel, thumbWidth, thumbHeight);
|
||||
}
|
||||
|
||||
if (thumbnail == null && itemModel is IThumbnail)
|
||||
{
|
||||
// If the item provides its own thumbnail, try to collect it
|
||||
thumbnail = await (itemModel as IThumbnail).GetThumbnail(thumbWidth, thumbHeight);
|
||||
}
|
||||
|
||||
if (thumbnail == null)
|
||||
{
|
||||
// Ask content provider - allows type specific thumbnail creation
|
||||
var contentProvider = ApplicationController.Instance.Library.GetContentProvider(itemModel);
|
||||
if (contentProvider != null
|
||||
&& contentProvider is MeshContentProvider)
|
||||
{
|
||||
// Before we have a thumbnail set to the content specific thumbnail
|
||||
thumbnail = contentProvider.DefaultImage.AlphaToPrimaryAccent();
|
||||
|
||||
ApplicationController.Instance.QueueForGeneration(async () =>
|
||||
{
|
||||
// TODO: What we really want here is to determine if the control is being drawn because it's in the visible region of its parent
|
||||
if (this.Visible)
|
||||
{
|
||||
|
||||
SetItemThumbnail(generatingThumbnailIcon.AlphaToPrimaryAccent());
|
||||
|
||||
// Then try to load a content specific thumbnail
|
||||
await contentProvider.GetThumbnail(
|
||||
itemModel,
|
||||
thumbWidth,
|
||||
thumbHeight,
|
||||
(image) =>
|
||||
{
|
||||
// Use the content providers default image if an image failed to load
|
||||
SetItemThumbnail(image ?? contentProvider.DefaultImage, true);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (contentProvider != null)
|
||||
{
|
||||
// Then try to load a content specific thumbnail
|
||||
await contentProvider.GetThumbnail(
|
||||
itemModel,
|
||||
thumbWidth,
|
||||
thumbHeight,
|
||||
(image) => thumbnail = image);
|
||||
}
|
||||
}
|
||||
|
||||
if (thumbnail == null)
|
||||
{
|
||||
// Use the listview defaults
|
||||
thumbnail = ((itemModel is ILibraryContainerLink) ? defaultFolderIcon : defaultItemIcon).AlphaToPrimaryAccent();
|
||||
}
|
||||
|
||||
SetItemThumbnail(thumbnail);
|
||||
}
|
||||
|
||||
protected void SetItemThumbnail(ImageBuffer thumbnail, bool colorize = false)
|
||||
{
|
||||
if (thumbnail != null)
|
||||
{
|
||||
// Resize canvas to target as fallback
|
||||
if (thumbnail.Width < thumbWidth || thumbnail.Height < thumbHeight)
|
||||
{
|
||||
thumbnail = listViewItem.ListView.ResizeCanvas(thumbnail, thumbWidth, thumbHeight);
|
||||
}
|
||||
else if (thumbnail.Width > thumbWidth || thumbnail.Height > thumbHeight)
|
||||
{
|
||||
thumbnail = LibraryProviderHelpers.ResizeImage(thumbnail, thumbWidth, thumbHeight);
|
||||
}
|
||||
|
||||
// TODO: Resolve and implement
|
||||
// Allow the container to draw an overlay - use signal interface or add method to interface?
|
||||
//var iconWithOverlay = ActiveContainer.DrawOverlay()
|
||||
|
||||
this.imageWidget.Image = thumbnail;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDraw(Graphics2D graphics2D)
|
||||
{
|
||||
base.OnDraw(graphics2D);
|
||||
|
||||
var widgetBorder = new RoundedRect(LocalBounds, 0);
|
||||
|
||||
// Draw the hover border if the mouse is in bounds or if its the ActivePrint item
|
||||
if (mouseInBounds || (this.IsActivePrint && !this.EditMode))
|
||||
{
|
||||
//Draw interior border
|
||||
graphics2D.Render(new Stroke(widgetBorder, 3), ActiveTheme.Instance.SecondaryAccentColor);
|
||||
}
|
||||
|
||||
if (this.IsHoverItem)
|
||||
{
|
||||
RectangleDouble Bounds = LocalBounds;
|
||||
RoundedRect rectBorder = new RoundedRect(Bounds, 0);
|
||||
|
||||
this.BackgroundColor = RGBA_Bytes.White;
|
||||
|
||||
graphics2D.Render(new Stroke(rectBorder, 3), ActiveTheme.Instance.SecondaryAccentColor);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnMouseDown(MouseEventArgs mouseEvent)
|
||||
{
|
||||
mouseDownInBounds = true;
|
||||
mouseDownAt = mouseEvent.Position;
|
||||
|
||||
if (IsDoubleClick(mouseEvent))
|
||||
{
|
||||
listViewItem.OnDoubleClick();
|
||||
}
|
||||
|
||||
// On mouse down update the view3DWidget reference that will be used in MouseMove and MouseUp
|
||||
view3DWidget = MatterControlApplication.Instance.ActiveView3DWidget;
|
||||
|
||||
base.OnMouseDown(mouseEvent);
|
||||
}
|
||||
|
||||
public override void OnMouseMove(MouseEventArgs mouseEvent)
|
||||
{
|
||||
var delta = mouseDownAt - mouseEvent.Position;
|
||||
|
||||
bool dragActive = mouseDownInBounds && delta.Length > 40;
|
||||
// If dragging and the drag threshold has been hit, start a drag operation but loading the drag items
|
||||
if (dragActive
|
||||
&& (listViewItem.Model is ILibraryContentStream || listViewItem.Model is ILibraryContentItem))
|
||||
{
|
||||
if (view3DWidget != null && view3DWidget.DragDropSource == null)
|
||||
{
|
||||
if (listViewItem.Model is ILibraryContentStream)
|
||||
{
|
||||
// Use provider to acquire Object3D
|
||||
var contentModel = listViewItem.Model as ILibraryContentStream;
|
||||
|
||||
// Update the ListView pointer for the dragging item
|
||||
listViewItem.ListView.DragSourceRowItem = listViewItem;
|
||||
|
||||
var contentResult = contentModel.CreateContent();
|
||||
if (contentResult != null)
|
||||
{
|
||||
// Assign a new drag source
|
||||
view3DWidget.DragDropSource = contentResult.Object3D;
|
||||
}
|
||||
}
|
||||
else if (listViewItem.Model is ILibraryContentItem)
|
||||
{
|
||||
(listViewItem.Model as ILibraryContentItem).GetContent(null).ContinueWith((task) =>
|
||||
{
|
||||
view3DWidget.DragDropSource = task.Result;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Performs move in View3DWidget and indicates if add occurred
|
||||
var screenSpaceMousePosition = this.TransformToScreenSpace(mouseEvent.Position);
|
||||
view3DWidget.AltDragOver(screenSpaceMousePosition);
|
||||
}
|
||||
|
||||
base.OnMouseMove(mouseEvent);
|
||||
}
|
||||
|
||||
public override void OnMouseUp(MouseEventArgs mouseEvent)
|
||||
{
|
||||
if (view3DWidget?.DragDropSource != null && view3DWidget.Scene.Children.Contains(view3DWidget.DragDropSource))
|
||||
{
|
||||
// Mouse and widget positions
|
||||
var screenSpaceMousePosition = this.TransformToScreenSpace(mouseEvent.Position);
|
||||
var meshViewerPosition = this.view3DWidget.meshViewerWidget.TransformToScreenSpace(view3DWidget.meshViewerWidget.LocalBounds);
|
||||
|
||||
// If the mouse is not within the meshViewer, remove the inserted drag item
|
||||
if (!meshViewerPosition.Contains(screenSpaceMousePosition))
|
||||
{
|
||||
view3DWidget.Scene.ModifyChildren(children => children.Remove(view3DWidget.DragDropSource));
|
||||
view3DWidget.Scene.ClearSelection();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create and push the undo operation
|
||||
view3DWidget.AddUndoOperation(
|
||||
new InsertCommand(view3DWidget, view3DWidget.DragDropSource));
|
||||
}
|
||||
|
||||
view3DWidget.FinishDrop();
|
||||
}
|
||||
|
||||
mouseDownInBounds = false;
|
||||
base.OnMouseUp(mouseEvent);
|
||||
}
|
||||
|
||||
public override void OnMouseEnterBounds(MouseEventArgs mouseEvent)
|
||||
{
|
||||
base.OnMouseEnterBounds(mouseEvent);
|
||||
mouseInBounds = true;
|
||||
UpdateHoverState();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
public override void OnMouseLeaveBounds(MouseEventArgs mouseEvent)
|
||||
{
|
||||
mouseInBounds = false;
|
||||
base.OnMouseLeaveBounds(mouseEvent);
|
||||
UpdateHoverState();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
protected virtual void UpdateColors()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual async void UpdateHoverState()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual bool IsHoverItem { get; set; }
|
||||
public virtual bool EditMode { get; set; }
|
||||
|
||||
private bool isActivePrint = false;
|
||||
public bool IsActivePrint
|
||||
{
|
||||
get
|
||||
{
|
||||
return isActivePrint;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (isActivePrint != value)
|
||||
{
|
||||
isActivePrint = value;
|
||||
UpdateColors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool isSelected = false;
|
||||
|
||||
public bool IsSelected
|
||||
{
|
||||
get
|
||||
{
|
||||
return isSelected;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (isSelected != value)
|
||||
{
|
||||
//selectionCheckBox.Checked = value;
|
||||
|
||||
isSelected = value;
|
||||
UpdateColors();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
62
Library/Widgets/ListView/PrintItemAction.cs
Normal file
62
Library/Widgets/ListView/PrintItemAction.cs
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
Copyright (c) 2017, 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 MatterHackers.Agg.UI;
|
||||
using MatterHackers.MatterControl.CustomWidgets;
|
||||
using MatterHackers.MatterControl.Library;
|
||||
|
||||
namespace MatterHackers.MatterControl.PrintQueue
|
||||
{
|
||||
public class PrintItemAction
|
||||
{
|
||||
public string Title { get; set; }
|
||||
|
||||
public Action<IEnumerable<ILibraryItem>, ListView> Action { get; set; }
|
||||
|
||||
public bool AllowMultiple { get; set; } = false;
|
||||
public bool AllowProtected { get; set; } = false;
|
||||
public bool AllowContainers { get; set; } = false;
|
||||
public bool AlwaysEnabled { get; set; } = false;
|
||||
internal MenuItem MenuItem { get; set; }
|
||||
}
|
||||
|
||||
public class MenuSeparator : PrintItemAction
|
||||
{
|
||||
public MenuSeparator(string section)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class PrintItemMenuExtension
|
||||
{
|
||||
public abstract IEnumerable<PrintItemAction> GetMenuItems();
|
||||
}
|
||||
}
|
||||
425
Library/Widgets/ListView/RowListView.cs
Normal file
425
Library/Widgets/ListView/RowListView.cs
Normal file
|
|
@ -0,0 +1,425 @@
|
|||
/*
|
||||
Copyright (c) 2017, 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.Threading.Tasks;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Image;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.Localizations;
|
||||
using MatterHackers.MatterControl.Library;
|
||||
using MatterHackers.VectorMath;
|
||||
|
||||
namespace MatterHackers.MatterControl.CustomWidgets
|
||||
{
|
||||
public class RowListView : FlowLayoutWidget, IListContentView
|
||||
{
|
||||
public int ThumbWidth { get; } = 50;
|
||||
public int ThumbHeight { get; } = 50;
|
||||
|
||||
public RowListView()
|
||||
: base(FlowDirection.TopToBottom)
|
||||
{
|
||||
}
|
||||
|
||||
public void AddItem(ListViewItem item)
|
||||
{
|
||||
var detailsView = new RowViewItem(item, this.ThumbWidth, this.ThumbHeight);
|
||||
this.AddChild(detailsView);
|
||||
|
||||
item.ViewWidget = detailsView;
|
||||
}
|
||||
|
||||
public void ClearItems()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class RowViewItem : ListViewItemBase
|
||||
{
|
||||
private CheckBox selectionCheckBox;
|
||||
|
||||
private SlideWidget actionButtonContainer;
|
||||
|
||||
private ConditionalClickWidget conditionalClickContainer;
|
||||
|
||||
private TextWidget partLabel;
|
||||
|
||||
private GuiWidget middleColumn;
|
||||
|
||||
//private TextWidget partStatus;
|
||||
|
||||
private GuiWidget selectionCheckBoxContainer;
|
||||
|
||||
private FatFlatClickWidget viewButton;
|
||||
|
||||
private TextWidget viewButtonLabel;
|
||||
|
||||
private event EventHandler unregisterEvents;
|
||||
|
||||
public RowViewItem(ListViewItem listViewItem, int thumbWidth, int thumbHeight)
|
||||
: base(listViewItem, thumbWidth, thumbHeight)
|
||||
{
|
||||
// Set Display Attributes
|
||||
this.VAnchor = VAnchor.FitToChildren;
|
||||
this.HAnchor = HAnchor.ParentLeftRight | HAnchor.FitToChildren;
|
||||
this.Height = 50;
|
||||
this.BackgroundColor = RGBA_Bytes.White;
|
||||
this.Padding = new BorderDouble(0);
|
||||
this.Margin = new BorderDouble(6, 0, 6, 6);
|
||||
|
||||
var topToBottomLayout = new FlowLayoutWidget(FlowDirection.TopToBottom) { HAnchor = HAnchor.ParentLeftRight };
|
||||
|
||||
var topContentsFlowLayout = new FlowLayoutWidget(FlowDirection.LeftToRight) { HAnchor = HAnchor.ParentLeftRight };
|
||||
{
|
||||
selectionCheckBoxContainer = new GuiWidget()
|
||||
{
|
||||
VAnchor = VAnchor.ParentBottomTop,
|
||||
Width = 40,
|
||||
Visible = false,
|
||||
Margin = new BorderDouble(left: 6)
|
||||
};
|
||||
|
||||
selectionCheckBox = new CheckBox("")
|
||||
{
|
||||
Name = "List Item Checkbox",
|
||||
VAnchor = VAnchor.ParentCenter,
|
||||
HAnchor = HAnchor.ParentCenter
|
||||
};
|
||||
selectionCheckBoxContainer.AddChild(selectionCheckBox);
|
||||
|
||||
var leftColumn = new FlowLayoutWidget(FlowDirection.LeftToRight)
|
||||
{
|
||||
VAnchor = VAnchor.ParentTop | VAnchor.FitToChildren
|
||||
};
|
||||
topContentsFlowLayout.AddChild(leftColumn);
|
||||
|
||||
// TODO: add in default thumbnail handling from parent or IListItem
|
||||
imageWidget = new ImageWidget(thumbWidth, thumbHeight)
|
||||
{
|
||||
Name = "List Item Thumbnail",
|
||||
BackgroundColor = ActiveTheme.Instance.PrimaryAccentColor
|
||||
};
|
||||
leftColumn.AddChild(imageWidget);
|
||||
|
||||
// TODO: Move to caller
|
||||
// TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
|
||||
// textInfo.ToTitleCase(PrintItemWrapper.Name).Replace('_', ' ')
|
||||
|
||||
partLabel = new TextWidget(listViewItem.Model.Name, pointSize: 14)
|
||||
{
|
||||
TextColor = RGBA_Bytes.Black,
|
||||
MinimumSize = new Vector2(1, 18),
|
||||
VAnchor = VAnchor.ParentCenter
|
||||
};
|
||||
|
||||
/*
|
||||
partStatus = new TextWidget("{0}: {1}".FormatWith("Status".Localize().ToUpper(), "Queued to Print".Localize()), pointSize: 10)
|
||||
{
|
||||
AutoExpandBoundsToText = true,
|
||||
TextColor = RGBA_Bytes.Black,
|
||||
MinimumSize = new Vector2(50, 12)
|
||||
middleColumn.AddChild(partStatus);
|
||||
|
||||
}; */
|
||||
|
||||
middleColumn = new GuiWidget(0.0, 0.0)
|
||||
{
|
||||
VAnchor = VAnchor.ParentBottomTop,
|
||||
HAnchor = HAnchor.ParentLeftRight,
|
||||
Padding = 0,
|
||||
Margin = new BorderDouble(10, 3)
|
||||
};
|
||||
|
||||
listViewItem.ProgressTarget = middleColumn;
|
||||
|
||||
bool mouseDownOnMiddle = false;
|
||||
middleColumn.MouseDown += (sender, e) =>
|
||||
{
|
||||
// TODO: Need custom model type for non-content items
|
||||
// Abort normal processing for view helpers
|
||||
/* if (this.IsViewHelperItem)
|
||||
{
|
||||
return;
|
||||
}*/
|
||||
mouseDownOnMiddle = true;
|
||||
};
|
||||
|
||||
middleColumn.MouseUp += (sender, e) =>
|
||||
{
|
||||
if (mouseDownOnMiddle
|
||||
&& listViewItem.Model is ILibraryContentItem
|
||||
&& middleColumn.LocalBounds.Contains(e.Position))
|
||||
{
|
||||
// TODO: Resolve missing .EditMode condition
|
||||
if (false /*this.libraryDataView.EditMode*/)
|
||||
{
|
||||
if (this.IsSelected)
|
||||
{
|
||||
listViewItem.ListView.SelectedItems.Remove(listViewItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
listViewItem.ListView.SelectedItems.Remove(listViewItem);
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!this.IsSelected)
|
||||
{
|
||||
if (!Keyboard.IsKeyDown(Keys.ControlKey))
|
||||
{
|
||||
listViewItem.ListView.SelectedItems.Clear();
|
||||
}
|
||||
|
||||
listViewItem.ListView.SelectedItems.Add(listViewItem);
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mouseDownOnMiddle = false;
|
||||
};
|
||||
|
||||
middleColumn.AddChild(partLabel);
|
||||
|
||||
topContentsFlowLayout.AddChild(middleColumn);
|
||||
}
|
||||
|
||||
// The ConditionalClickWidget supplies a user driven Enabled property based on a delegate of your choosing
|
||||
conditionalClickContainer = new ConditionalClickWidget(() => this.EditMode)
|
||||
{
|
||||
HAnchor = HAnchor.ParentLeftRight,
|
||||
VAnchor = VAnchor.ParentBottomTop
|
||||
};
|
||||
conditionalClickContainer.Click += onQueueItemClick;
|
||||
|
||||
topToBottomLayout.AddChild(topContentsFlowLayout);
|
||||
this.AddChild(topToBottomLayout);
|
||||
|
||||
actionButtonContainer = getItemActionButtons();
|
||||
actionButtonContainer.Visible = false;
|
||||
this.AddChild(conditionalClickContainer);
|
||||
|
||||
this.AddChild(actionButtonContainer);
|
||||
}
|
||||
|
||||
public override async void OnLoad(EventArgs args)
|
||||
{
|
||||
base.OnLoad(args);
|
||||
await this.LoadItemThumbnail();
|
||||
}
|
||||
|
||||
private bool isHoverItem = false;
|
||||
public override bool IsHoverItem
|
||||
{
|
||||
get { return isHoverItem; }
|
||||
set
|
||||
{
|
||||
if (this.isHoverItem != value)
|
||||
{
|
||||
this.isHoverItem = value;
|
||||
if (value && !this.EditMode)
|
||||
{
|
||||
this.actionButtonContainer.SlideIn();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.actionButtonContainer.SlideOut();
|
||||
}
|
||||
|
||||
UpdateColors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnClosed(ClosedEventArgs e)
|
||||
{
|
||||
unregisterEvents?.Invoke(this, null);
|
||||
base.OnClosed(e);
|
||||
}
|
||||
|
||||
protected override void UpdateColors()
|
||||
{
|
||||
base.UpdateColors();
|
||||
|
||||
if (this.IsActivePrint && !this.EditMode)
|
||||
{
|
||||
this.BackgroundColor = ActiveTheme.Instance.SecondaryAccentColor;
|
||||
this.partLabel.TextColor = RGBA_Bytes.White;
|
||||
//this.partStatus.TextColor = RGBA_Bytes.White;
|
||||
this.viewButton.BackgroundColor = RGBA_Bytes.White;
|
||||
this.viewButtonLabel.TextColor = ActiveTheme.Instance.SecondaryAccentColor;
|
||||
}
|
||||
else if (this.IsSelected)
|
||||
{
|
||||
this.BackgroundColor = ActiveTheme.Instance.PrimaryAccentColor;
|
||||
this.partLabel.TextColor = RGBA_Bytes.White;
|
||||
//this.partStatus.TextColor = RGBA_Bytes.White;
|
||||
this.selectionCheckBox.TextColor = RGBA_Bytes.White;
|
||||
this.viewButton.BackgroundColor = RGBA_Bytes.White;
|
||||
this.viewButtonLabel.TextColor = ActiveTheme.Instance.SecondaryAccentColor;
|
||||
}
|
||||
else if (this.IsHoverItem)
|
||||
{
|
||||
this.BackgroundColor = RGBA_Bytes.White;
|
||||
this.partLabel.TextColor = RGBA_Bytes.Black;
|
||||
this.selectionCheckBox.TextColor = RGBA_Bytes.Black;
|
||||
//this.partStatus.TextColor = RGBA_Bytes.Black;
|
||||
this.viewButton.BackgroundColor = ActiveTheme.Instance.SecondaryAccentColor;
|
||||
this.viewButtonLabel.TextColor = RGBA_Bytes.White;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.BackgroundColor = new RGBA_Bytes(255, 255, 255, 255);
|
||||
this.partLabel.TextColor = RGBA_Bytes.Black;
|
||||
this.selectionCheckBox.TextColor = RGBA_Bytes.Black;
|
||||
//this.partStatus.TextColor = RGBA_Bytes.Black;
|
||||
this.viewButton.BackgroundColor = ActiveTheme.Instance.SecondaryAccentColor;
|
||||
this.viewButtonLabel.TextColor = RGBA_Bytes.White;
|
||||
}
|
||||
}
|
||||
|
||||
private SlideWidget getItemActionButtons()
|
||||
{
|
||||
var removeLabel = new TextWidget("Remove".Localize())
|
||||
{
|
||||
Name = "Queue Item " + listViewItem.Model.Name + " Remove",
|
||||
TextColor = RGBA_Bytes.White,
|
||||
VAnchor = VAnchor.ParentCenter,
|
||||
HAnchor = HAnchor.ParentCenter
|
||||
};
|
||||
|
||||
var removeButton = new FatFlatClickWidget(removeLabel)
|
||||
{
|
||||
VAnchor = VAnchor.ParentBottomTop,
|
||||
BackgroundColor = ActiveTheme.Instance.PrimaryAccentColor,
|
||||
Width = 100
|
||||
};
|
||||
removeButton.Click += onRemovePartClick;
|
||||
|
||||
viewButtonLabel = new TextWidget("View".Localize())
|
||||
{
|
||||
Name = "Queue Item " + listViewItem.Model.Name + " View",
|
||||
TextColor = RGBA_Bytes.White,
|
||||
VAnchor = VAnchor.ParentCenter,
|
||||
HAnchor = HAnchor.ParentCenter,
|
||||
};
|
||||
|
||||
viewButton = new FatFlatClickWidget(viewButtonLabel)
|
||||
{
|
||||
VAnchor = VAnchor.ParentBottomTop,
|
||||
BackgroundColor = ActiveTheme.Instance.SecondaryAccentColor,
|
||||
Width = 100,
|
||||
};
|
||||
viewButton.Click += onViewPartClick;
|
||||
|
||||
var buttonFlowContainer = new FlowLayoutWidget(FlowDirection.LeftToRight)
|
||||
{
|
||||
VAnchor = VAnchor.ParentBottomTop
|
||||
};
|
||||
buttonFlowContainer.AddChild(viewButton);
|
||||
buttonFlowContainer.AddChild(removeButton);
|
||||
|
||||
var buttonContainer = new SlideWidget()
|
||||
{
|
||||
VAnchor = VAnchor.ParentBottomTop,
|
||||
HAnchor = HAnchor.ParentRight
|
||||
};
|
||||
buttonContainer.AddChild(buttonFlowContainer);
|
||||
buttonContainer.Width = 200;
|
||||
|
||||
return buttonContainer;
|
||||
}
|
||||
|
||||
protected override async void UpdateHoverState()
|
||||
{
|
||||
if (!mouseInBounds)
|
||||
{
|
||||
IsHoverItem = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Hover only occurs after mouse is in bounds for a given period of time
|
||||
await Task.Delay(500);
|
||||
|
||||
if (!mouseInBounds)
|
||||
{
|
||||
IsHoverItem = false;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (UnderMouseState)
|
||||
{
|
||||
case UnderMouseState.NotUnderMouse:
|
||||
IsHoverItem = false;
|
||||
break;
|
||||
|
||||
case UnderMouseState.FirstUnderMouse:
|
||||
IsHoverItem = true;
|
||||
break;
|
||||
|
||||
case UnderMouseState.UnderMouseNotFirst:
|
||||
IsHoverItem = ContainsFirstUnderMouseRecursive();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void onQueueItemClick(object sender, EventArgs e)
|
||||
{
|
||||
if (this.IsSelected)
|
||||
{
|
||||
this.IsSelected = false;
|
||||
this.selectionCheckBox.Checked = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.IsSelected = true;
|
||||
this.selectionCheckBox.Checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void onRemovePartClick(object sender, EventArgs e)
|
||||
{
|
||||
this.actionButtonContainer.SlideOut();
|
||||
//UiThread.RunOnIdle(DeletePartFromQueue);
|
||||
}
|
||||
|
||||
private void onViewPartClick(object sender, EventArgs e)
|
||||
{
|
||||
this.actionButtonContainer.SlideOut();
|
||||
//UiThread.RunOnIdle(() =>
|
||||
//{
|
||||
// OpenPartViewWindow(View3DWidget.OpenMode.Viewing);
|
||||
//});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
914
Library/Widgets/PrintLibraryWidget.cs
Normal file
914
Library/Widgets/PrintLibraryWidget.cs
Normal file
|
|
@ -0,0 +1,914 @@
|
|||
/*
|
||||
Copyright (c) 2017, Kevin Pope, 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.IO;
|
||||
using System.Linq;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.PlatformAbstract;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.Localizations;
|
||||
using MatterHackers.MatterControl.CustomWidgets;
|
||||
using MatterHackers.MatterControl.Library;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using MatterHackers.MatterControl.PrintQueue;
|
||||
using MatterHackers.MatterControl.SettingsManagement;
|
||||
using MatterHackers.MatterControl.SlicerConfiguration;
|
||||
using MatterHackers.PolygonMesh;
|
||||
using MatterHackers.VectorMath;
|
||||
|
||||
namespace MatterHackers.MatterControl.PrintLibrary
|
||||
{
|
||||
public class PrintLibraryWidget : GuiWidget
|
||||
{
|
||||
private static CreateFolderWindow createFolderWindow = null;
|
||||
private static RenameItemWindow renameItemWindow = null;
|
||||
private ExportToFolderFeedbackWindow exportingWindow = null;
|
||||
private TextImageButtonFactory textImageButtonFactory;
|
||||
private TextImageButtonFactory editButtonFactory;
|
||||
|
||||
private FolderBreadCrumbWidget breadCrumbWidget;
|
||||
|
||||
private Button addToLibraryButton;
|
||||
private Button createFolderButton;
|
||||
private Button enterEditModeButton;
|
||||
private FlowLayoutWidget buttonPanel;
|
||||
private MHTextEditWidget searchInput;
|
||||
private ListView libraryView;
|
||||
private GuiWidget providerMessageContainer;
|
||||
private TextWidget providerMessageWidget;
|
||||
|
||||
private DropDownMenu actionMenu;
|
||||
private List<PrintItemAction> menuActions = new List<PrintItemAction>();
|
||||
|
||||
public PrintLibraryWidget()
|
||||
{
|
||||
this.Padding = new BorderDouble(3);
|
||||
this.BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;
|
||||
this.AnchorAll();
|
||||
|
||||
textImageButtonFactory = new TextImageButtonFactory()
|
||||
{
|
||||
borderWidth = 0,
|
||||
normalTextColor = ActiveTheme.Instance.PrimaryTextColor,
|
||||
hoverTextColor = ActiveTheme.Instance.PrimaryTextColor,
|
||||
pressedTextColor = ActiveTheme.Instance.PrimaryTextColor,
|
||||
disabledTextColor = ActiveTheme.Instance.TabLabelUnselected,
|
||||
disabledFillColor = new RGBA_Bytes()
|
||||
};
|
||||
|
||||
editButtonFactory = new TextImageButtonFactory()
|
||||
{
|
||||
normalTextColor = ActiveTheme.Instance.PrimaryTextColor,
|
||||
hoverTextColor = ActiveTheme.Instance.PrimaryTextColor,
|
||||
disabledTextColor = ActiveTheme.Instance.TabLabelUnselected,
|
||||
disabledFillColor = new RGBA_Bytes(),
|
||||
pressedTextColor = ActiveTheme.Instance.PrimaryTextColor,
|
||||
borderWidth = 0,
|
||||
Margin = new BorderDouble(10, 0)
|
||||
};
|
||||
|
||||
var allControls = new FlowLayoutWidget(FlowDirection.TopToBottom);
|
||||
|
||||
// Create search panel
|
||||
{
|
||||
var searchPanel = new FlowLayoutWidget()
|
||||
{
|
||||
BackgroundColor = ActiveTheme.Instance.TransparentDarkOverlay,
|
||||
HAnchor = HAnchor.ParentLeftRight,
|
||||
Padding = new BorderDouble(0)
|
||||
};
|
||||
|
||||
enterEditModeButton = editButtonFactory.Generate("Edit".Localize(), centerText: true);
|
||||
enterEditModeButton.Name = "Library Edit Button";
|
||||
searchPanel.AddChild(enterEditModeButton);
|
||||
|
||||
searchInput = new MHTextEditWidget(messageWhenEmptyAndNotSelected: "Search Library".Localize())
|
||||
{
|
||||
Name = "Search Library Edit",
|
||||
Margin = new BorderDouble(0, 3, 0, 0),
|
||||
HAnchor = HAnchor.ParentLeftRight,
|
||||
VAnchor = VAnchor.ParentCenter
|
||||
};
|
||||
searchInput.ActualTextEditWidget.EnterPressed += (s, e) => PerformSearch();
|
||||
searchPanel.AddChild(searchInput);
|
||||
|
||||
// TODO: We should describe the intent of setting to zero and immediately restoring to the original value. Not clear, looks pointless
|
||||
double oldWidth = editButtonFactory.FixedWidth;
|
||||
editButtonFactory.FixedWidth = 0;
|
||||
|
||||
Button searchButton = editButtonFactory.Generate("Search".Localize(), centerText: true);
|
||||
searchButton.Name = "Search Library Button";
|
||||
searchButton.Click += (s, e) => PerformSearch();
|
||||
editButtonFactory.FixedWidth = oldWidth;
|
||||
searchPanel.AddChild(searchButton);
|
||||
|
||||
allControls.AddChild(searchPanel);
|
||||
}
|
||||
|
||||
libraryView = new ListView(ApplicationController.Instance.Library);
|
||||
libraryView.SelectedItems.CollectionChanged += SelectedItems_CollectionChanged;
|
||||
|
||||
ApplicationController.Instance.Library.ContainerChanged += Library_ContainerChanged;
|
||||
|
||||
breadCrumbWidget = new FolderBreadCrumbWidget(libraryView);
|
||||
var breadCrumbSpaceHolder = new FlowLayoutWidget()
|
||||
{
|
||||
HAnchor = HAnchor.ParentLeftRight,
|
||||
};
|
||||
breadCrumbSpaceHolder.AddChild(breadCrumbWidget);
|
||||
|
||||
var breadCrumbAndActionBar = new FlowLayoutWidget()
|
||||
{
|
||||
HAnchor = HAnchor.ParentLeftRight,
|
||||
};
|
||||
breadCrumbAndActionBar.AddChild(breadCrumbSpaceHolder);
|
||||
|
||||
actionMenu = new DropDownMenu("Actions".Localize() + "... ")
|
||||
{
|
||||
AlignToRightEdge = true,
|
||||
NormalColor = new RGBA_Bytes(),
|
||||
BorderWidth = 1,
|
||||
BorderColor = new RGBA_Bytes(ActiveTheme.Instance.SecondaryTextColor, 100),
|
||||
MenuAsWideAsItems = false,
|
||||
VAnchor = VAnchor.ParentBottomTop,
|
||||
Margin = new BorderDouble(3),
|
||||
Padding = new BorderDouble(10),
|
||||
Name = "LibraryActionMenu"
|
||||
};
|
||||
|
||||
breadCrumbAndActionBar.AddChild(actionMenu);
|
||||
|
||||
allControls.AddChild(breadCrumbAndActionBar);
|
||||
|
||||
allControls.AddChild(libraryView);
|
||||
|
||||
buttonPanel = new FlowLayoutWidget()
|
||||
{
|
||||
HAnchor = HAnchor.ParentLeftRight,
|
||||
Padding = new BorderDouble(0, 3),
|
||||
MinimumSize = new Vector2(0, 46)
|
||||
};
|
||||
AddLibraryButtonElements();
|
||||
allControls.AddChild(buttonPanel);
|
||||
|
||||
allControls.AnchorAll();
|
||||
|
||||
this.AddChild(allControls);
|
||||
}
|
||||
|
||||
private void SelectedItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Reset)
|
||||
{
|
||||
foreach (var item in libraryView.Items)
|
||||
{
|
||||
item.ViewWidget.IsSelected = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (e.OldItems != null)
|
||||
{
|
||||
foreach (var item in e.OldItems.OfType<ListViewItem>())
|
||||
{
|
||||
item.ViewWidget.IsSelected = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (e.NewItems != null)
|
||||
{
|
||||
foreach (var item in e.NewItems.OfType<ListViewItem>())
|
||||
{
|
||||
item.ViewWidget.IsSelected = true;
|
||||
}
|
||||
}
|
||||
|
||||
EnableMenus();
|
||||
}
|
||||
|
||||
private void Library_ContainerChanged(object sender, ContainerChangedEventArgs e)
|
||||
{
|
||||
// Release
|
||||
if (e.PreviousContainer != null)
|
||||
{
|
||||
e.PreviousContainer.Reloaded -= UpdateStatus;
|
||||
}
|
||||
|
||||
var activeContainer = this.libraryView.ActiveContainer;
|
||||
|
||||
|
||||
var writableContainer = activeContainer as ILibraryWritableContainer;
|
||||
|
||||
bool containerSupportsEdits = activeContainer is ILibraryWritableContainer;
|
||||
|
||||
addToLibraryButton.Enabled = containerSupportsEdits;
|
||||
createFolderButton.Enabled = containerSupportsEdits && writableContainer?.AllowAction(ContainerActions.AddContainers) == true;
|
||||
|
||||
searchInput.Text = activeContainer.KeywordFilter;
|
||||
breadCrumbWidget.SetBreadCrumbs(activeContainer);
|
||||
|
||||
activeContainer.Reloaded += UpdateStatus;
|
||||
|
||||
UpdateStatus(null, null);
|
||||
}
|
||||
|
||||
private void UpdateStatus(object sender, EventArgs e)
|
||||
{
|
||||
string message = this.libraryView.ActiveContainer?.StatusMessage;
|
||||
if (!string.IsNullOrEmpty(message))
|
||||
{
|
||||
providerMessageWidget.Text = message;
|
||||
providerMessageContainer.Visible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
providerMessageContainer.Visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void AddLibraryButtonElements()
|
||||
{
|
||||
buttonPanel.RemoveAllChildren();
|
||||
|
||||
// the add button
|
||||
addToLibraryButton = textImageButtonFactory.Generate("Add".Localize(), "icon_circle_plus.png");
|
||||
addToLibraryButton.Enabled = false; // The library selector (the first library selected) is protected so we can't add to it.
|
||||
addToLibraryButton.ToolTipText = "Add an .stl, .amf, .gcode or .zip file to the Library".Localize();
|
||||
addToLibraryButton.Name = "Library Add Button";
|
||||
buttonPanel.AddChild(addToLibraryButton);
|
||||
addToLibraryButton.Margin = new BorderDouble(0, 0, 3, 0);
|
||||
addToLibraryButton.Click += (sender, e) => UiThread.RunOnIdle(() =>
|
||||
{
|
||||
FileDialog.OpenFileDialog(
|
||||
new OpenFileDialogParams(ApplicationSettings.OpenPrintableFileParams, multiSelect: true),
|
||||
(openParams) =>
|
||||
{
|
||||
if (openParams.FileNames != null)
|
||||
{
|
||||
System.Diagnostics.Debugger.Break();
|
||||
//this.libraryView.ActiveContainer.AddFiles(openParams.FileNames);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// the create folder button
|
||||
createFolderButton = textImageButtonFactory.Generate("Create Folder".Localize());
|
||||
createFolderButton.Enabled = false; // The library selector (the first library selected) is protected so we can't add to it.
|
||||
createFolderButton.Name = "Create Folder From Library Button";
|
||||
createFolderButton.Margin = new BorderDouble(0, 0, 3, 0);
|
||||
createFolderButton.Click += (sender, e) =>
|
||||
{
|
||||
if (createFolderWindow == null)
|
||||
{
|
||||
createFolderWindow = new CreateFolderWindow((returnInfo) =>
|
||||
{
|
||||
// TODO: Implement
|
||||
throw new NotImplementedException("createFolderButton click");
|
||||
//this.libraryView.ActiveContainer.AddCollectionToLibrary(returnInfo.newName);
|
||||
});
|
||||
createFolderWindow.Closed += (sender2, e2) => { createFolderWindow = null; };
|
||||
}
|
||||
else
|
||||
{
|
||||
createFolderWindow.BringToFront();
|
||||
}
|
||||
};
|
||||
buttonPanel.AddChild(createFolderButton);
|
||||
|
||||
if (OemSettings.Instance.ShowShopButton)
|
||||
{
|
||||
var shopButton = textImageButtonFactory.Generate("Buy Materials".Localize(), StaticData.Instance.LoadIcon("icon_shopping_cart_32x32.png", 32, 32));
|
||||
shopButton.ToolTipText = "Shop online for printing materials".Localize();
|
||||
shopButton.Name = "Buy Materials Button";
|
||||
shopButton.Margin = new BorderDouble(0, 0, 3, 0);
|
||||
shopButton.Click += (sender, e) =>
|
||||
{
|
||||
double activeFilamentDiameter = 0;
|
||||
if (ActiveSliceSettings.Instance.PrinterSelected)
|
||||
{
|
||||
activeFilamentDiameter = 3;
|
||||
if (ActiveSliceSettings.Instance.GetValue<double>(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));
|
||||
};
|
||||
buttonPanel.AddChild(shopButton);
|
||||
}
|
||||
|
||||
// add in the message widget
|
||||
providerMessageContainer = new GuiWidget()
|
||||
{
|
||||
VAnchor = VAnchor.FitToChildren | VAnchor.ParentTop,
|
||||
HAnchor = HAnchor.ParentLeftRight,
|
||||
Visible = false,
|
||||
};
|
||||
buttonPanel.AddChild(providerMessageContainer, -1);
|
||||
|
||||
providerMessageWidget = new TextWidget("")
|
||||
{
|
||||
PointSize = 8,
|
||||
HAnchor = HAnchor.ParentRight,
|
||||
VAnchor = VAnchor.ParentBottom,
|
||||
TextColor = ActiveTheme.Instance.SecondaryTextColor,
|
||||
Margin = new BorderDouble(6),
|
||||
AutoExpandBoundsToText = true,
|
||||
};
|
||||
providerMessageContainer.AddChild(providerMessageWidget);
|
||||
}
|
||||
|
||||
private void CreateActionMenuItems(DropDownMenu dropDownMenu)
|
||||
{
|
||||
dropDownMenu.SelectionChanged += (sender, e) =>
|
||||
{
|
||||
string menuSelection = ((DropDownMenu)sender).SelectedValue;
|
||||
foreach (var menuItem in menuActions)
|
||||
{
|
||||
if (menuItem.Title == menuSelection)
|
||||
{
|
||||
menuItem.Action?.Invoke(libraryView.SelectedItems.Select(i => i.Model), libraryView);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// edit menu item
|
||||
menuActions.Add(new PrintItemAction()
|
||||
{
|
||||
Title = "Edit".Localize(),
|
||||
AllowMultiple = false,
|
||||
AllowProtected = false,
|
||||
AllowContainers = false,
|
||||
Action = (selectedLibraryItems, listView) => System.Diagnostics.Debugger.Break() /* editButton_Click(s, null) */
|
||||
});
|
||||
|
||||
// rename menu item
|
||||
menuActions.Add(new PrintItemAction()
|
||||
{
|
||||
Title = "Rename".Localize(),
|
||||
AllowMultiple = false,
|
||||
AllowProtected = false,
|
||||
AllowContainers = true,
|
||||
Action = (selectedLibraryItems, listView) => renameFromLibraryButton_Click(selectedLibraryItems, null),
|
||||
});
|
||||
|
||||
// move menu item
|
||||
menuActions.Add(new PrintItemAction()
|
||||
{
|
||||
Title = "Move".Localize(),
|
||||
AllowMultiple = true,
|
||||
AllowProtected = false,
|
||||
AllowContainers = true,
|
||||
Action = (selectedLibraryItems, listView) => moveInLibraryButton_Click(selectedLibraryItems, null),
|
||||
});
|
||||
|
||||
// remove menu item
|
||||
menuActions.Add(new PrintItemAction()
|
||||
{
|
||||
Title = "Remove".Localize(),
|
||||
AllowMultiple = true,
|
||||
AllowProtected = false,
|
||||
AllowContainers = true,
|
||||
Action = (selectedLibraryItems, listView) => deleteFromLibraryButton_Click(selectedLibraryItems, null),
|
||||
});
|
||||
|
||||
menuActions.Add(new MenuSeparator("Classic Queue"));
|
||||
|
||||
// add to queue menu item
|
||||
menuActions.Add(new PrintItemAction()
|
||||
{
|
||||
Title = "Add to Queue".Localize(),
|
||||
AllowMultiple = true,
|
||||
AllowProtected = true,
|
||||
AllowContainers = false,
|
||||
Action = (selectedLibraryItems, listView) => addToQueueButton_Click(selectedLibraryItems, null),
|
||||
});
|
||||
|
||||
// export menu item
|
||||
menuActions.Add(new PrintItemAction()
|
||||
{
|
||||
Title = "Export".Localize(),
|
||||
AllowMultiple = false,
|
||||
AllowProtected = true,
|
||||
AllowContainers = false,
|
||||
Action = (selectedLibraryItems, listView) => exportButton_Click(selectedLibraryItems, null),
|
||||
});
|
||||
|
||||
// share menu item
|
||||
menuActions.Add(new PrintItemAction()
|
||||
{
|
||||
Title = "Share".Localize(),
|
||||
AllowMultiple = false,
|
||||
AllowProtected = false,
|
||||
AllowContainers = false,
|
||||
Action = (selectedLibraryItems, listView) => shareFromLibraryButton_Click(selectedLibraryItems, null),
|
||||
});
|
||||
|
||||
// Extension point - RegisteredLibraryActions not defined in this file/assembly can insert here via this named token
|
||||
menuActions.AddRange(ApplicationController.Instance.RegisteredLibraryActions("StandardLibraryOperations"));
|
||||
|
||||
#region Classic QueueMenu items
|
||||
#if !__ANDROID__
|
||||
menuActions.Add(new MenuSeparator("Design"));
|
||||
menuActions.Add(new PrintItemAction()
|
||||
{
|
||||
Title = "Export to Zip".Localize(),
|
||||
AllowMultiple = true,
|
||||
AllowProtected = true,
|
||||
AllowContainers = false,
|
||||
Action = (selectedLibraryItems, listView) =>
|
||||
{
|
||||
var streamItems = selectedLibraryItems.OfType<ILibraryContentStream>();
|
||||
if (streamItems.Any())
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
var project = new ProjectFileHandler(streamItems);
|
||||
project.SaveAs();
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
menuActions.Add(new MenuSeparator("G-Code"));
|
||||
menuActions.Add(new PrintItemAction()
|
||||
{
|
||||
Title = "Export to Folder or SD Card".Localize(),
|
||||
AllowMultiple = true,
|
||||
AllowProtected = false,
|
||||
AllowContainers = false,
|
||||
Action = (selectedLibraryItems, listView) =>
|
||||
{
|
||||
if (!ActiveSliceSettings.Instance.PrinterSelected)
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
// MustSelectPrinterMessage
|
||||
StyledMessageBox.ShowMessageBox(
|
||||
null,
|
||||
"Before you can export printable files, you must select a printer.".Localize(),
|
||||
"Please select a printer".Localize());
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
UiThread.RunOnIdle(SelectLocationToExportGCode);
|
||||
}
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
||||
/* TODO: Reconsider - these are actions that apply to the printer, no the selection. We could Add items from SD but how is ContainerContext -> SD -> Eject relevant?
|
||||
if (ActiveSliceSettings.Instance.GetValue<bool>(SettingsKey.has_sd_card_reader))
|
||||
{
|
||||
menuItems.Add(new Tuple<string, Func<bool>>("SD Card".Localize(), null));
|
||||
menuItems.Add(new Tuple<string, Func<bool>>(" Load Files".Localize(), () =>
|
||||
{
|
||||
QueueData.Instance.LoadFilesFromSD();
|
||||
return true;
|
||||
}));
|
||||
menuItems.Add(new Tuple<string, Func<bool>>("Eject SD Card".Localize(), () =>
|
||||
{
|
||||
// Remove all the QueueData.SdCardFileName parts from the queue
|
||||
QueueData.Instance.RemoveAllSdCardFiles();
|
||||
PrinterConnectionAndCommunication.Instance.SendLineToPrinterNow("M22"); // (Release SD card)
|
||||
return true;
|
||||
}));
|
||||
} */
|
||||
|
||||
menuActions.Add(new MenuSeparator("Other"));
|
||||
if (OsInformation.OperatingSystem == OSType.Windows)
|
||||
{
|
||||
#if !__ANDROID__
|
||||
// The pdf export library is not working on the mac at the moment so we don't include the
|
||||
// part sheet export option on mac.
|
||||
menuActions.Add(new PrintItemAction()
|
||||
{
|
||||
Title = "Create Part Sheet".Localize(),
|
||||
AllowMultiple = true,
|
||||
AllowProtected = true,
|
||||
AllowContainers = false,
|
||||
Action = (selectedLibraryItems, listView) =>
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
var printItems = selectedLibraryItems.OfType<ILibraryContentStream>();
|
||||
if (printItems.Any())
|
||||
{
|
||||
FileDialog.SaveFileDialog(
|
||||
new SaveFileDialogParams("Save Parts Sheet|*.pdf")
|
||||
{
|
||||
ActionButtonLabel = "Save Parts Sheet".Localize(),
|
||||
Title = "MatterControl".Localize() + ": " + "Save".Localize()
|
||||
},
|
||||
(saveParams) =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(saveParams.FileName))
|
||||
{
|
||||
var feedbackWindow = new SavePartsSheetFeedbackWindow(
|
||||
printItems.Count(),
|
||||
printItems.FirstOrDefault()?.Name,
|
||||
ActiveTheme.Instance.PrimaryBackgroundColor);
|
||||
|
||||
var currentPartsInQueue = new PartsSheet(printItems, saveParams.FileName);
|
||||
currentPartsInQueue.UpdateRemainingItems += feedbackWindow.StartingNextPart;
|
||||
currentPartsInQueue.DoneSaving += feedbackWindow.DoneSaving;
|
||||
|
||||
feedbackWindow.ShowAsSystemWindow();
|
||||
|
||||
currentPartsInQueue.SaveSheets();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
#endregion
|
||||
|
||||
menuActions.Add(new MenuSeparator("ListView Options"));
|
||||
menuActions.Add(new PrintItemAction()
|
||||
{
|
||||
Title = "View List".Localize(),
|
||||
AlwaysEnabled = true,
|
||||
Action = (selectedLibraryItems, listView) =>
|
||||
{
|
||||
listView.ListContentView = new RowListView();
|
||||
},
|
||||
});
|
||||
|
||||
menuActions.Add(new PrintItemAction()
|
||||
{
|
||||
Title = "View Icons".Localize(),
|
||||
AlwaysEnabled = true,
|
||||
Action = (selectedLibraryItems, listView) =>
|
||||
{
|
||||
listView.ListContentView = new IconListView();
|
||||
},
|
||||
});
|
||||
|
||||
menuActions.Add(new PrintItemAction()
|
||||
{
|
||||
Title = "View Large Icons".Localize(),
|
||||
AlwaysEnabled = true,
|
||||
Action = (selectedLibraryItems, listView) =>
|
||||
{
|
||||
listView.ListContentView = new IconListView()
|
||||
{
|
||||
ThumbWidth = 256,
|
||||
ThumbHeight = 256,
|
||||
};
|
||||
},
|
||||
});
|
||||
// Create menu items in the DropList for each element in this.menuActions
|
||||
foreach (var item in menuActions)
|
||||
{
|
||||
if (item is MenuSeparator)
|
||||
{
|
||||
item.MenuItem = dropDownMenu.AddHorizontalLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
item.MenuItem = dropDownMenu.AddItem(item.Title);
|
||||
}
|
||||
|
||||
item.MenuItem.Enabled = item.Action != null;
|
||||
}
|
||||
|
||||
EnableMenus();
|
||||
}
|
||||
|
||||
private void SelectLocationToExportGCode()
|
||||
{
|
||||
/*
|
||||
FileDialog.SelectFolderDialog(
|
||||
new SelectFolderDialogParams("Select Location To Save Files")
|
||||
{
|
||||
ActionButtonLabel = "Export".Localize(),
|
||||
Title = "MatterControl: Select A Folder"
|
||||
},
|
||||
(openParams) =>
|
||||
{
|
||||
string path = openParams.FolderPath;
|
||||
if (path != null && path != "")
|
||||
{
|
||||
List<PrintItem> parts = QueueData.Instance.CreateReadOnlyPartList(true);
|
||||
if (parts.Count > 0)
|
||||
{
|
||||
if (exportingWindow == null)
|
||||
{
|
||||
exportingWindow = new ExportToFolderFeedbackWindow(parts.Count, parts[0].Name, ActiveTheme.Instance.PrimaryBackgroundColor);
|
||||
exportingWindow.Closed += (s, e) =>
|
||||
{
|
||||
this.exportingWindow = null;
|
||||
};
|
||||
exportingWindow.ShowAsSystemWindow();
|
||||
}
|
||||
else
|
||||
{
|
||||
exportingWindow.BringToFront();
|
||||
}
|
||||
|
||||
var exportToFolderProcess = new ExportToFolderProcess(parts, path);
|
||||
exportToFolderProcess.StartingNextPart += exportingWindow.StartingNextPart;
|
||||
exportToFolderProcess.UpdatePartStatus += exportingWindow.UpdatePartStatus;
|
||||
exportToFolderProcess.DoneSaving += exportingWindow.DoneSaving;
|
||||
exportToFolderProcess.Start();
|
||||
}
|
||||
}
|
||||
}); */
|
||||
}
|
||||
|
||||
private void renameFromLibraryButton_Click(IEnumerable<ILibraryItem> items, object p)
|
||||
{
|
||||
if (libraryView.SelectedItems.Count == 1)
|
||||
{
|
||||
var selectedItem = libraryView.SelectedItems.FirstOrDefault();
|
||||
if (selectedItem == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (renameItemWindow == null)
|
||||
{
|
||||
renameItemWindow = new RenameItemWindow(
|
||||
selectedItem.Text,
|
||||
(returnInfo) =>
|
||||
{
|
||||
var model = libraryView.SelectedItems.FirstOrDefault()?.Model;
|
||||
if (model != null)
|
||||
{
|
||||
var container = libraryView.ActiveContainer as ILibraryWritableContainer;
|
||||
if (container != null)
|
||||
{
|
||||
container.Rename(model, returnInfo.newName);
|
||||
libraryView.SelectedItems.Clear();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
renameItemWindow.Closed += (s, e) => renameItemWindow = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
renameItemWindow.BringToFront();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnClosed(ClosedEventArgs e)
|
||||
{
|
||||
if (libraryView?.ActiveContainer != null)
|
||||
{
|
||||
libraryView.ActiveContainer.Reloaded -= UpdateStatus;
|
||||
ApplicationController.Instance.Library.ContainerChanged -= Library_ContainerChanged;
|
||||
}
|
||||
|
||||
base.OnClosed(e);
|
||||
}
|
||||
|
||||
private void PerformSearch()
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
libraryView.ActiveContainer.KeywordFilter = searchInput.Text.Trim();
|
||||
breadCrumbWidget.SetBreadCrumbs(libraryView.ActiveContainer);
|
||||
});
|
||||
}
|
||||
|
||||
private void addToQueueButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
foreach (var item in libraryView.SelectedItems)
|
||||
{
|
||||
throw new NotImplementedException("addToQueueButton_Click");
|
||||
|
||||
// Get content
|
||||
// Create printitemwrapper (or not) - an implementation for this exists in cloud library
|
||||
// Add printitemwrapper to queue
|
||||
}
|
||||
|
||||
libraryView.SelectedItems.Clear();
|
||||
}
|
||||
|
||||
private void EnableMenus()
|
||||
{
|
||||
foreach (var menuAction in menuActions)
|
||||
{
|
||||
var menuItem = menuAction.MenuItem;
|
||||
|
||||
if (menuAction.AlwaysEnabled)
|
||||
{
|
||||
menuItem.Enabled = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
menuItem.Enabled = menuAction.Action != null && libraryView.SelectedItems.Count > 0;
|
||||
|
||||
if (!menuAction.AllowMultiple)
|
||||
{
|
||||
menuItem.Enabled &= libraryView.SelectedItems.Count == 1;
|
||||
}
|
||||
|
||||
if (!menuAction.AllowProtected)
|
||||
{
|
||||
menuItem.Enabled &= libraryView.SelectedItems.All(i => !i.Model.IsProtected);
|
||||
}
|
||||
|
||||
if (!menuAction.AllowContainers)
|
||||
{
|
||||
menuItem.Enabled &= libraryView.SelectedItems.All(i => !(i.Model is ILibraryContainer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteFromLibraryButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
// TODO: If we don't filter to non-container content here, then the providers could be passed a container to move to some other container
|
||||
var libraryItems = libraryView.SelectedItems.Where(item => item is ILibraryContentItem);
|
||||
if (libraryItems.Any())
|
||||
{
|
||||
var container = libraryView.ActiveContainer as ILibraryWritableContainer;
|
||||
if (container != null)
|
||||
{
|
||||
container.Remove(libraryItems.Select(p => p.Model));
|
||||
}
|
||||
}
|
||||
|
||||
libraryView.SelectedItems.Clear();
|
||||
}
|
||||
|
||||
private void moveInLibraryButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
// TODO: If we don't filter to non-container content here, then the providers could be passed a container to move to some other container
|
||||
var partItems = libraryView.SelectedItems.Where(item => item is ILibraryContentItem);
|
||||
if (partItems.Count() > 0)
|
||||
{
|
||||
// If all selected items are LibraryRowItemParts, then we can invoke the batch remove functionality (in the Cloud library scenario)
|
||||
// and perform all moves as part of a single request, with a single notification from Socketeer
|
||||
|
||||
var container = libraryView.ActiveContainer as ILibraryWritableContainer;
|
||||
if (container != null)
|
||||
{
|
||||
throw new NotImplementedException("Library Move not implemented");
|
||||
// TODO: Implement move
|
||||
container.Move(partItems.Select(p => p.Model), null);
|
||||
}
|
||||
}
|
||||
|
||||
libraryView.SelectedItems.Clear();
|
||||
}
|
||||
|
||||
private void shareFromLibraryButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
// TODO: Should be rewritten to Register from cloudlibrary, include logic to add to library as needed
|
||||
System.Diagnostics.Debugger.Break();
|
||||
|
||||
if (libraryView.SelectedItems.Count == 1)
|
||||
{
|
||||
var partItem = libraryView.SelectedItems.Select(i => i.Model).FirstOrDefault();
|
||||
if (partItem != null)
|
||||
{
|
||||
//libraryView.ActiveContainer.ShareItem(partItem, "something");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void exportButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
//Open export options
|
||||
if (libraryView.SelectedItems.Count == 1)
|
||||
{
|
||||
var libraryItem = libraryView.SelectedItems.Select(i => i.Model).FirstOrDefault();
|
||||
if (libraryItem != null)
|
||||
{
|
||||
throw new NotImplementedException("Export not implemented");
|
||||
|
||||
// TODO: Implement
|
||||
//ApplicationController.OpenExportWindow(await this.GetPrintItemWrapperAsync());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public async Task<PrintItemWrapper> GetPrintItemWrapperAsync()
|
||||
{
|
||||
return await libraryProvider.GetPrintItemWrapperAsync(this.ItemIndex);
|
||||
} */
|
||||
|
||||
// TODO: We've discussed not doing popup edit in a new window. That's what this did, not worth porting yet...
|
||||
/*
|
||||
private void editButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
//Open export options
|
||||
if (libraryDataView.SelectedItems.Count == 1)
|
||||
{
|
||||
|
||||
OpenPartViewWindow(PartPreviewWindow.View3DWidget.OpenMode.Editing);
|
||||
|
||||
LibraryRowItem libraryItem = libraryDataView.SelectedItems[0];
|
||||
libraryItem.Edit();
|
||||
}
|
||||
} */
|
||||
|
||||
public override void OnMouseEnterBounds(MouseEventArgs mouseEvent)
|
||||
{
|
||||
if (mouseEvent.DragFiles?.Count > 0)
|
||||
{
|
||||
if (libraryView?.ActiveContainer?.IsProtected == false)
|
||||
{
|
||||
foreach (string file in mouseEvent.DragFiles)
|
||||
{
|
||||
string extension = Path.GetExtension(file).ToUpper();
|
||||
if ((extension != "" && MeshFileIo.ValidFileExtensions().Contains(extension))
|
||||
|| extension == ".GCODE"
|
||||
|| extension == ".ZIP")
|
||||
{
|
||||
mouseEvent.AcceptDrop = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.OnMouseEnterBounds(mouseEvent);
|
||||
}
|
||||
|
||||
public override void OnMouseMove(MouseEventArgs mouseEvent)
|
||||
{
|
||||
if (PositionWithinLocalBounds(mouseEvent.X, mouseEvent.Y)
|
||||
&& mouseEvent.DragFiles?.Count > 0)
|
||||
{
|
||||
if (libraryView != null
|
||||
&& !libraryView.ActiveContainer.IsProtected)
|
||||
{
|
||||
// TODO: Consider reusing common accept drop logic
|
||||
//mouseEvent.AcceptDrop = mouseEvent.DragFiles.TrueForAll(filePath => ApplicationController.Instance.IsLoadableFile(filePath));
|
||||
|
||||
foreach (string file in mouseEvent.DragFiles)
|
||||
{
|
||||
string extension = Path.GetExtension(file).ToUpper();
|
||||
if ((extension != "" && MeshFileIo.ValidFileExtensions().Contains(extension))
|
||||
|| extension == ".GCODE"
|
||||
|| extension == ".ZIP")
|
||||
{
|
||||
mouseEvent.AcceptDrop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.OnMouseMove(mouseEvent);
|
||||
}
|
||||
|
||||
public override void OnMouseUp(MouseEventArgs mouseEvent)
|
||||
{
|
||||
// TODO: Does this fire when .AcceptDrop is false? Looks like it should
|
||||
if (mouseEvent.DragFiles?.Count > 0
|
||||
&& libraryView?.ActiveContainer.IsProtected == false)
|
||||
{
|
||||
var container = libraryView.ActiveContainer as ILibraryWritableContainer;
|
||||
container?.Add(mouseEvent.DragFiles.Select(f => new FileSystemFileItem(f)));
|
||||
}
|
||||
|
||||
base.OnMouseUp(mouseEvent);
|
||||
}
|
||||
|
||||
public override void OnLoad(EventArgs args)
|
||||
{
|
||||
// Defer creating menu items until plugins have loaded
|
||||
CreateActionMenuItems(actionMenu);
|
||||
|
||||
base.OnLoad(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
149
Library/Widgets/SystemWindows/CreateFolderWindow.cs
Normal file
149
Library/Widgets/SystemWindows/CreateFolderWindow.cs
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.Localizations;
|
||||
using MatterHackers.MatterControl.CustomWidgets;
|
||||
using MatterHackers.MatterControl.DataStorage;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace MatterHackers.MatterControl
|
||||
{
|
||||
public class CreateFolderWindow : SystemWindow
|
||||
{
|
||||
private Action<CreateFolderReturnInfo> functionToCallToCreateNamedFolder;
|
||||
private TextImageButtonFactory textImageButtonFactory = new TextImageButtonFactory();
|
||||
private MHTextEditWidget folderNameWidget;
|
||||
|
||||
public CreateFolderWindow(Action<CreateFolderReturnInfo> functionToCallToCreateNamedFolder)
|
||||
: base(480, 180)
|
||||
{
|
||||
Title = "MatterControl - Create Folder";
|
||||
AlwaysOnTopOfMain = true;
|
||||
|
||||
this.functionToCallToCreateNamedFolder = functionToCallToCreateNamedFolder;
|
||||
|
||||
FlowLayoutWidget topToBottom = new FlowLayoutWidget(FlowDirection.TopToBottom);
|
||||
topToBottom.AnchorAll();
|
||||
topToBottom.Padding = new BorderDouble(3, 0, 3, 5);
|
||||
|
||||
// Creates Header
|
||||
FlowLayoutWidget headerRow = new FlowLayoutWidget(FlowDirection.LeftToRight);
|
||||
headerRow.HAnchor = HAnchor.ParentLeftRight;
|
||||
headerRow.Margin = new BorderDouble(0, 3, 0, 0);
|
||||
headerRow.Padding = new BorderDouble(0, 3, 0, 3);
|
||||
BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;
|
||||
|
||||
//Creates Text and adds into header
|
||||
{
|
||||
string createFolderLabel = "Create New Folder:".Localize();
|
||||
TextWidget elementHeader = new TextWidget(createFolderLabel, pointSize: 14);
|
||||
elementHeader.TextColor = ActiveTheme.Instance.PrimaryTextColor;
|
||||
elementHeader.HAnchor = HAnchor.ParentLeftRight;
|
||||
elementHeader.VAnchor = Agg.UI.VAnchor.ParentBottom;
|
||||
|
||||
headerRow.AddChild(elementHeader);
|
||||
topToBottom.AddChild(headerRow);
|
||||
this.AddChild(topToBottom);
|
||||
}
|
||||
|
||||
//Creates container in the middle of window
|
||||
FlowLayoutWidget middleRowContainer = new FlowLayoutWidget(FlowDirection.TopToBottom);
|
||||
{
|
||||
middleRowContainer.HAnchor = HAnchor.ParentLeftRight;
|
||||
middleRowContainer.VAnchor = VAnchor.ParentBottomTop;
|
||||
middleRowContainer.Padding = new BorderDouble(5);
|
||||
middleRowContainer.BackgroundColor = ActiveTheme.Instance.SecondaryBackgroundColor;
|
||||
}
|
||||
|
||||
string fileNameLabel = "Folder Name".Localize();
|
||||
TextWidget textBoxHeader = new TextWidget(fileNameLabel, pointSize: 12);
|
||||
textBoxHeader.TextColor = ActiveTheme.Instance.PrimaryTextColor;
|
||||
textBoxHeader.Margin = new BorderDouble(5);
|
||||
textBoxHeader.HAnchor = HAnchor.ParentLeft;
|
||||
|
||||
//Adds text box and check box to the above container
|
||||
folderNameWidget = new MHTextEditWidget("", pixelWidth: 300, messageWhenEmptyAndNotSelected: "Enter a Folder Name Here".Localize());
|
||||
folderNameWidget.Name = "Create Folder - Text Input";
|
||||
folderNameWidget.HAnchor = HAnchor.ParentLeftRight;
|
||||
folderNameWidget.Margin = new BorderDouble(5);
|
||||
|
||||
middleRowContainer.AddChild(textBoxHeader);
|
||||
middleRowContainer.AddChild(folderNameWidget);
|
||||
middleRowContainer.AddChild(new HorizontalSpacer());
|
||||
topToBottom.AddChild(middleRowContainer);
|
||||
|
||||
//Creates button container on the bottom of window
|
||||
FlowLayoutWidget buttonRow = new FlowLayoutWidget(FlowDirection.LeftToRight);
|
||||
{
|
||||
BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;
|
||||
buttonRow.HAnchor = HAnchor.ParentLeftRight;
|
||||
buttonRow.Padding = new BorderDouble(0, 3);
|
||||
}
|
||||
|
||||
Button createFolderButton = textImageButtonFactory.Generate("Create".Localize(), centerText: true);
|
||||
createFolderButton.Name = "Create Folder Button";
|
||||
createFolderButton.Visible = true;
|
||||
createFolderButton.Cursor = Cursors.Hand;
|
||||
buttonRow.AddChild(createFolderButton);
|
||||
|
||||
createFolderButton.Click += createFolderButton_Click;
|
||||
folderNameWidget.ActualTextEditWidget.EnterPressed += new KeyEventHandler(ActualTextEditWidget_EnterPressed);
|
||||
|
||||
//Adds Create and Close Button to button container
|
||||
buttonRow.AddChild(new HorizontalSpacer());
|
||||
|
||||
Button cancelButton = textImageButtonFactory.Generate("Cancel".Localize(), centerText: true);
|
||||
cancelButton.Visible = true;
|
||||
cancelButton.Cursor = Cursors.Hand;
|
||||
buttonRow.AddChild(cancelButton);
|
||||
cancelButton.Click += (sender, e) =>
|
||||
{
|
||||
CloseOnIdle();
|
||||
};
|
||||
|
||||
topToBottom.AddChild(buttonRow);
|
||||
|
||||
ShowAsSystemWindow();
|
||||
}
|
||||
|
||||
public override void OnLoad(EventArgs args)
|
||||
{
|
||||
UiThread.RunOnIdle(folderNameWidget.Focus);
|
||||
base.OnLoad(args);
|
||||
}
|
||||
|
||||
private void ActualTextEditWidget_EnterPressed(object sender, KeyEventArgs keyEvent)
|
||||
{
|
||||
SubmitForm();
|
||||
}
|
||||
|
||||
private void createFolderButton_Click(object sender, EventArgs mouseEvent)
|
||||
{
|
||||
SubmitForm();
|
||||
}
|
||||
|
||||
private void SubmitForm()
|
||||
{
|
||||
string newName = folderNameWidget.ActualTextEditWidget.Text;
|
||||
if (newName != "")
|
||||
{
|
||||
string fileName = Path.ChangeExtension(Path.GetRandomFileName(), ".amf");
|
||||
string fileNameAndPath = Path.Combine(ApplicationDataStorage.Instance.ApplicationLibraryDataPath, fileName);
|
||||
|
||||
CreateFolderReturnInfo returnInfo = new CreateFolderReturnInfo(newName);
|
||||
functionToCallToCreateNamedFolder(returnInfo);
|
||||
CloseOnIdle();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateFolderReturnInfo
|
||||
{
|
||||
public string newName;
|
||||
|
||||
public CreateFolderReturnInfo(string newName)
|
||||
{
|
||||
this.newName = newName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
174
Library/Widgets/SystemWindows/RenameItemWindow.cs
Normal file
174
Library/Widgets/SystemWindows/RenameItemWindow.cs
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.Localizations;
|
||||
using MatterHackers.MatterControl.CustomWidgets;
|
||||
using MatterHackers.MatterControl.DataStorage;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace MatterHackers.MatterControl
|
||||
{
|
||||
public class RenameItemWindow : SystemWindow
|
||||
{
|
||||
private Action<RenameItemReturnInfo> functionToCallToCreateNamedFolder;
|
||||
private TextImageButtonFactory textImageButtonFactory = new TextImageButtonFactory();
|
||||
private MHTextEditWidget saveAsNameWidget;
|
||||
TextWidget elementHeader;
|
||||
Button renameItemButton;
|
||||
|
||||
public string ElementHeader
|
||||
{
|
||||
get { return elementHeader.Text; }
|
||||
set { elementHeader.Text = value; }
|
||||
}
|
||||
|
||||
public class RenameItemReturnInfo
|
||||
{
|
||||
public string newName;
|
||||
|
||||
public RenameItemReturnInfo(string newName)
|
||||
{
|
||||
this.newName = newName;
|
||||
}
|
||||
}
|
||||
|
||||
public RenameItemWindow(string currentItemName, Action<RenameItemReturnInfo> functionToCallToRenameItem, string renameButtonString = null)
|
||||
: base(480, 180)
|
||||
{
|
||||
Title = "MatterControl - Rename Item";
|
||||
AlwaysOnTopOfMain = true;
|
||||
|
||||
this.functionToCallToCreateNamedFolder = functionToCallToRenameItem;
|
||||
|
||||
FlowLayoutWidget topToBottom = new FlowLayoutWidget(FlowDirection.TopToBottom);
|
||||
topToBottom.AnchorAll();
|
||||
topToBottom.Padding = new BorderDouble(3, 0, 3, 5);
|
||||
|
||||
// Creates Header
|
||||
FlowLayoutWidget headerRow = new FlowLayoutWidget(FlowDirection.LeftToRight);
|
||||
headerRow.HAnchor = HAnchor.ParentLeftRight;
|
||||
headerRow.Margin = new BorderDouble(0, 3, 0, 0);
|
||||
headerRow.Padding = new BorderDouble(0, 3, 0, 3);
|
||||
BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;
|
||||
|
||||
//Creates Text and adds into header
|
||||
{
|
||||
string renameItemLabel = "Rename Item:".Localize();
|
||||
elementHeader = new TextWidget(renameItemLabel, pointSize: 14);
|
||||
elementHeader.TextColor = ActiveTheme.Instance.PrimaryTextColor;
|
||||
elementHeader.HAnchor = HAnchor.ParentLeftRight;
|
||||
elementHeader.VAnchor = Agg.UI.VAnchor.ParentBottom;
|
||||
|
||||
headerRow.AddChild(elementHeader);
|
||||
topToBottom.AddChild(headerRow);
|
||||
this.AddChild(topToBottom);
|
||||
}
|
||||
|
||||
//Creates container in the middle of window
|
||||
FlowLayoutWidget middleRowContainer = new FlowLayoutWidget(FlowDirection.TopToBottom);
|
||||
{
|
||||
middleRowContainer.HAnchor = HAnchor.ParentLeftRight;
|
||||
middleRowContainer.VAnchor = VAnchor.ParentBottomTop;
|
||||
middleRowContainer.Padding = new BorderDouble(5);
|
||||
middleRowContainer.BackgroundColor = ActiveTheme.Instance.SecondaryBackgroundColor;
|
||||
}
|
||||
|
||||
string fileNameLabel = "New Name".Localize();
|
||||
TextWidget textBoxHeader = new TextWidget(fileNameLabel, pointSize: 12);
|
||||
textBoxHeader.TextColor = ActiveTheme.Instance.PrimaryTextColor;
|
||||
textBoxHeader.Margin = new BorderDouble(5);
|
||||
textBoxHeader.HAnchor = HAnchor.ParentLeft;
|
||||
|
||||
//Adds text box and check box to the above container
|
||||
saveAsNameWidget = new MHTextEditWidget(currentItemName, pixelWidth: 300, messageWhenEmptyAndNotSelected: "Enter New Name Here".Localize());
|
||||
saveAsNameWidget.HAnchor = HAnchor.ParentLeftRight;
|
||||
saveAsNameWidget.Margin = new BorderDouble(5);
|
||||
|
||||
middleRowContainer.AddChild(textBoxHeader);
|
||||
middleRowContainer.AddChild(saveAsNameWidget);
|
||||
middleRowContainer.AddChild(new HorizontalSpacer());
|
||||
topToBottom.AddChild(middleRowContainer);
|
||||
|
||||
//Creates button container on the bottom of window
|
||||
FlowLayoutWidget buttonRow = new FlowLayoutWidget(FlowDirection.LeftToRight);
|
||||
{
|
||||
BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;
|
||||
buttonRow.HAnchor = HAnchor.ParentLeftRight;
|
||||
buttonRow.Padding = new BorderDouble(0, 3);
|
||||
}
|
||||
|
||||
if(renameButtonString == null)
|
||||
{
|
||||
renameButtonString = "Rename".Localize();
|
||||
}
|
||||
renameItemButton = textImageButtonFactory.Generate(renameButtonString, centerText: true);
|
||||
renameItemButton.Name = "Rename Button";
|
||||
renameItemButton.Visible = true;
|
||||
renameItemButton.Cursor = Cursors.Hand;
|
||||
buttonRow.AddChild(renameItemButton);
|
||||
|
||||
renameItemButton.Click += renameItemButton_Click;
|
||||
saveAsNameWidget.ActualTextEditWidget.EnterPressed += new KeyEventHandler(ActualTextEditWidget_EnterPressed);
|
||||
|
||||
//Adds Create and Close Button to button container
|
||||
buttonRow.AddChild(new HorizontalSpacer());
|
||||
|
||||
Button cancelButton = textImageButtonFactory.Generate("Cancel".Localize(), centerText: true);
|
||||
cancelButton.Visible = true;
|
||||
cancelButton.Cursor = Cursors.Hand;
|
||||
buttonRow.AddChild(cancelButton);
|
||||
cancelButton.Click += (sender, e) =>
|
||||
{
|
||||
CloseOnIdle();
|
||||
};
|
||||
|
||||
topToBottom.AddChild(buttonRow);
|
||||
|
||||
ShowAsSystemWindow();
|
||||
}
|
||||
|
||||
public override void OnLoad(EventArgs args)
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
saveAsNameWidget.Focus();
|
||||
saveAsNameWidget.ActualTextEditWidget.InternalTextEditWidget.SelectAll();
|
||||
});
|
||||
base.OnLoad(args);
|
||||
}
|
||||
|
||||
private void ActualTextEditWidget_EnterPressed(object sender, KeyEventArgs keyEvent)
|
||||
{
|
||||
SubmitForm();
|
||||
}
|
||||
|
||||
private void renameItemButton_Click(object sender, EventArgs mouseEvent)
|
||||
{
|
||||
SubmitForm();
|
||||
}
|
||||
|
||||
private void SubmitForm()
|
||||
{
|
||||
string newName = saveAsNameWidget.ActualTextEditWidget.Text;
|
||||
if (newName != "")
|
||||
{
|
||||
string fileName = Path.ChangeExtension(Path.GetRandomFileName(), ".amf");
|
||||
string fileNameAndPath = Path.Combine(ApplicationDataStorage.Instance.ApplicationLibraryDataPath, fileName);
|
||||
|
||||
RenameItemReturnInfo returnInfo = new RenameItemReturnInfo(newName);
|
||||
functionToCallToCreateNamedFolder(returnInfo);
|
||||
CloseOnIdle();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateFolderReturnInfo
|
||||
{
|
||||
public string newName;
|
||||
|
||||
public CreateFolderReturnInfo(string newName)
|
||||
{
|
||||
this.newName = newName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue