Making the editor have local function to reduce complexity
This commit is contained in:
parent
9450bdbcf9
commit
7b65b02d92
8 changed files with 1325 additions and 1231 deletions
|
|
@ -146,7 +146,7 @@ namespace MatterHackers.MatterControl
|
|||
|
||||
public IEnumerable<PrinterConfig> ActivePrinters => this.Workspaces.Where(w => w.Printer != null).Select(w => w.Printer);
|
||||
|
||||
public ExtensionsConfig Extensions { get; }
|
||||
public EditorExtensionsConfig EditorExtensions { get; }
|
||||
|
||||
public PopupMenu GetActionMenuForSceneItem(bool addInSubmenu, View3DWidget view3DWidget)
|
||||
{
|
||||
|
|
@ -1166,9 +1166,9 @@ namespace MatterHackers.MatterControl
|
|||
// _activePrinters = new List<PrinterConfig>();
|
||||
};
|
||||
|
||||
this.Extensions = new ExtensionsConfig(this.Library);
|
||||
this.Extensions.Register(new SheetEditor());
|
||||
this.Extensions.Register(new PropertyEditor());
|
||||
this.EditorExtensions = new EditorExtensionsConfig(this.Library);
|
||||
this.EditorExtensions.RegisterFactory((theme, undoBuffer) => new SheetEditor());
|
||||
this.EditorExtensions.RegisterFactory((theme, undoBuffer) => new PropertyEditor(theme, undoBuffer));
|
||||
|
||||
HelpArticle helpArticle = null;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ either expressed or implied, of the FreeBSD Project.
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.MatterControl.Library;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
|
|
@ -41,7 +42,7 @@ using MatterHackers.MeshVisualizer;
|
|||
|
||||
namespace MatterHackers.MatterControl
|
||||
{
|
||||
public class ExtensionsConfig
|
||||
public class EditorExtensionsConfig
|
||||
{
|
||||
private LibraryConfig libraryConfig;
|
||||
|
||||
|
|
@ -52,37 +53,39 @@ namespace MatterHackers.MatterControl
|
|||
// new SubtractAndReplace()
|
||||
// };
|
||||
|
||||
public ExtensionsConfig(LibraryConfig libraryConfig)
|
||||
public EditorExtensionsConfig(LibraryConfig libraryConfig)
|
||||
{
|
||||
this.libraryConfig = libraryConfig;
|
||||
|
||||
objectEditorsByType = new Dictionary<Type, HashSet<IObjectEditor>>();
|
||||
objectEditorsByType = new Dictionary<Type, HashSet<Func<ThemeConfig, UndoBuffer, IObjectEditor>>>();
|
||||
}
|
||||
|
||||
private void MapTypesToEditor(IObjectEditor editor)
|
||||
private void MapTypesToEditorFactory(Func<ThemeConfig, UndoBuffer, IObjectEditor> object3DEditorFactory)
|
||||
{
|
||||
var editor = object3DEditorFactory.Invoke(null, null);
|
||||
|
||||
foreach (Type type in editor.SupportedTypes())
|
||||
{
|
||||
if (!objectEditorsByType.TryGetValue(type, out HashSet<IObjectEditor> mappedEditors))
|
||||
if (!objectEditorsByType.TryGetValue(type, out HashSet<Func<ThemeConfig, UndoBuffer, IObjectEditor>> mappedEditorsFactories))
|
||||
{
|
||||
mappedEditors = new HashSet<IObjectEditor>();
|
||||
objectEditorsByType.Add(type, mappedEditors);
|
||||
mappedEditorsFactories = new HashSet<Func<ThemeConfig, UndoBuffer, IObjectEditor>>();
|
||||
objectEditorsByType.Add(type, mappedEditorsFactories);
|
||||
}
|
||||
|
||||
mappedEditors.Add(editor);
|
||||
mappedEditorsFactories.Add(object3DEditorFactory);
|
||||
}
|
||||
}
|
||||
|
||||
public void Register(IObjectEditor object3DEditor)
|
||||
public void RegisterFactory(Func<ThemeConfig, UndoBuffer, IObjectEditor> object3DEditorFactory)
|
||||
{
|
||||
this.MapTypesToEditor(object3DEditor);
|
||||
this.MapTypesToEditorFactory(object3DEditorFactory);
|
||||
}
|
||||
|
||||
private Dictionary<Type, HashSet<IObjectEditor>> objectEditorsByType;
|
||||
private Dictionary<Type, HashSet<Func<ThemeConfig, UndoBuffer, IObjectEditor>>> objectEditorsByType;
|
||||
|
||||
public HashSet<IObjectEditor> GetEditorsForType(Type selectedItemType)
|
||||
public HashSet<Func<ThemeConfig, UndoBuffer, IObjectEditor>> GetEditorsForType(Type selectedItemType)
|
||||
{
|
||||
HashSet<IObjectEditor> mappedEditors;
|
||||
HashSet<Func<ThemeConfig, UndoBuffer, IObjectEditor>> mappedEditors;
|
||||
objectEditorsByType.TryGetValue(selectedItemType, out mappedEditors);
|
||||
|
||||
if (mappedEditors == null)
|
||||
|
|
@ -48,7 +48,7 @@ namespace MatterHackers.Plugins.EditorTools
|
|||
applicationController.Library.RegisterCreator(item);
|
||||
}
|
||||
|
||||
applicationController.Extensions.Register(new OpenSCADBuilder());
|
||||
applicationController.EditorExtensions.RegisterFactory((theme, undoBuffer) => new OpenSCADBuilder());
|
||||
// applicationController.Extensions.Register(new PrimitivesEditor());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,13 +27,6 @@ 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.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Web;
|
||||
using Markdig.Agg;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Image;
|
||||
|
|
@ -48,26 +41,28 @@ using MatterHackers.MatterControl.Library.Widgets;
|
|||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using MatterHackers.MatterControl.SlicerConfiguration;
|
||||
using MatterHackers.VectorMath;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace MatterHackers.MatterControl.DesignTools
|
||||
{
|
||||
public class PropertyEditor : IObjectEditor
|
||||
public interface IPropertyEditorFactory
|
||||
{
|
||||
static PropertyEditor()
|
||||
{
|
||||
SelectedChildrenEditor.Register();
|
||||
GuiWidget CreateEditor(PropertyEditor propertyEditor, EditableProperty property, EditorContext context);
|
||||
}
|
||||
|
||||
public string Name => "Property Editor";
|
||||
public class PropertyEditor : IObjectEditor
|
||||
{
|
||||
public const BindingFlags OwnedPropertiesOnly = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
|
||||
|
||||
public IEnumerable<Type> SupportedTypes() => new Type[] { typeof(IObject3D) };
|
||||
|
||||
private static readonly Dictionary<Type, CreateEditorDelegate> AllowedTypes = new Dictionary<Type, CreateEditorDelegate>()
|
||||
private static readonly Dictionary<Type, IPropertyEditorFactory> AllowedTypes = new Dictionary<Type, IPropertyEditorFactory>()
|
||||
{
|
||||
{ typeof(double), null },
|
||||
{ typeof(int), null },
|
||||
{ typeof(char), null },
|
||||
{ typeof(string), null },
|
||||
{ typeof(bool), null },
|
||||
{ typeof(StringOrExpression), null },
|
||||
{ typeof(DoubleOrExpression), null },
|
||||
|
|
@ -85,19 +80,201 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
{ typeof(PrinterSettingsLayer), null }
|
||||
};
|
||||
|
||||
public delegate GuiWidget CreateEditorDelegate(EditableProperty property, EditorContext context, UndoBuffer undoBuffer, ThemeConfig theme);
|
||||
private SafeList<SettingsRow> rows = new SafeList<SettingsRow>();
|
||||
|
||||
public static void RegisterEditor(Type type, CreateEditorDelegate createEditorDelegate)
|
||||
public ThemeConfig Theme { get; }
|
||||
|
||||
public UndoBuffer UndoBuffer { get; }
|
||||
|
||||
static PropertyEditor()
|
||||
{
|
||||
SelectedChildrenPropertyEditor.Register();
|
||||
StringPropertyEditor.Register();
|
||||
}
|
||||
|
||||
public PropertyEditor(ThemeConfig theme, UndoBuffer undoBuffer)
|
||||
{
|
||||
this.Theme = theme;
|
||||
this.UndoBuffer = undoBuffer;
|
||||
}
|
||||
|
||||
public string Name => "Property Editor";
|
||||
|
||||
public static void AddMarkDownDescription(object item, GuiWidget editControlsContainer, ThemeConfig theme)
|
||||
{
|
||||
if (item.GetType().GetCustomAttributes(typeof(MarkDownDescriptionAttribute), true).FirstOrDefault() is MarkDownDescriptionAttribute markdownDescription)
|
||||
{
|
||||
var markdownWidget = new MarkdownWidget(theme)
|
||||
{
|
||||
Padding = new BorderDouble(left: theme.DefaultContainerPadding / 2),
|
||||
Markdown = markdownDescription.Markdown,
|
||||
VAnchor = VAnchor.Fit
|
||||
};
|
||||
|
||||
editControlsContainer.AddChild(markdownWidget);
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddUnlockLinkIfRequired(IObject3D item, GuiWidget editControlsContainer, ThemeConfig theme)
|
||||
{
|
||||
(string url, GuiWidget markdownWidget)? unlockdata = null;
|
||||
|
||||
if (item.GetType().GetCustomAttributes(typeof(RequiresPermissionsAttribute), true).FirstOrDefault() is RequiresPermissionsAttribute unlockLink
|
||||
&& !ApplicationController.Instance.UserHasPermission(item))
|
||||
{
|
||||
unlockdata = ApplicationController.Instance.GetUnlockData?.Invoke(item, theme);
|
||||
}
|
||||
else if (!item.Persistable)
|
||||
{
|
||||
// find the first self or child that is not authorized
|
||||
var permission = item.DescendantsAndSelf()
|
||||
.Where(i => !i.Persistable && !ApplicationController.Instance.UserHasPermission(i));
|
||||
|
||||
if (permission.Any())
|
||||
{
|
||||
var unlockItem = permission.First();
|
||||
unlockdata = ApplicationController.Instance.GetUnlockData?.Invoke(unlockItem, theme);
|
||||
}
|
||||
}
|
||||
|
||||
if (unlockdata != null && !string.IsNullOrEmpty(unlockdata.Value.url))
|
||||
{
|
||||
if (unlockdata.Value.markdownWidget != null)
|
||||
{
|
||||
unlockdata.Value.markdownWidget.VAnchor = VAnchor.Fit;
|
||||
editControlsContainer.AddChild(unlockdata.Value.markdownWidget);
|
||||
}
|
||||
|
||||
editControlsContainer.AddChild(GetUnlockRow(theme, unlockdata.Value.url));
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddWebPageLinkIfRequired(object item, FlowLayoutWidget editControlsContainer, ThemeConfig theme)
|
||||
{
|
||||
if (item.GetType().GetCustomAttributes(typeof(WebPageLinkAttribute), true).FirstOrDefault() is WebPageLinkAttribute unlockLink)
|
||||
{
|
||||
var detailsLink = new ThemedTextIconButton(unlockLink.ButtonName.Localize(), StaticData.Instance.LoadIcon("internet.png", 16, 16).GrayToColor(theme.TextColor), theme)
|
||||
{
|
||||
BackgroundColor = theme.MinimalShade,
|
||||
ToolTipText = unlockLink.Url,
|
||||
};
|
||||
detailsLink.Click += (s, e) =>
|
||||
{
|
||||
ApplicationController.LaunchBrowser(unlockLink.Url);
|
||||
};
|
||||
|
||||
// website row
|
||||
editControlsContainer.AddChild(new SettingsRow(unlockLink.RowName, null, detailsLink, theme));
|
||||
}
|
||||
}
|
||||
|
||||
public static FlowLayoutWidget CreateSettingsColumn(EditableProperty property, UIField field, bool fullWidth = false)
|
||||
{
|
||||
return CreateSettingsColumn(property.DisplayName.Localize(), field, property.Description, fullWidth: fullWidth);
|
||||
}
|
||||
|
||||
public static FlowLayoutWidget CreateSettingsColumn(EditableProperty property)
|
||||
{
|
||||
return CreateSettingsColumn(property.DisplayName.Localize(), property.Description);
|
||||
}
|
||||
|
||||
public static IEnumerable<EditableProperty> GetEditablePropreties(object item)
|
||||
{
|
||||
return item.GetType().GetProperties(OwnedPropertiesOnly)
|
||||
.Where(pi => (AllowedTypes.ContainsKey(pi.PropertyType) || pi.PropertyType.IsEnum)
|
||||
&& pi.GetGetMethod() != null
|
||||
&& pi.GetSetMethod() != null)
|
||||
.Select(p => new EditableProperty(p, item));
|
||||
}
|
||||
|
||||
public static IEnumerable<EditableProperty> GetExecutableFunctions(IObject3D item)
|
||||
{
|
||||
BindingFlags buttonFunctionsOnly = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
|
||||
|
||||
return item.GetType().GetProperties(buttonFunctionsOnly)
|
||||
.Where(pi => (AllowedTypes.ContainsKey(pi.PropertyType) || pi.PropertyType.IsEnum)
|
||||
&& pi.GetGetMethod() != null
|
||||
&& pi.GetSetMethod() != null)
|
||||
.Select(p => new EditableProperty(p, item));
|
||||
}
|
||||
|
||||
public static GuiWidget GetUnlockRow(ThemeConfig theme, string url)
|
||||
{
|
||||
var detailsLink = new ThemedTextIconButton("Unlock".Localize(), StaticData.Instance.LoadIcon("locked.png", 16, 16).GrayToColor(theme.TextColor), theme)
|
||||
{
|
||||
Margin = 5,
|
||||
ToolTipText = "Visit MatterHackers.com to Purchase".Localize()
|
||||
};
|
||||
detailsLink.Click += (s, e) =>
|
||||
{
|
||||
ApplicationController.LaunchBrowser(url);
|
||||
};
|
||||
theme.ApplyPrimaryActionStyle(detailsLink);
|
||||
|
||||
return new SettingsRow("Demo Mode".Localize(), null, detailsLink, theme);
|
||||
}
|
||||
|
||||
public static void RegisterEditor(Type type, IPropertyEditorFactory propertyEditorFactory)
|
||||
{
|
||||
if (!AllowedTypes.ContainsKey(type))
|
||||
{
|
||||
AllowedTypes.Add(type, createEditorDelegate);
|
||||
AllowedTypes.Add(type, propertyEditorFactory);
|
||||
}
|
||||
}
|
||||
|
||||
public const BindingFlags OwnedPropertiesOnly = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
|
||||
public static void RegisterValueChanged(EditableProperty property, UndoBuffer undoBuffer, EditorContext context, UIField field, Func<string, object> valueFromString, Func<object, string> valueToString = null)
|
||||
{
|
||||
field.ValueChanged += (s, e) =>
|
||||
{
|
||||
var contextItem = context.Item;
|
||||
var contextObject3D = contextItem as IObject3D;
|
||||
var propertyObject3D = property.Source as IObject3D;
|
||||
var propertyGridModifier = property.Source as IPropertyGridModifier;
|
||||
|
||||
private SafeList<SettingsRow> rows = new SafeList<SettingsRow>();
|
||||
var newValue = field.Value;
|
||||
var oldValue = "";
|
||||
if (property.Value is DirectOrExpression directOrExpression)
|
||||
{
|
||||
oldValue = directOrExpression.Expression;
|
||||
}
|
||||
else
|
||||
{
|
||||
oldValue = property.Value.ToString();
|
||||
}
|
||||
if (newValue == oldValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (valueToString != null)
|
||||
{
|
||||
oldValue = valueToString(property.Value);
|
||||
}
|
||||
|
||||
// field.Content
|
||||
if (undoBuffer != null
|
||||
&& e.UserInitiated)
|
||||
{
|
||||
undoBuffer.AddAndDo(new UndoRedoActions(() =>
|
||||
{
|
||||
property.SetValue(valueFromString(oldValue));
|
||||
propertyObject3D?.Invalidate(new InvalidateArgs(contextObject3D, InvalidateType.Properties));
|
||||
propertyGridModifier?.UpdateControls(new PublicPropertyChange(context, property.PropertyInfo.Name));
|
||||
},
|
||||
() =>
|
||||
{
|
||||
property.SetValue(valueFromString(newValue));
|
||||
propertyObject3D?.Invalidate(new InvalidateArgs(contextObject3D, InvalidateType.Properties));
|
||||
propertyGridModifier?.UpdateControls(new PublicPropertyChange(context, property.PropertyInfo.Name));
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
property.SetValue(valueFromString(newValue));
|
||||
propertyObject3D?.Invalidate(new InvalidateArgs(contextObject3D, InvalidateType.Properties));
|
||||
propertyGridModifier?.UpdateControls(new PublicPropertyChange(context, property.PropertyInfo.Name));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public GuiWidget Create(object item, UndoBuffer undoBuffer, ThemeConfig theme)
|
||||
{
|
||||
|
|
@ -170,7 +347,7 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
scope = mainContainer;
|
||||
}
|
||||
|
||||
var editor = CreatePropertyEditor(rows, property, undoBuffer, context, theme);
|
||||
var editor = CreatePropertyEditor(property, undoBuffer, context, theme);
|
||||
if (editor != null)
|
||||
{
|
||||
scope.AddChild(editor);
|
||||
|
|
@ -210,174 +387,7 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
return mainContainer;
|
||||
}
|
||||
|
||||
private void AddFunctionButtons(object item, FlowLayoutWidget mainContainer, ThemeConfig theme)
|
||||
{
|
||||
if (item is IEditorButtonProvider editorButtonProvider)
|
||||
{
|
||||
foreach (var editorButtonData in editorButtonProvider.GetEditorButtonsData())
|
||||
{
|
||||
var editorButton = new ThemedTextButton(editorButtonData.Name, theme)
|
||||
{
|
||||
Margin = 5,
|
||||
ToolTipText = editorButtonData.HelpText,
|
||||
BackgroundColor = theme.MinimalShade,
|
||||
};
|
||||
if (editorButtonData.PrimaryAction)
|
||||
{
|
||||
theme.ApplyPrimaryActionStyle(editorButton);
|
||||
}
|
||||
|
||||
var row = new SettingsRow("".Localize(), null, editorButton, theme);
|
||||
editorButtonData.SetStates?.Invoke(editorButton, row);
|
||||
editorButton.Click += (s, e) =>
|
||||
{
|
||||
editorButtonData.Action?.Invoke();
|
||||
};
|
||||
|
||||
mainContainer.AddChild(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static SettingsRow CreateSettingsRow(EditableProperty property, GuiWidget content, ThemeConfig theme, SafeList<SettingsRow> rows = null)
|
||||
{
|
||||
var row = new SettingsRow(property.DisplayName.Localize(), property.Description, content, theme);
|
||||
if (rows != null)
|
||||
{
|
||||
rows.Add(row);
|
||||
row.SetTextRightMargin(rows);
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
public static FlowLayoutWidget CreateSettingsColumn(EditableProperty property, UIField field, bool fullWidth = false)
|
||||
{
|
||||
return CreateSettingsColumn(property.DisplayName.Localize(), field, property.Description, fullWidth: fullWidth);
|
||||
}
|
||||
|
||||
public static FlowLayoutWidget CreateSettingsColumn(EditableProperty property)
|
||||
{
|
||||
return CreateSettingsColumn(property.DisplayName.Localize(), property.Description);
|
||||
}
|
||||
|
||||
private static FlowLayoutWidget CreateSettingsColumn(string labelText, UIField field, string toolTipText = null, bool fullWidth = false)
|
||||
{
|
||||
var row = new FlowLayoutWidget()
|
||||
{
|
||||
HAnchor = HAnchor.Stretch
|
||||
};
|
||||
|
||||
if (!fullWidth)
|
||||
{
|
||||
row.AddChild(new HorizontalSpacer());
|
||||
}
|
||||
|
||||
row.AddChild(field.Content);
|
||||
|
||||
var column = CreateSettingsColumn(labelText, toolTipText);
|
||||
column.AddChild(row);
|
||||
|
||||
return column;
|
||||
}
|
||||
|
||||
private static FlowLayoutWidget CreateSettingsColumn(string labelText, string toolTipText = null)
|
||||
{
|
||||
var theme = AppContext.Theme;
|
||||
|
||||
var column = new FlowLayoutWidget(FlowDirection.TopToBottom)
|
||||
{
|
||||
HAnchor = HAnchor.Stretch,
|
||||
Padding = new BorderDouble(9, 5, 5, 5), // Use hard-coded 9 pixel left margin to match SettingsRow
|
||||
ToolTipText = toolTipText
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(labelText))
|
||||
{
|
||||
var label = SettingsRow.CreateSettingsLabel(labelText, toolTipText, theme.TextColor);
|
||||
label.VAnchor = VAnchor.Absolute;
|
||||
label.HAnchor = HAnchor.Left;
|
||||
|
||||
column.AddChild(label);
|
||||
}
|
||||
|
||||
return column;
|
||||
}
|
||||
|
||||
public static IEnumerable<EditableProperty> GetEditablePropreties(object item)
|
||||
{
|
||||
return item.GetType().GetProperties(OwnedPropertiesOnly)
|
||||
.Where(pi => (AllowedTypes.ContainsKey(pi.PropertyType) || pi.PropertyType.IsEnum)
|
||||
&& pi.GetGetMethod() != null
|
||||
&& pi.GetSetMethod() != null)
|
||||
.Select(p => new EditableProperty(p, item));
|
||||
}
|
||||
|
||||
public static IEnumerable<EditableProperty> GetExecutableFunctions(IObject3D item)
|
||||
{
|
||||
BindingFlags buttonFunctionsOnly = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
|
||||
|
||||
return item.GetType().GetProperties(buttonFunctionsOnly)
|
||||
.Where(pi => (AllowedTypes.ContainsKey(pi.PropertyType) || pi.PropertyType.IsEnum)
|
||||
&& pi.GetGetMethod() != null
|
||||
&& pi.GetSetMethod() != null)
|
||||
.Select(p => new EditableProperty(p, item));
|
||||
}
|
||||
|
||||
public static void RegisterValueChanged(EditableProperty property, UndoBuffer undoBuffer, EditorContext context, UIField field, Func<string, object> valueFromString, Func<object, string> valueToString = null)
|
||||
{
|
||||
field.ValueChanged += (s, e) =>
|
||||
{
|
||||
var contextItem = context.Item;
|
||||
var contextObject3D = contextItem as IObject3D;
|
||||
var propertyObject3D = property.Source as IObject3D;
|
||||
var propertyGridModifier = property.Source as IPropertyGridModifier;
|
||||
|
||||
var newValue = field.Value;
|
||||
var oldValue = "";
|
||||
if (property.Value is DirectOrExpression directOrExpression)
|
||||
{
|
||||
oldValue = directOrExpression.Expression;
|
||||
}
|
||||
else
|
||||
{
|
||||
oldValue = property.Value.ToString();
|
||||
}
|
||||
if (newValue == oldValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (valueToString != null)
|
||||
{
|
||||
oldValue = valueToString(property.Value);
|
||||
}
|
||||
|
||||
// field.Content
|
||||
if (undoBuffer != null
|
||||
&& e.UserInitiated)
|
||||
{
|
||||
undoBuffer.AddAndDo(new UndoRedoActions(() =>
|
||||
{
|
||||
property.SetValue(valueFromString(oldValue));
|
||||
propertyObject3D?.Invalidate(new InvalidateArgs(contextObject3D, InvalidateType.Properties));
|
||||
propertyGridModifier?.UpdateControls(new PublicPropertyChange(context, property.PropertyInfo.Name));
|
||||
},
|
||||
() =>
|
||||
{
|
||||
property.SetValue(valueFromString(newValue));
|
||||
propertyObject3D?.Invalidate(new InvalidateArgs(contextObject3D, InvalidateType.Properties));
|
||||
propertyGridModifier?.UpdateControls(new PublicPropertyChange(context, property.PropertyInfo.Name));
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
property.SetValue(valueFromString(newValue));
|
||||
propertyObject3D?.Invalidate(new InvalidateArgs(contextObject3D, InvalidateType.Properties));
|
||||
propertyGridModifier?.UpdateControls(new PublicPropertyChange(context, property.PropertyInfo.Name));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static GuiWidget CreatePropertyEditor(SafeList<SettingsRow> rows, EditableProperty property, UndoBuffer undoBuffer, EditorContext context, ThemeConfig theme)
|
||||
public GuiWidget CreatePropertyEditor(EditableProperty property, UndoBuffer undoBuffer, EditorContext context, ThemeConfig theme)
|
||||
{
|
||||
if (property == null
|
||||
|| context == null)
|
||||
|
|
@ -401,7 +411,7 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
if (AllowedTypes.ContainsKey(propertyValue.GetType())
|
||||
&& AllowedTypes[propertyValue.GetType()] != null)
|
||||
{
|
||||
rowContainer = AllowedTypes[propertyValue.GetType()](property, context, undoBuffer, theme);
|
||||
rowContainer = AllowedTypes[propertyValue.GetType()].CreateEditor(this, property, context);
|
||||
}
|
||||
else if (propertyValue is double doubleValue)
|
||||
{
|
||||
|
|
@ -876,7 +886,7 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
return doubleExpresion;
|
||||
}, theme),
|
||||
theme,
|
||||
rows);
|
||||
true);
|
||||
|
||||
void RefreshField(object s, InvalidateArgs e)
|
||||
{
|
||||
|
|
@ -952,7 +962,7 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
return intExpresion;
|
||||
}, theme),
|
||||
theme,
|
||||
rows);
|
||||
true);
|
||||
|
||||
void RefreshField(object s, InvalidateArgs e)
|
||||
{
|
||||
|
|
@ -985,160 +995,6 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
propertyIObject3D.Invalidated += RefreshField;
|
||||
field.Content.Closed += (s, e) => propertyIObject3D.Invalidated -= RefreshField;
|
||||
}
|
||||
else if (propertyValue is string stringValue)
|
||||
{
|
||||
if (property.PropertyInfo.GetCustomAttributes(true).OfType<GoogleSearchAttribute>().FirstOrDefault() != null)
|
||||
{
|
||||
rowContainer = NewImageSearchWidget(theme);
|
||||
}
|
||||
else if (propertyIObject3D is AssetObject3D assetObject
|
||||
&& property.PropertyInfo.Name == "AssetPath")
|
||||
{
|
||||
// This is the AssetPath property of an asset object, add a button to set the AssetPath from a file
|
||||
// Change button
|
||||
var changeButton = new ThemedTextButton(property.Description, theme)
|
||||
{
|
||||
BackgroundColor = theme.MinimalShade,
|
||||
Margin = 3
|
||||
};
|
||||
|
||||
rowContainer = new SettingsRow(property.DisplayName,
|
||||
null,
|
||||
changeButton,
|
||||
theme);
|
||||
|
||||
|
||||
changeButton.Click += (sender, e) =>
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
ImageObject3D.ShowOpenDialog(assetObject);
|
||||
});
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
if (readOnly)
|
||||
{
|
||||
WrappedTextWidget wrappedTextWidget = null;
|
||||
if (!string.IsNullOrEmpty(property.DisplayName))
|
||||
{
|
||||
rowContainer = new GuiWidget()
|
||||
{
|
||||
HAnchor = HAnchor.Stretch,
|
||||
VAnchor = VAnchor.Fit,
|
||||
Margin = 9
|
||||
};
|
||||
|
||||
var displayName = rowContainer.AddChild(new TextWidget(property.DisplayName,
|
||||
textColor: theme.TextColor,
|
||||
pointSize: 10)
|
||||
{
|
||||
VAnchor = VAnchor.Center,
|
||||
});
|
||||
|
||||
var wrapContainer = new GuiWidget()
|
||||
{
|
||||
Margin = new BorderDouble(displayName.Width + displayName.Margin.Width + 15, 3, 3, 3),
|
||||
HAnchor = HAnchor.Stretch,
|
||||
VAnchor = VAnchor.Fit
|
||||
};
|
||||
wrappedTextWidget = new WrappedTextWidget(stringValue, textColor: theme.TextColor, pointSize: 10)
|
||||
{
|
||||
HAnchor = HAnchor.Stretch
|
||||
};
|
||||
wrappedTextWidget.TextWidget.HAnchor = HAnchor.Right;
|
||||
wrapContainer.AddChild(wrappedTextWidget);
|
||||
rowContainer.AddChild(wrapContainer);
|
||||
}
|
||||
else
|
||||
{
|
||||
rowContainer = wrappedTextWidget = new WrappedTextWidget(stringValue,
|
||||
textColor: theme.TextColor,
|
||||
pointSize: 10)
|
||||
{
|
||||
Margin = 9
|
||||
};
|
||||
}
|
||||
|
||||
void RefreshField(object s, InvalidateArgs e)
|
||||
{
|
||||
if (e.InvalidateType.HasFlag(InvalidateType.DisplayValues))
|
||||
{
|
||||
wrappedTextWidget.Text = property.Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
if (propertyIObject3D != null)
|
||||
{
|
||||
propertyIObject3D.Invalidated += RefreshField;
|
||||
wrappedTextWidget.Closed += (s, e) => propertyIObject3D.Invalidated -= RefreshField;
|
||||
}
|
||||
}
|
||||
else // normal edit row
|
||||
{
|
||||
if (property.PropertyInfo.GetCustomAttributes(true).OfType<MultiLineEditAttribute>().FirstOrDefault() != null)
|
||||
{
|
||||
// create a a multi-line string editor
|
||||
var field = new MultilineStringField(theme, property.PropertyInfo.GetCustomAttributes(true).OfType<UpdateOnEveryKeystrokeAttribute>().FirstOrDefault() != null);
|
||||
field.Initialize(0);
|
||||
field.SetValue(stringValue, false);
|
||||
field.ClearUndoHistory();
|
||||
field.Content.HAnchor = HAnchor.Stretch;
|
||||
field.Content.Descendants<ScrollableWidget>().FirstOrDefault().MaximumSize = new Vector2(double.MaxValue, 200);
|
||||
field.Content.Descendants<ScrollingArea>().FirstOrDefault().Parent.VAnchor = VAnchor.Top;
|
||||
field.Content.MinimumSize = new Vector2(0, 100 * GuiWidget.DeviceScale);
|
||||
field.Content.Margin = new BorderDouble(0, 0, 0, 5);
|
||||
RegisterValueChanged(property, undoBuffer, context, field, (valueString) => valueString);
|
||||
rowContainer = CreateSettingsColumn(property, field, fullWidth: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create a string editor
|
||||
var field = new TextField(theme);
|
||||
field.Initialize(0);
|
||||
field.SetValue(stringValue, false);
|
||||
field.ClearUndoHistory();
|
||||
field.Content.HAnchor = HAnchor.Stretch;
|
||||
RegisterValueChanged(property, undoBuffer, context, field, (valueString) => valueString);
|
||||
rowContainer = CreateSettingsRow(property, field.Content, theme, rows);
|
||||
|
||||
// check for DirectoryPathAttribute
|
||||
var directoryPathAttribute = property.PropertyInfo.GetCustomAttributes(true).OfType<DirectoryPathAttribute>().FirstOrDefault();
|
||||
if (directoryPathAttribute != null)
|
||||
{
|
||||
// add a browse button
|
||||
var browseButton = new ThemedIconButton(StaticData.Instance.LoadIcon(Path.Combine("Library", "folder.png"), 16, 16).GrayToColor(theme.TextColor), theme)
|
||||
{
|
||||
ToolTipText = "Select Folder".Localize(),
|
||||
};
|
||||
browseButton.Click += (s, e) =>
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
AggContext.FileDialogs.SelectFolderDialog(
|
||||
new SelectFolderDialogParams(directoryPathAttribute.Message)
|
||||
{
|
||||
ActionButtonLabel = directoryPathAttribute.ActionLabel,
|
||||
Title = ApplicationController.Instance.ProductName + " - " + "Select A Folder".Localize(),
|
||||
RootFolder = SelectFolderDialogParams.RootFolderTypes.Specify,
|
||||
FolderPath = stringValue
|
||||
},
|
||||
(openParams) =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(openParams.FolderPath))
|
||||
{
|
||||
field.SetValue(openParams.FolderPath, true);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
rowContainer.AddChild(browseButton);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (propertyValue is StringOrExpression stringOrExpression)
|
||||
{
|
||||
if (property.PropertyInfo.GetCustomAttributes(true).OfType<MultiLineEditAttribute>().FirstOrDefault() != null)
|
||||
|
|
@ -1293,13 +1149,12 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
propertyIObject3D.Invalidated += RefreshField;
|
||||
field.Content.Closed += (s, e) => propertyIObject3D.Invalidated -= RefreshField;
|
||||
}
|
||||
|
||||
}
|
||||
else if (propertyValue is IObject3D item
|
||||
&& ApplicationController.Instance.Extensions.GetEditorsForType(property.PropertyType)?.FirstOrDefault() is IObjectEditor iObject3DEditor)
|
||||
&& ApplicationController.Instance.EditorExtensions.GetEditorsForType(property.PropertyType)?.FirstOrDefault() is Func<ThemeConfig, UndoBuffer, IObjectEditor> iObject3DEditorFactory)
|
||||
{
|
||||
// Use known IObject3D editors
|
||||
rowContainer = iObject3DEditor.Create(item, undoBuffer, theme);
|
||||
rowContainer = iObject3DEditorFactory.Invoke(theme, undoBuffer).Create(item, undoBuffer, theme);
|
||||
}
|
||||
|
||||
// remember the row name and widget
|
||||
|
|
@ -1308,121 +1163,88 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
return rowContainer;
|
||||
}
|
||||
|
||||
public static GuiWidget NewImageSearchWidget(ThemeConfig theme, string postPend = "silhouette")
|
||||
public SettingsRow CreateSettingsRow(EditableProperty property, GuiWidget content, ThemeConfig theme, bool alignRightMargin = false)
|
||||
{
|
||||
var searchRow = new FlowLayoutWidget()
|
||||
var row = new SettingsRow(property.DisplayName.Localize(), property.Description, content, theme);
|
||||
if (rows != null)
|
||||
{
|
||||
rows.Add(row);
|
||||
row.SetTextRightMargin(rows);
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
public IEnumerable<Type> SupportedTypes() => new Type[] { typeof(IObject3D) };
|
||||
|
||||
private static FlowLayoutWidget CreateSettingsColumn(string labelText, UIField field, string toolTipText = null, bool fullWidth = false)
|
||||
{
|
||||
var row = new FlowLayoutWidget()
|
||||
{
|
||||
HAnchor = HAnchor.Stretch
|
||||
};
|
||||
|
||||
if (!fullWidth)
|
||||
{
|
||||
row.AddChild(new HorizontalSpacer());
|
||||
}
|
||||
|
||||
row.AddChild(field.Content);
|
||||
|
||||
var column = CreateSettingsColumn(labelText, toolTipText);
|
||||
column.AddChild(row);
|
||||
|
||||
return column;
|
||||
}
|
||||
|
||||
private static FlowLayoutWidget CreateSettingsColumn(string labelText, string toolTipText = null)
|
||||
{
|
||||
var theme = AppContext.Theme;
|
||||
|
||||
var column = new FlowLayoutWidget(FlowDirection.TopToBottom)
|
||||
{
|
||||
HAnchor = HAnchor.Stretch,
|
||||
Margin = new BorderDouble(5, 0)
|
||||
Padding = new BorderDouble(9, 5, 5, 5), // Use hard-coded 9 pixel left margin to match SettingsRow
|
||||
ToolTipText = toolTipText
|
||||
};
|
||||
|
||||
var searchField = new ThemedTextEditWidget("", theme, messageWhenEmptyAndNotSelected: "Search Google for images")
|
||||
if (!string.IsNullOrEmpty(labelText))
|
||||
{
|
||||
HAnchor = HAnchor.Stretch,
|
||||
VAnchor = VAnchor.Center
|
||||
};
|
||||
searchRow.AddChild(searchField);
|
||||
var searchButton = new ThemedIconButton(StaticData.Instance.LoadIcon("icon_search_24x24.png", 16, 16).GrayToColor(theme.TextColor), theme)
|
||||
{
|
||||
ToolTipText = "Search".Localize(),
|
||||
};
|
||||
searchRow.AddChild(searchButton);
|
||||
var label = SettingsRow.CreateSettingsLabel(labelText, toolTipText, theme.TextColor);
|
||||
label.VAnchor = VAnchor.Absolute;
|
||||
label.HAnchor = HAnchor.Left;
|
||||
|
||||
void DoSearch(object s, EventArgs e)
|
||||
{
|
||||
var search = HttpUtility.UrlEncode(searchField.Text);
|
||||
if (!string.IsNullOrEmpty(search))
|
||||
{
|
||||
ApplicationController.LaunchBrowser($"http://www.google.com/search?q={search} {postPend}&tbm=isch");
|
||||
}
|
||||
};
|
||||
|
||||
searchField.ActualTextEditWidget.EditComplete += DoSearch;
|
||||
searchButton.Click += DoSearch;
|
||||
return searchRow;
|
||||
column.AddChild(label);
|
||||
}
|
||||
|
||||
public static void AddUnlockLinkIfRequired(IObject3D item, GuiWidget editControlsContainer, ThemeConfig theme)
|
||||
{
|
||||
(string url, GuiWidget markdownWidget)? unlockdata = null;
|
||||
|
||||
if (item.GetType().GetCustomAttributes(typeof(RequiresPermissionsAttribute), true).FirstOrDefault() is RequiresPermissionsAttribute unlockLink
|
||||
&& !ApplicationController.Instance.UserHasPermission(item))
|
||||
{
|
||||
unlockdata = ApplicationController.Instance.GetUnlockData?.Invoke(item, theme);
|
||||
}
|
||||
else if (!item.Persistable)
|
||||
{
|
||||
// find the first self or child that is not authorized
|
||||
var permission = item.DescendantsAndSelf()
|
||||
.Where(i => !i.Persistable && !ApplicationController.Instance.UserHasPermission(i));
|
||||
|
||||
if (permission.Any())
|
||||
{
|
||||
var unlockItem = permission.First();
|
||||
unlockdata = ApplicationController.Instance.GetUnlockData?.Invoke(unlockItem, theme);
|
||||
}
|
||||
return column;
|
||||
}
|
||||
|
||||
if (unlockdata != null && !string.IsNullOrEmpty(unlockdata.Value.url))
|
||||
private void AddFunctionButtons(object item, FlowLayoutWidget mainContainer, ThemeConfig theme)
|
||||
{
|
||||
if (unlockdata.Value.markdownWidget != null)
|
||||
if (item is IEditorButtonProvider editorButtonProvider)
|
||||
{
|
||||
unlockdata.Value.markdownWidget.VAnchor = VAnchor.Fit;
|
||||
editControlsContainer.AddChild(unlockdata.Value.markdownWidget);
|
||||
}
|
||||
|
||||
editControlsContainer.AddChild(GetUnlockRow(theme, unlockdata.Value.url));
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddMarkDownDescription(object item, GuiWidget editControlsContainer, ThemeConfig theme)
|
||||
foreach (var editorButtonData in editorButtonProvider.GetEditorButtonsData())
|
||||
{
|
||||
if (item.GetType().GetCustomAttributes(typeof(MarkDownDescriptionAttribute), true).FirstOrDefault() is MarkDownDescriptionAttribute markdownDescription)
|
||||
{
|
||||
var markdownWidget = new MarkdownWidget(theme)
|
||||
{
|
||||
Padding = new BorderDouble(left: theme.DefaultContainerPadding / 2),
|
||||
Markdown = markdownDescription.Markdown,
|
||||
VAnchor = VAnchor.Fit
|
||||
};
|
||||
|
||||
editControlsContainer.AddChild(markdownWidget);
|
||||
}
|
||||
}
|
||||
|
||||
public static GuiWidget GetUnlockRow(ThemeConfig theme, string url)
|
||||
{
|
||||
var detailsLink = new ThemedTextIconButton("Unlock".Localize(), StaticData.Instance.LoadIcon("locked.png", 16, 16).GrayToColor(theme.TextColor), theme)
|
||||
var editorButton = new ThemedTextButton(editorButtonData.Name, theme)
|
||||
{
|
||||
Margin = 5,
|
||||
ToolTipText = "Visit MatterHackers.com to Purchase".Localize()
|
||||
};
|
||||
detailsLink.Click += (s, e) =>
|
||||
{
|
||||
ApplicationController.LaunchBrowser(url);
|
||||
};
|
||||
theme.ApplyPrimaryActionStyle(detailsLink);
|
||||
|
||||
return new SettingsRow("Demo Mode".Localize(), null, detailsLink, theme);
|
||||
}
|
||||
|
||||
public static void AddWebPageLinkIfRequired(object item, FlowLayoutWidget editControlsContainer, ThemeConfig theme)
|
||||
{
|
||||
if (item.GetType().GetCustomAttributes(typeof(WebPageLinkAttribute), true).FirstOrDefault() is WebPageLinkAttribute unlockLink)
|
||||
{
|
||||
var detailsLink = new ThemedTextIconButton(unlockLink.ButtonName.Localize(), StaticData.Instance.LoadIcon("internet.png", 16, 16).GrayToColor(theme.TextColor), theme)
|
||||
{
|
||||
ToolTipText = editorButtonData.HelpText,
|
||||
BackgroundColor = theme.MinimalShade,
|
||||
ToolTipText = unlockLink.Url,
|
||||
};
|
||||
detailsLink.Click += (s, e) =>
|
||||
if (editorButtonData.PrimaryAction)
|
||||
{
|
||||
ApplicationController.LaunchBrowser(unlockLink.Url);
|
||||
theme.ApplyPrimaryActionStyle(editorButton);
|
||||
}
|
||||
|
||||
var row = new SettingsRow("".Localize(), null, editorButton, theme);
|
||||
editorButtonData.SetStates?.Invoke(editorButton, row);
|
||||
editorButton.Click += (s, e) =>
|
||||
{
|
||||
editorButtonData.Action?.Invoke();
|
||||
};
|
||||
|
||||
// website row
|
||||
editControlsContainer.AddChild(new SettingsRow(unlockLink.RowName, null, detailsLink, theme));
|
||||
mainContainer.AddChild(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,12 +37,13 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using static MatterHackers.Agg.UI.OnScreenKeyboard;
|
||||
|
||||
namespace MatterHackers.MatterControl.DesignTools
|
||||
{
|
||||
public static class SelectedChildrenEditor
|
||||
public class SelectedChildrenPropertyEditor : IPropertyEditorFactory
|
||||
{
|
||||
public static GuiWidget CreateEditor(EditableProperty property, EditorContext context, UndoBuffer undoBuffer, ThemeConfig theme)
|
||||
public GuiWidget CreateEditor(PropertyEditor propertyEditor, EditableProperty property, EditorContext context)
|
||||
{
|
||||
var childSelector = property.Source as SelectedChildren;
|
||||
if (childSelector != null)
|
||||
|
|
@ -51,6 +52,8 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
throw new Exception("Passed the wrong type to the SelectedChildrenEditor");
|
||||
}
|
||||
|
||||
var theme = propertyEditor.Theme;
|
||||
var undoBuffer = propertyEditor.UndoBuffer;
|
||||
var contextItem = context.Item;
|
||||
var contextObject3D = contextItem as IObject3D;
|
||||
var propertyIObject3D = property.Source as IObject3D;
|
||||
|
|
@ -76,7 +79,7 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
return childrenSelector;
|
||||
});
|
||||
|
||||
rowContainer = PropertyEditor.CreateSettingsRow(property, field.Content, theme);
|
||||
rowContainer = propertyEditor.CreateSettingsRow(property, field.Content, theme);
|
||||
}
|
||||
else // show the subtract editor for boolean subtract and subtract and replace
|
||||
{
|
||||
|
|
@ -187,7 +190,7 @@ namespace MatterHackers.MatterControl.DesignTools
|
|||
|
||||
public static void Register()
|
||||
{
|
||||
PropertyEditor.RegisterEditor(typeof(SelectedChildren), CreateEditor);
|
||||
PropertyEditor.RegisterEditor(typeof(SelectedChildren), new SelectedChildrenPropertyEditor());
|
||||
}
|
||||
|
||||
private static GuiWidget CreateSelector(SelectedChildren childSelector, IObject3D parent, ThemeConfig theme)
|
||||
264
MatterControlLib/DesignTools/StringPropertyEditor.cs
Normal file
264
MatterControlLib/DesignTools/StringPropertyEditor.cs
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
Copyright (c) 2018, Lars Brubaker, John Lewin
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those
|
||||
of the authors and should not be interpreted as representing official policies,
|
||||
either expressed or implied, of the FreeBSD Project.
|
||||
*/
|
||||
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.ImageProcessing;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.Localizations;
|
||||
using MatterHackers.MatterControl.CustomWidgets;
|
||||
using MatterHackers.MatterControl.SlicerConfiguration;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.ComponentModel;
|
||||
using MatterHackers.VectorMath;
|
||||
using System.IO;
|
||||
|
||||
namespace MatterHackers.MatterControl.DesignTools
|
||||
{
|
||||
public class StringPropertyEditor : IPropertyEditorFactory
|
||||
{
|
||||
public GuiWidget CreateEditor(PropertyEditor propertyEditor, EditableProperty property, EditorContext context)
|
||||
{
|
||||
var stringValue = property.Source as string;
|
||||
if (stringValue != null)
|
||||
{
|
||||
// we passed the wrong type
|
||||
throw new Exception("Passed the wrong type to the SelectedChildrenEditor");
|
||||
}
|
||||
|
||||
var theme = propertyEditor.Theme;
|
||||
var undoBuffer = propertyEditor.UndoBuffer;
|
||||
|
||||
var contextItem = context.Item;
|
||||
var contextObject3D = contextItem as IObject3D;
|
||||
var propertyIObject3D = property.Source as IObject3D;
|
||||
var propertyGridModifier = property.Source as IPropertyGridModifier;
|
||||
|
||||
GuiWidget rowContainer = null;
|
||||
|
||||
if (property.PropertyInfo.GetCustomAttributes(true).OfType<GoogleSearchAttribute>().FirstOrDefault() != null)
|
||||
{
|
||||
rowContainer = NewImageSearchWidget(theme);
|
||||
}
|
||||
else if (propertyIObject3D is AssetObject3D assetObject
|
||||
&& property.PropertyInfo.Name == "AssetPath")
|
||||
{
|
||||
// This is the AssetPath property of an asset object, add a button to set the AssetPath from a file
|
||||
// Change button
|
||||
var changeButton = new ThemedTextButton(property.Description, theme)
|
||||
{
|
||||
BackgroundColor = theme.MinimalShade,
|
||||
Margin = 3
|
||||
};
|
||||
|
||||
rowContainer = new SettingsRow(property.DisplayName,
|
||||
null,
|
||||
changeButton,
|
||||
theme);
|
||||
|
||||
|
||||
changeButton.Click += (sender, e) =>
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
ImageObject3D.ShowOpenDialog(assetObject);
|
||||
});
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
var readOnly = property.PropertyInfo.GetCustomAttributes(true).OfType<ReadOnlyAttribute>().FirstOrDefault() != null;
|
||||
|
||||
if (readOnly)
|
||||
{
|
||||
WrappedTextWidget wrappedTextWidget = null;
|
||||
if (!string.IsNullOrEmpty(property.DisplayName))
|
||||
{
|
||||
rowContainer = new GuiWidget()
|
||||
{
|
||||
HAnchor = HAnchor.Stretch,
|
||||
VAnchor = VAnchor.Fit,
|
||||
Margin = 9
|
||||
};
|
||||
|
||||
var displayName = rowContainer.AddChild(new TextWidget(property.DisplayName,
|
||||
textColor: theme.TextColor,
|
||||
pointSize: 10)
|
||||
{
|
||||
VAnchor = VAnchor.Center,
|
||||
});
|
||||
|
||||
var wrapContainer = new GuiWidget()
|
||||
{
|
||||
Margin = new BorderDouble(displayName.Width + displayName.Margin.Width + 15, 3, 3, 3),
|
||||
HAnchor = HAnchor.Stretch,
|
||||
VAnchor = VAnchor.Fit
|
||||
};
|
||||
wrappedTextWidget = new WrappedTextWidget(stringValue, textColor: theme.TextColor, pointSize: 10)
|
||||
{
|
||||
HAnchor = HAnchor.Stretch
|
||||
};
|
||||
wrappedTextWidget.TextWidget.HAnchor = HAnchor.Right;
|
||||
wrapContainer.AddChild(wrappedTextWidget);
|
||||
rowContainer.AddChild(wrapContainer);
|
||||
}
|
||||
else
|
||||
{
|
||||
rowContainer = wrappedTextWidget = new WrappedTextWidget(stringValue,
|
||||
textColor: theme.TextColor,
|
||||
pointSize: 10)
|
||||
{
|
||||
Margin = 9
|
||||
};
|
||||
}
|
||||
|
||||
void RefreshField(object s, InvalidateArgs e)
|
||||
{
|
||||
if (e.InvalidateType.HasFlag(InvalidateType.DisplayValues))
|
||||
{
|
||||
wrappedTextWidget.Text = property.Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
if (propertyIObject3D != null)
|
||||
{
|
||||
propertyIObject3D.Invalidated += RefreshField;
|
||||
wrappedTextWidget.Closed += (s, e) => propertyIObject3D.Invalidated -= RefreshField;
|
||||
}
|
||||
}
|
||||
else // normal edit row
|
||||
{
|
||||
if (property.PropertyInfo.GetCustomAttributes(true).OfType<MultiLineEditAttribute>().FirstOrDefault() != null)
|
||||
{
|
||||
// create a a multi-line string editor
|
||||
var field = new MultilineStringField(theme, property.PropertyInfo.GetCustomAttributes(true).OfType<UpdateOnEveryKeystrokeAttribute>().FirstOrDefault() != null);
|
||||
field.Initialize(0);
|
||||
field.SetValue(stringValue, false);
|
||||
field.ClearUndoHistory();
|
||||
field.Content.HAnchor = HAnchor.Stretch;
|
||||
field.Content.Descendants<ScrollableWidget>().FirstOrDefault().MaximumSize = new Vector2(double.MaxValue, 200);
|
||||
field.Content.Descendants<ScrollingArea>().FirstOrDefault().Parent.VAnchor = VAnchor.Top;
|
||||
field.Content.MinimumSize = new Vector2(0, 100 * GuiWidget.DeviceScale);
|
||||
field.Content.Margin = new BorderDouble(0, 0, 0, 5);
|
||||
PropertyEditor.RegisterValueChanged(property, undoBuffer, context, field, (valueString) => valueString);
|
||||
rowContainer = PropertyEditor.CreateSettingsColumn(property, field, fullWidth: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create a string editor
|
||||
var field = new TextField(theme);
|
||||
field.Initialize(0);
|
||||
field.SetValue(stringValue, false);
|
||||
field.ClearUndoHistory();
|
||||
field.Content.HAnchor = HAnchor.Stretch;
|
||||
PropertyEditor.RegisterValueChanged(property, undoBuffer, context, field, (valueString) => valueString);
|
||||
rowContainer = propertyEditor.CreateSettingsRow(property, field.Content, theme, true);
|
||||
|
||||
// check for DirectoryPathAttribute
|
||||
var directoryPathAttribute = property.PropertyInfo.GetCustomAttributes(true).OfType<DirectoryPathAttribute>().FirstOrDefault();
|
||||
if (directoryPathAttribute != null)
|
||||
{
|
||||
// add a browse button
|
||||
var browseButton = new ThemedIconButton(StaticData.Instance.LoadIcon(Path.Combine("Library", "folder.png"), 16, 16).GrayToColor(theme.TextColor), theme)
|
||||
{
|
||||
ToolTipText = "Select Folder".Localize(),
|
||||
};
|
||||
browseButton.Click += (s, e) =>
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
AggContext.FileDialogs.SelectFolderDialog(
|
||||
new SelectFolderDialogParams(directoryPathAttribute.Message)
|
||||
{
|
||||
ActionButtonLabel = directoryPathAttribute.ActionLabel,
|
||||
Title = ApplicationController.Instance.ProductName + " - " + "Select A Folder".Localize(),
|
||||
RootFolder = SelectFolderDialogParams.RootFolderTypes.Specify,
|
||||
FolderPath = stringValue
|
||||
},
|
||||
(openParams) =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(openParams.FolderPath))
|
||||
{
|
||||
field.SetValue(openParams.FolderPath, true);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
rowContainer.AddChild(browseButton);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rowContainer;
|
||||
}
|
||||
|
||||
public static GuiWidget NewImageSearchWidget(ThemeConfig theme, string postPend = "silhouette")
|
||||
{
|
||||
var searchRow = new FlowLayoutWidget()
|
||||
{
|
||||
HAnchor = HAnchor.Stretch,
|
||||
Margin = new BorderDouble(5, 0)
|
||||
};
|
||||
|
||||
var searchField = new ThemedTextEditWidget("", theme, messageWhenEmptyAndNotSelected: "Search Google for images")
|
||||
{
|
||||
HAnchor = HAnchor.Stretch,
|
||||
VAnchor = VAnchor.Center
|
||||
};
|
||||
searchRow.AddChild(searchField);
|
||||
var searchButton = new ThemedIconButton(StaticData.Instance.LoadIcon("icon_search_24x24.png", 16, 16).GrayToColor(theme.TextColor), theme)
|
||||
{
|
||||
ToolTipText = "Search".Localize(),
|
||||
};
|
||||
searchRow.AddChild(searchButton);
|
||||
|
||||
void DoSearch(object s, EventArgs e)
|
||||
{
|
||||
var search = HttpUtility.UrlEncode(searchField.Text);
|
||||
if (!string.IsNullOrEmpty(search))
|
||||
{
|
||||
ApplicationController.LaunchBrowser($"http://www.google.com/search?q={search} {postPend}&tbm=isch");
|
||||
}
|
||||
};
|
||||
|
||||
searchField.ActualTextEditWidget.EditComplete += DoSearch;
|
||||
searchButton.Click += DoSearch;
|
||||
return searchRow;
|
||||
}
|
||||
|
||||
public static void Register()
|
||||
{
|
||||
PropertyEditor.RegisterEditor(typeof(String), new StringPropertyEditor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -60,8 +60,9 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
|
||||
var rows = new SafeList<SettingsRow>();
|
||||
|
||||
var editor = PropertyEditor.CreatePropertyEditor(
|
||||
rows,
|
||||
var propertyEditor = new PropertyEditor(theme, new UndoBuffer());
|
||||
|
||||
var editor = propertyEditor.CreatePropertyEditor(
|
||||
new EditableProperty(propertyInfo, supportGenerator),
|
||||
null,
|
||||
new EditorContext(),
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
|
||||
editorSectionWidget.Text = selectedItem.Name ?? selectedItemType.Name;
|
||||
|
||||
HashSet<IObjectEditor> mappedEditors = ApplicationController.Instance.Extensions.GetEditorsForType(selectedItemType);
|
||||
HashSet<Func<ThemeConfig, UndoBuffer, IObjectEditor>> mappedEditors = ApplicationController.Instance.EditorExtensions.GetEditorsForType(selectedItemType);
|
||||
|
||||
var undoBuffer = sceneContext.Scene.UndoBuffer;
|
||||
|
||||
|
|
@ -310,9 +310,9 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
else
|
||||
{
|
||||
if (item != null
|
||||
&& ApplicationController.Instance.Extensions.GetEditorsForType(item.GetType())?.FirstOrDefault() is IObjectEditor editor)
|
||||
&& ApplicationController.Instance.EditorExtensions.GetEditorsForType(item.GetType())?.FirstOrDefault() is Func<ThemeConfig, UndoBuffer, IObjectEditor> editorFactory)
|
||||
{
|
||||
ShowObjectEditor((editor, item, item.Name), selectedItem);
|
||||
ShowObjectEditor((editorFactory.Invoke(theme, undoBuffer), item, item.Name), selectedItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -559,9 +559,9 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
{
|
||||
if (instance is IObject3D object3D)
|
||||
{
|
||||
if (ApplicationController.Instance.Extensions.GetEditorsForType(object3D.GetType())?.FirstOrDefault() is IObjectEditor editor)
|
||||
if (ApplicationController.Instance.EditorExtensions.GetEditorsForType(object3D.GetType())?.FirstOrDefault() is Func<ThemeConfig, UndoBuffer, IObjectEditor> editorFactory)
|
||||
{
|
||||
ShowObjectEditor((editor, object3D, object3D.Name), selectedItem);
|
||||
ShowObjectEditor((editorFactory.Invoke(theme, undoBuffer), object3D, object3D.Name), selectedItem);
|
||||
}
|
||||
}
|
||||
else if (JsonPathContext.ReflectionValueSystem.LastMemberValue is ReflectionTarget reflectionTarget)
|
||||
|
|
@ -577,7 +577,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
|
||||
var editableProperty = new EditableProperty(reflectionTarget.PropertyInfo, reflectionTarget.Source);
|
||||
|
||||
var editor = PropertyEditor.CreatePropertyEditor(rows, editableProperty, undoBuffer, context, theme);
|
||||
var propertyEditor = new PropertyEditor(theme, undoBuffer);
|
||||
var editor = propertyEditor.CreatePropertyEditor(editableProperty, undoBuffer, context, theme);
|
||||
if (editor != null)
|
||||
{
|
||||
editorPanel.AddChild(editor);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue