Index: src/DeltaShell/DeltaShell.Gui/DeltaShell.Gui.csproj
===================================================================
diff -u -r7311da16a34bc2588440d0166f3a09402e4fd16f -r50d4f9e34ad8050478c2d63675b1f17a376fb43d
--- src/DeltaShell/DeltaShell.Gui/DeltaShell.Gui.csproj (.../DeltaShell.Gui.csproj) (revision 7311da16a34bc2588440d0166f3a09402e4fd16f)
+++ src/DeltaShell/DeltaShell.Gui/DeltaShell.Gui.csproj (.../DeltaShell.Gui.csproj) (revision 50d4f9e34ad8050478c2d63675b1f17a376fb43d)
@@ -140,6 +140,9 @@
ProgressDialog.cs
+
+ Component
+
SplashScreen.xaml
@@ -184,12 +187,6 @@
OptionsDialog.cs
-
- UserControl
-
-
- PropertyGrid.cs
-
UserControl
@@ -490,10 +487,6 @@
ProgressDialog.cs
-
- PropertyGrid.cs
- Designer
-
ViewSelectionContextMenuController.cs
Designer
Index: src/DeltaShell/DeltaShell.Gui/Forms/MainWindow/MainWindow.xaml.cs
===================================================================
diff -u -rb301f31bca6957a9326b4b0ab912bd7b5da60195 -r50d4f9e34ad8050478c2d63675b1f17a376fb43d
--- src/DeltaShell/DeltaShell.Gui/Forms/MainWindow/MainWindow.xaml.cs (.../MainWindow.xaml.cs) (revision b301f31bca6957a9326b4b0ab912bd7b5da60195)
+++ src/DeltaShell/DeltaShell.Gui/Forms/MainWindow/MainWindow.xaml.cs (.../MainWindow.xaml.cs) (revision 50d4f9e34ad8050478c2d63675b1f17a376fb43d)
@@ -62,7 +62,7 @@
private bool resetDefaultLayout;
private MessageWindow.MessageWindow messageWindow;
- private PropertyGrid.PropertyGrid propertyGrid;
+ private PropertyGridView propertyGrid;
private WindowInteropHelper windowInteropHelper;
private IEnumerable ribbonCommandHandlers;
@@ -267,7 +267,7 @@
{
if ((propertyGrid == null) || (propertyGrid.IsDisposed))
{
- propertyGrid = new PropertyGrid.PropertyGrid(Gui);
+ propertyGrid = new PropertyGridView(Gui);
}
propertyGrid.Text = Properties.Resources.Properties;
Fisheye: Tag 50d4f9e34ad8050478c2d63675b1f17a376fb43d refers to a dead (removed) revision in file `src/DeltaShell/DeltaShell.Gui/Forms/PropertyGrid/PropertyGrid.Designer.cs'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 50d4f9e34ad8050478c2d63675b1f17a376fb43d refers to a dead (removed) revision in file `src/DeltaShell/DeltaShell.Gui/Forms/PropertyGrid/PropertyGrid.cs'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 50d4f9e34ad8050478c2d63675b1f17a376fb43d refers to a dead (removed) revision in file `src/DeltaShell/DeltaShell.Gui/Forms/PropertyGrid/PropertyGrid.resx'.
Fisheye: No comparison available. Pass `N' to diff?
Index: src/DeltaShell/DeltaShell.Gui/PropertyGridView.cs
===================================================================
diff -u
--- src/DeltaShell/DeltaShell.Gui/PropertyGridView.cs (revision 0)
+++ src/DeltaShell/DeltaShell.Gui/PropertyGridView.cs (revision 50d4f9e34ad8050478c2d63675b1f17a376fb43d)
@@ -0,0 +1,352 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Security.Permissions;
+using System.Windows.Forms;
+using DelftTools.Controls;
+using DelftTools.Shell.Core;
+using DelftTools.Shell.Gui;
+using DelftTools.Shell.Gui.Forms;
+using DelftTools.Utils.PropertyBag.Dynamic;
+using DeltaShell.Gui.Properties;
+using log4net;
+
+namespace DeltaShell.Gui
+{
+ public class PropertyGridView : System.Windows.Forms.PropertyGrid, IPropertyGrid, IObserver
+ {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(PropertyGridView));
+
+ ///
+ /// todo: This is still an unwanted dependency. PropertyGrid uses gui to subscribe to the SelectionChanged
+ /// delegate and in responce queries the gui.Selection
+ /// nicer? : custom public delegate in IPropertyGrid with selection as parameter
+ ///
+ private readonly IGui gui;
+
+ private object selectedObject;
+ private IObservable observableProperty;
+
+ public PropertyGridView(IGui gui)
+ {
+// InitializeComponent();
+ HideTabsButton();
+
+ this.gui = gui;
+
+ gui.SelectionChanged += GuiSelectionChanged;
+ }
+
+ public new object SelectedObject
+ {
+ get
+ {
+ return selectedObject;
+ }
+ set
+ {
+ // Performance optimization
+ if (selectedObject == value)
+ {
+ return;
+ }
+
+ selectedObject = value;
+
+ OnSelectedObjectChanged();
+ }
+ }
+
+// public override void Refresh()
+// {
+// Refresh();
+// }
+
+ public void UpdateObserver()
+ {
+ Refresh();
+ }
+
+ public object GetObjectProperties(object sourceData)
+ {
+ if (sourceData == null)
+ {
+ return null;
+ }
+
+ // Obtain all property information
+ var propertyInfos = gui.Plugins.SelectMany(p => p.GetPropertyInfos()).ToList();
+
+ // 1. Match property information based on ObjectType and on AdditionalDataCheck
+ propertyInfos = propertyInfos.Where(pi => pi.ObjectType.IsInstanceOfType(sourceData) && (pi.AdditionalDataCheck == null || pi.AdditionalDataCheck(sourceData))).ToList();
+
+ // 2. Match property information based on object type inheritance
+ propertyInfos = FilterPropertyInfoByTypeInheritance(propertyInfos, pi => pi.ObjectType);
+
+ // 3. Match property information based on property type inheritance
+ propertyInfos = FilterPropertyInfoByTypeInheritance(propertyInfos, pi => pi.PropertyType);
+
+ if (propertyInfos.Count == 0)
+ {
+ // No (or multiple) object properties found: return 'null' so that no object properties are shown in the property grid
+ return null;
+ }
+
+ if (propertyInfos.Count > 1)
+ {
+ // 4. We assume that the propertyInfos with AdditionalDataCheck are the most specific
+ propertyInfos = propertyInfos.Where(pi => pi.AdditionalDataCheck != null).ToList();
+ }
+
+ if (propertyInfos.Count == 1)
+ {
+ return CreateObjectProperties(propertyInfos.ElementAt(0), sourceData);
+ }
+
+ Log.Debug(Resources.PropertyGrid_GetObjectProperties_Multiple_object_property_instances_found_for_the_same_data_object__no_object_properties_are_displayed_in_the_property_grid);
+ return null;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (gui != null)
+ {
+ gui.SelectionChanged -= GuiSelectionChanged;
+ }
+
+ if (observableProperty != null)
+ {
+ observableProperty.Detach(this);
+ }
+
+ base.Dispose(disposing);
+ }
+
+ private void HideTabsButton()
+ {
+ // removing "property tabs" button and separator before it
+ // TODO: case we used derived functionality for this?
+ var strip = Controls.OfType().ToList()[0];
+ strip.Items[3].Visible = false;
+ strip.Items[4].Visible = false;
+ }
+
+ private void GuiSelectionChanged(object sender, EventArgs e)
+ {
+ if (observableProperty != null)
+ {
+ observableProperty.Detach(this);
+ }
+
+ var selection = gui.Selection;
+ if (selection == null)
+ {
+ SelectedObject = null;
+ return;
+ }
+
+ observableProperty = selection as IObservable;
+ if (observableProperty != null)
+ {
+ observableProperty.Attach(this);
+ }
+
+ SelectedObject = GetObjectProperties(selection);
+ }
+
+ private List FilterPropertyInfoByTypeInheritance(List propertyInfo, Func getTypeAction)
+ {
+ var propertyInfoCount = propertyInfo.Count;
+ var propertyInfoWithUnInheritedType = propertyInfo.ToList();
+
+ for (var i = 0; i < propertyInfoCount; i++)
+ {
+ var firstType = getTypeAction(propertyInfo.ElementAt(i));
+
+ for (var j = 0; j < propertyInfoCount; j++)
+ {
+ if (i == j)
+ {
+ continue;
+ }
+
+ var secondType = getTypeAction(propertyInfo.ElementAt(j));
+
+ if (firstType != secondType && firstType.IsAssignableFrom(secondType))
+ {
+ propertyInfoWithUnInheritedType.Remove(propertyInfo.ElementAt(i));
+
+ break;
+ }
+ }
+ }
+
+ return propertyInfoWithUnInheritedType.Any()
+ ? propertyInfoWithUnInheritedType.ToList() // One or more specific property information objects found: return the filtered list
+ : propertyInfo; // No specific property information found: return the original list
+ }
+
+ private object CreateObjectProperties(PropertyInfo propertyInfo, object sourceData)
+ {
+ try
+ {
+ // Try to create object properties for the source data
+ var objectProperties = propertyInfo.CreateObjectProperties(sourceData);
+
+ // Return a dynamic property bag containing the created object properties
+ return objectProperties is DynamicPropertyBag
+ ? (object) objectProperties
+ : new DynamicPropertyBag(objectProperties);
+ }
+ catch (Exception)
+ {
+ Log.Debug(Resources.PropertyGrid_CreateObjectProperties_Could_not_create_object_properties_for_the_data);
+
+ // Directly return the source data (TODO: Shouldn't we return "null" instead?)
+ return sourceData;
+ }
+ }
+
+ ///
+ /// If the selected objects changed rebuild the internal dictionary that counts the number of
+ /// objects of each type.
+ ///
+ private void OnSelectedObjectChanged()
+ {
+ if (SelectedObject == null)
+ {
+ base.SelectedObject = null;
+ return;
+ }
+
+ var selectedType = GetRelevantType(SelectedObject);
+
+ Log.DebugFormat(Resources.PropertyGrid_OnSelectedObjectsChanged_Selected_object_of_type___0_, selectedType.Name);
+
+ base.SelectedObject = SelectedObject;
+ }
+
+ private static Type GetRelevantType(object obj)
+ {
+ if (obj is DynamicPropertyBag)
+ {
+ var bag = obj as DynamicPropertyBag;
+ return bag.GetContentType();
+ }
+ return obj.GetType();
+ }
+
+ #region IPropertyGrid Members
+
+ public object Data
+ {
+ get
+ {
+ return SelectedObject;
+ }
+ set
+ {
+ SelectedObject = value;
+ }
+ }
+
+ public Image Image
+ {
+ get
+ {
+ return Resources.PropertiesHS;
+ }
+ set {}
+ }
+
+ public void EnsureVisible(object item) {}
+
+ public ViewInfo ViewInfo { get; set; }
+
+ #endregion
+
+ #region Enable tab key navigation on property grid
+
+ ///
+ /// Do special processing for Tab key.
+ /// http://www.codeproject.com/csharp/wdzPropertyGridUtils.asp
+ ///
+ ///
+ ///
+ ///
+ [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
+ protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
+ {
+ if ((keyData == Keys.Tab) || (keyData == (Keys.Tab | Keys.Shift)))
+ {
+ var selectedItem = SelectedGridItem;
+ var root = selectedItem;
+ if (selectedItem == null)
+ {
+ return false;
+ }
+ while (root.Parent != null)
+ {
+ root = root.Parent;
+ }
+ // Find all expanded items and put them in a list.
+ var items = new ArrayList();
+ AddExpandedItems(root, items);
+
+ // Find selectedItem.
+ int foundIndex = items.IndexOf(selectedItem);
+ if ((keyData & Keys.Shift) == Keys.Shift)
+ {
+ foundIndex--;
+ if (foundIndex < 0)
+ {
+ foundIndex = items.Count - 1;
+ }
+ SelectedGridItem = (GridItem) items[foundIndex];
+ if (SelectedGridItem.GridItems.Count > 0)
+ {
+ SelectedGridItem.Expanded = false;
+ }
+ }
+ else
+ {
+ foundIndex++;
+ if (items.Count > 0)
+ {
+ if (foundIndex >= items.Count)
+ {
+ foundIndex = 0;
+ }
+ SelectedGridItem = (GridItem) items[foundIndex];
+ }
+ if (SelectedGridItem.GridItems.Count > 0)
+ {
+ SelectedGridItem.Expanded = true;
+ }
+ }
+
+ return true;
+ }
+ return base.ProcessCmdKey(ref msg, keyData);
+ }
+
+ private static void AddExpandedItems(GridItem parent, IList items)
+ {
+ if (parent.PropertyDescriptor != null)
+ {
+ items.Add(parent);
+ }
+ if (parent.Expanded)
+ {
+ foreach (GridItem child in parent.GridItems)
+ {
+ AddExpandedItems(child, items);
+ }
+ }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
Index: test/DeltaShell/DeltaShell.Tests/DeltaShell.Tests.csproj
===================================================================
diff -u -r6dbce7d02bbc8849c767bf7963df7127a98c2897 -r50d4f9e34ad8050478c2d63675b1f17a376fb43d
--- test/DeltaShell/DeltaShell.Tests/DeltaShell.Tests.csproj (.../DeltaShell.Tests.csproj) (revision 6dbce7d02bbc8849c767bf7963df7127a98c2897)
+++ test/DeltaShell/DeltaShell.Tests/DeltaShell.Tests.csproj (.../DeltaShell.Tests.csproj) (revision 50d4f9e34ad8050478c2d63675b1f17a376fb43d)
@@ -48,6 +48,10 @@
true
+
+ False
+ ..\..\..\lib\DevExpress.Utils.v9.3.dll
+
False
..\..\..\lib\log4net.dll
Index: test/DeltaShell/DeltaShell.Tests/Gui/Forms/PropertyGrid/PropertyGridTest.cs
===================================================================
diff -u -r5fc71a385897af92ccb092f2f969b5709afab85a -r50d4f9e34ad8050478c2d63675b1f17a376fb43d
--- test/DeltaShell/DeltaShell.Tests/Gui/Forms/PropertyGrid/PropertyGridTest.cs (.../PropertyGridTest.cs) (revision 5fc71a385897af92ccb092f2f969b5709afab85a)
+++ test/DeltaShell/DeltaShell.Tests/Gui/Forms/PropertyGrid/PropertyGridTest.cs (.../PropertyGridTest.cs) (revision 50d4f9e34ad8050478c2d63675b1f17a376fb43d)
@@ -25,7 +25,7 @@
mocks.ReplayAll();
- var propertyGrid = new DeltaShell.Gui.Forms.PropertyGrid.PropertyGrid(gui);
+ var propertyGrid = new PropertyGridView(gui);
var objectProperties = propertyGrid.GetObjectProperties(1.0);
Assert.IsNull(objectProperties);
@@ -52,7 +52,7 @@
mocks.ReplayAll();
- var propertyGrid = new DeltaShell.Gui.Forms.PropertyGrid.PropertyGrid(gui);
+ var propertyGrid = new PropertyGridView(gui);
var objectProperties = propertyGrid.GetObjectProperties(new A());
Assert.IsTrue(objectProperties is DynamicPropertyBag);
@@ -83,7 +83,7 @@
mocks.ReplayAll();
- var propertyGrid = new DeltaShell.Gui.Forms.PropertyGrid.PropertyGrid(gui);
+ var propertyGrid = new PropertyGridView(gui);
var objectProperties = propertyGrid.GetObjectProperties(new A());
Assert.IsNull(objectProperties);
@@ -120,7 +120,7 @@
mocks.ReplayAll();
- var propertyGrid = new DeltaShell.Gui.Forms.PropertyGrid.PropertyGrid(gui);
+ var propertyGrid = new PropertyGridView(gui);
var objectProperties = propertyGrid.GetObjectProperties(new C()); //we ask for C
Assert.AreSame(typeof(SimpleProperties),
@@ -149,7 +149,7 @@
mocks.ReplayAll();
- var propertyGrid = new DeltaShell.Gui.Forms.PropertyGrid.PropertyGrid(gui);
+ var propertyGrid = new PropertyGridView(gui);
var objectProperties = propertyGrid.GetObjectProperties(new D());
Assert.IsTrue(objectProperties is DynamicPropertyBag);
@@ -178,7 +178,7 @@
mocks.ReplayAll();
- var propertyGrid = new DeltaShell.Gui.Forms.PropertyGrid.PropertyGrid(gui);
+ var propertyGrid = new PropertyGridView(gui);
var objectProperties = propertyGrid.GetObjectProperties(new D());
Assert.IsTrue(objectProperties is DynamicPropertyBag);
@@ -213,7 +213,7 @@
mocks.ReplayAll();
- var propertyGrid = new DeltaShell.Gui.Forms.PropertyGrid.PropertyGrid(gui);
+ var propertyGrid = new PropertyGridView(gui);
var objectProperties = propertyGrid.GetObjectProperties(new D());
Assert.IsTrue(objectProperties is DynamicPropertyBag);
@@ -241,7 +241,7 @@
mocks.ReplayAll();
- var propertyGrid = new DeltaShell.Gui.Forms.PropertyGrid.PropertyGrid(gui);
+ var propertyGrid = new PropertyGridView(gui);
var objectProperties = propertyGrid.GetObjectProperties(new B());
Assert.IsTrue(objectProperties is DynamicPropertyBag);
@@ -273,7 +273,7 @@
mocks.ReplayAll();
- var propertyGrid = new DeltaShell.Gui.Forms.PropertyGrid.PropertyGrid(gui);
+ var propertyGrid = new PropertyGridView(gui);
var objectProperties = propertyGrid.GetObjectProperties(new B());
Assert.IsTrue(objectProperties is DynamicPropertyBag);
@@ -303,7 +303,7 @@
mocks.ReplayAll();
- var propertyGrid = new DeltaShell.Gui.Forms.PropertyGrid.PropertyGrid(gui);
+ var propertyGrid = new PropertyGridView(gui);
var objectProperties = propertyGrid.GetObjectProperties(new B());
Assert.IsTrue(objectProperties is DynamicPropertyBag);
@@ -337,7 +337,7 @@
mocks.ReplayAll();
- var propertyGrid = new DeltaShell.Gui.Forms.PropertyGrid.PropertyGrid(gui);
+ var propertyGrid = new PropertyGridView(gui);
var objectProperties = propertyGrid.GetObjectProperties(new B());
Assert.IsTrue(objectProperties is DynamicPropertyBag);
@@ -366,7 +366,7 @@
mocks.ReplayAll();
object propertyObject = new B();
- var propertyGrid = new DeltaShell.Gui.Forms.PropertyGrid.PropertyGrid(gui);
+ var propertyGrid = new PropertyGridView(gui);
TestHelper.AssertLogMessageIsGenerated(() => propertyObject = propertyGrid.GetObjectProperties(new B()), "Multiple object property instances found for the same data object: no object properties are displayed in the property grid");
@@ -411,7 +411,7 @@
mocks.ReplayAll();
- var propertyGrid = new DeltaShell.Gui.Forms.PropertyGrid.PropertyGrid(gui);
+ var propertyGrid = new PropertyGridView(gui);
var objectProperties = propertyGrid.GetObjectProperties(new C());
Assert.IsTrue(objectProperties is DynamicPropertyBag);