diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2019-05-06 00:37:48 +0200 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2019-05-06 00:37:48 +0200 |
| commit | 09abcce174f8dc4e612f5cd98b07dffced5b38cd (patch) | |
| tree | f7c1c60b81cba6e05fafc5719dc9a21f9f4ed50e /Samples/CrowIDE/src/MemberView | |
| parent | e2f434f35a86a30962f2aebb36fcf59c9250838d (diff) | |
wip
Diffstat (limited to 'Samples/CrowIDE/src/MemberView')
| -rw-r--r-- | Samples/CrowIDE/src/MemberView/CategoryContainer.cs | 65 | ||||
| -rw-r--r-- | Samples/CrowIDE/src/MemberView/MembersView.cs | 139 | ||||
| -rw-r--r-- | Samples/CrowIDE/src/MemberView/PropertyContainer.cs | 222 |
3 files changed, 426 insertions, 0 deletions
diff --git a/Samples/CrowIDE/src/MemberView/CategoryContainer.cs b/Samples/CrowIDE/src/MemberView/CategoryContainer.cs new file mode 100644 index 00000000..fbf3fe2c --- /dev/null +++ b/Samples/CrowIDE/src/MemberView/CategoryContainer.cs @@ -0,0 +1,65 @@ +// +// CategoryContainer.cs +// +// Author: +// Jean-Philippe Bruyère <jp_bruyere@hotmail.com> +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace Crow.Coding +{ + public class CategoryContainer : IValueChange + { + #region IValueChange implementation + public event EventHandler<ValueChangeEventArgs> ValueChanged; + public virtual void NotifyValueChanged(string MemberName, object _value) + { + ValueChanged.Raise(this, new ValueChangeEventArgs(MemberName, _value)); + } + #endregion + + bool _isExpanded = true; + + public PropertyContainer[] Properties; + public string Name; + + public bool IsExpanded + { + get { return _isExpanded; } + set + { + if (value == _isExpanded) + return; + + _isExpanded = value; + + NotifyValueChanged ("IsExpanded", _isExpanded); + } + } + + public CategoryContainer (string categoryName, PropertyContainer[] properties){ + Name = categoryName; + Properties = properties; + } + } +} + diff --git a/Samples/CrowIDE/src/MemberView/MembersView.cs b/Samples/CrowIDE/src/MemberView/MembersView.cs new file mode 100644 index 00000000..b8dad3d0 --- /dev/null +++ b/Samples/CrowIDE/src/MemberView/MembersView.cs @@ -0,0 +1,139 @@ +// +// MembersView.cs +// +// Author: +// Jean-Philippe Bruyère <jp.bruyere@hotmail.com> +// +// Copyright (c) 2016 jp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +using System; +using Crow; +using System.Xml.Serialization; +using System.ComponentModel; +using System.Reflection; +using System.Collections.Generic; +using System.Linq; + +namespace Crow.Coding +{ + public class MembersView : ListBox + { + object instance; + ImlProjectItem projFile; + + public MembersView () : base() {} + + //cache property containers per type + //Dictionary<string,PropertyContainer[]> propContainersCache = new Dictionary<string, PropertyContainer[]>(); + Dictionary<string,List<CategoryContainer>> categoryContainersCache = new Dictionary<string,List<CategoryContainer>> (); + + [DefaultValue(null)] + public virtual object Instance { + get { return instance; } + set { + if (instance == value) + return; + object lastInst = instance; + + instance = value; + NotifyValueChanged ("Instance", instance); + + if (Instance is Widget) { + NotifyValueChanged ("SelectedItemName", Instance.GetType().Name + (Instance as Widget).design_id + + ":" + (Instance as Widget).design_imlPath ); + }else + NotifyValueChanged ("SelectedItemName", ""); + + if (instance == null) { + Data = null; + return; + } + + Type it = instance.GetType (); + if (!categoryContainersCache.ContainsKey (it.FullName)) { + MemberInfo[] members = it.GetMembers (BindingFlags.Public | BindingFlags.Instance); + List<PropertyContainer> props = new List<PropertyContainer> (); + foreach (MemberInfo m in members) { + if (m.MemberType == MemberTypes.Property) { + PropertyInfo pi = m as PropertyInfo; + if (!pi.CanWrite) + continue; + if (pi.GetCustomAttribute (typeof(XmlIgnoreAttribute)) != null) + continue; + props.Add (new PropertyContainer (this, pi)); + } + } + //propContainersCache.Add (it.FullName, props.OrderBy (p => p.Name).ToArray ()); + List<CategoryContainer> categories = new List<CategoryContainer> (); + + foreach (IGrouping<string,PropertyContainer> ig in props.OrderBy (p => p.Name).GroupBy(pc=>pc.DesignCategory)) { + categories.Add(new CategoryContainer(ig.Key, ig.ToArray())); + } + categoryContainersCache.Add (it.FullName, categories); + } + + + Data = categoryContainersCache[it.FullName]; + + if (lastInst != instance) { + foreach (CategoryContainer cc in categoryContainersCache [it.FullName]) { + foreach (PropertyContainer pc in cc.Properties) { + pc.NotifyValueChanged ("Value", pc.Value); + pc.NotifyValueChanged ("LabForeground", pc.LabForeground); + } + } + } + } + } + public ImlProjectItem ProjectNode { + get { return projFile; } + set { + if (projFile == value) + return; + +// if (projFile != null) +// projFile.UnregisterEditor (this); + + projFile = value; + +// if (projFile != null) +// projFile.RegisterEditor (this); + + NotifyValueChanged ("ProjectNode", projFile); + } + } + +// public void updateSource () { +// if (projFile == null) +// return; +// projFile.UpdateSource (this, (Instance as GraphicObject).GetIML ()); +// } + +// public override void Paint (ref Context ctx) +// { +// base.Paint (ref ctx); +// +// if (SelectedIndex < 0) +// return; +// +// Rectangle r = Parent.ContextCoordinates(Items [SelectedIndex].Slot); +// ctx.SetSourceRGB (0, 0, 1); +// ctx.Rectangle (r); +// ctx.LineWidth = 2; +// ctx.Stroke (); +// } + + } +} diff --git a/Samples/CrowIDE/src/MemberView/PropertyContainer.cs b/Samples/CrowIDE/src/MemberView/PropertyContainer.cs new file mode 100644 index 00000000..4d043ab4 --- /dev/null +++ b/Samples/CrowIDE/src/MemberView/PropertyContainer.cs @@ -0,0 +1,222 @@ +// +// PropertyContainer.cs +// +// Author: +// Jean-Philippe Bruyère <jp_bruyere@hotmail.com> +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Reflection; +using System.Linq; +using System.Collections.Generic; +using System.Diagnostics; +using System.ComponentModel; + +namespace Crow.Coding +{ + public class PropertyContainer : IValueChange + { + #region IValueChange implementation + public event EventHandler<ValueChangeEventArgs> ValueChanged; + public virtual void NotifyValueChanged(string MemberName, object _value) + { + ValueChanged.Raise(this, new ValueChangeEventArgs(MemberName, _value)); + } + #endregion + + PropertyInfo pi; + MembersView mview; + Command cmdReset, cmdGoToStyle; + + public List<Crow.Command> Commands; + + #region CTOR + public PropertyContainer(MembersView mv, PropertyInfo prop){ + mview = mv; + pi = prop; + + cmdReset = new Crow.Command (new Action (() => Reset ())) { Caption = "Reset to default" }; + cmdGoToStyle = new Crow.Command (new Action (() => GotoStyle ())) { Caption = "Goto style" }; + + Commands = new List<Crow.Command> (new Crow.Command[] { cmdReset, cmdGoToStyle }); + } + #endregion + + public string DesignCategory { + get { + DesignCategory dca = (DesignCategory)pi.GetCustomAttribute (typeof(DesignCategory)); + return dca == null ? "Divers" : dca.Name; + } + } + public string Name { get { return pi.Name; }} + public object Value { + get { + return mview.ProjectNode?.SelectedItem == null ? null : pi.GetValue(mview.ProjectNode.SelectedItem); + } + set { + try { + if (value == Value) + return; + Widget g = Instance; + string valstr = null, oldval = null; + + if (value != null) + valstr = value.ToString(); + + if (HasStyling) + oldval = g.design_style_values[Name]; + else if (HasDefaultValue) + oldval = DefaultValue?.ToString(); + else if (IsSetByIML) + oldval = g.design_iml_values [Name]; + + if (valstr == oldval){ + if (IsSetByIML){ + g.design_iml_values.Remove(Name); + Debug.WriteLine("iml attrib removed {0}.{1}", g.Name, Name); + }else + return; + }else{ + if (IsSetByIML){ + g.design_iml_values [Name] = valstr; + Debug.WriteLine("iml update {0}.{1} = {2}", g.Name, Name, valstr); + }else{ + g.design_iml_values.Add(Name,valstr); + Debug.WriteLine("iml add {0}.{1} = {2}", g.Name, Name, valstr); + } + } + + if (!pi.PropertyType.IsAssignableFrom(value.GetType()) && pi.PropertyType != typeof(string)){ + if (pi.PropertyType.IsEnum) { + if (value is string) { + pi.SetValue (g, Enum.Parse (pi.PropertyType, (string)value)); + }else + pi.SetValue (g, value); + } else { + MethodInfo me = pi.PropertyType.GetMethod + ("Parse", BindingFlags.Static | BindingFlags.Public, + System.Type.DefaultBinder, new Type [] {typeof (string)},null); + pi.SetValue (g, me.Invoke (null, new object[] { value }), null); + } + }else + pi.SetValue(g, value); + + Debug.WriteLine("\t\tPropContainer set design_dirty to instance"); + + mview.ProjectNode.Instance.design_HasChanged = true; + NotifyValueChanged ("Value", value); + NotifyValueChanged ("LabForeground", LabForeground); + } catch (Exception ex) { + Debug.WriteLine ("Error setting property:"+ ex.ToString()); + } + // + } + } + /// <summary> + /// for style attribute which is a string, return Style as type + /// </summary> + public string Type { get { return pi.PropertyType.IsEnum ? + "System.Enum" + : pi.Name == "Style" ? "Style" : pi.PropertyType.FullName; }} + + public object[] Choices { + get { + return pi.PropertyType.IsEnum ? + Enum.GetValues (pi.PropertyType).Cast<object>().ToArray() : + mview.ProjectNode.Project.solution.AvailaibleStyles; + } + } + /// <summary> + /// Current graphicobject instance + /// </summary> + public Widget Instance { + get { return mview.ProjectNode.SelectedItem as Widget; } + } + public object DefaultValue { + get { return ((DefaultValueAttribute)(pi.GetCustomAttribute (typeof (DefaultValueAttribute)))).Value; } + } + public bool HasDefaultValue { + get { return pi.GetCustomAttribute (typeof(DefaultValueAttribute))!=null; } + } + /// <summary> + /// return true if current value comes from IML attributes + /// </summary> + public bool IsSetByIML { + get { return Instance.design_iml_values.ContainsKey (Name); } + } + /// <summary> + /// return true if member default value comes from style + /// </summary> + public bool HasStyling { + get { return Instance.design_style_locations.ContainsKey(Name); } + } + /// <summary> + /// Return true if current value comes from styling + /// </summary> + public bool IsSetByStyling { + get { return IsSetByIML ? false : HasStyling; } + } + + + public Fill LabForeground { + get { return IsSetByIML ? Color.DarkBlue : HasStyling ? Color.Black : Color.Grey;} + } + + /// <summary> + /// reset to default value + /// </summary> + public void Reset () { + Widget inst = mview.ProjectNode.SelectedItem as Widget; + if (!inst.design_iml_values.ContainsKey (Name)) + return; + inst.design_iml_values.Remove (Name); + + NotifyValueChanged ("LabForeground", LabForeground); + mview.ProjectNode.UpdateSource(this, mview.ProjectNode.Instance.GetIML()); + //mview.ProjectNode.Instance.design_HasChanged = true; + //should reinstantiate to get default + } + public void GotoStyle(){ + Widget g = Instance; + if (!g.design_style_locations.ContainsKey (Name)) + return; + FileLocation fl = g.design_style_locations [Name]; + ProjectFile pf; + if (!mview.ProjectNode.Project.TryGetProjectFileFromPath ("#" + fl.FilePath, out pf)) + return; + + if (!pf.IsOpened) + pf.Open (); + + pf.CurrentLine = fl.Line; + pf.CurrentColumn = fl.Column; + + pf.IsSelected = true; + + } + + public override string ToString () + { + return string.Format ("{0} = {1}", Name, Value); + } + } +} + |