initial src code import
parent
b3f807c521
commit
29aa7d229a
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
|
||||
<appSettings>
|
||||
<add key="fimAddress" value="http://localhost"/>
|
||||
<add key="fimUser" value="Administrator"/>
|
||||
<add key="fimPassword" value="pass"/>
|
||||
</appSettings>
|
||||
</configuration>
|
|
@ -0,0 +1,8 @@
|
|||
<Application x:Class="Predica.FimExplorer.UI.WPF.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
StartupUri="Main\MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
|
@ -0,0 +1,11 @@
|
|||
using System.Windows;
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Microsoft.ResourceManagement.ObjectModel;
|
||||
using System;
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF.Details
|
||||
{
|
||||
/// <summary>
|
||||
/// Selects hyperlink for references and normal text for other values
|
||||
/// </summary>
|
||||
public class DetailsValueCellTemplateSelector : DataTemplateSelector
|
||||
{
|
||||
public override DataTemplate SelectTemplate(object item, DependencyObject container)
|
||||
{
|
||||
var contentPresenter = (ContentPresenter)container;
|
||||
var attribute = (FlattenedAttribute)item;
|
||||
|
||||
if (attribute == null || attribute.ValueType.IsNot<RmReference>())
|
||||
{
|
||||
return (DataTemplate)contentPresenter.FindResource("normalCell");
|
||||
}
|
||||
else
|
||||
{
|
||||
return (DataTemplate)contentPresenter.FindResource("referenceCell");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.ResourceManagement.ObjectModel;
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF.Details
|
||||
{
|
||||
public class FlattenedAttribute
|
||||
{
|
||||
private readonly KeyValuePair<RmAttributeName, RmAttributeValue> _attributeDescrpition;
|
||||
|
||||
public string AttributeName { get { return _attributeDescrpition.Key.Name; } }
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return _attributeDescrpition.Value.Value == null
|
||||
? string.Empty
|
||||
: _attributeDescrpition.Value.Value.ToString();
|
||||
}
|
||||
}
|
||||
public Type ValueType
|
||||
{
|
||||
get
|
||||
{
|
||||
return _attributeDescrpition.Value.Value == null
|
||||
? null
|
||||
: _attributeDescrpition.Value.Value.GetType();
|
||||
}
|
||||
}
|
||||
public string ValueTypeName
|
||||
{
|
||||
get
|
||||
{
|
||||
return _attributeDescrpition.Value.Value == null
|
||||
? string.Empty
|
||||
: _attributeDescrpition.Value.Value.GetType().Name;
|
||||
}
|
||||
}
|
||||
|
||||
public FlattenedAttribute(KeyValuePair<RmAttributeName, RmAttributeValue> attributeDescrpition)
|
||||
{
|
||||
_attributeDescrpition = attributeDescrpition;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.ResourceManagement.ObjectModel;
|
||||
using Predica.FimCommunication;
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF.Details
|
||||
{
|
||||
public class ObjectDetailsModel
|
||||
{
|
||||
private readonly IFimClient _fimClient;
|
||||
private readonly WindowsManager _windowsManager;
|
||||
|
||||
public RmResource Resource { get; set; }
|
||||
public IEnumerable<FlattenedAttribute> Attributes { get; set; }
|
||||
|
||||
public string ResourceForWindowTitle
|
||||
{
|
||||
get
|
||||
{
|
||||
return "[{0}] {1} ({2})".FormatWith(Resource.ObjectType, Resource.DisplayName, Resource.ObjectID);
|
||||
}
|
||||
}
|
||||
|
||||
public ObjectDetailsModel(RmResource resource, IFimClient fimClient, WindowsManager windowsManager)
|
||||
{
|
||||
_fimClient = fimClient;
|
||||
_windowsManager = windowsManager;
|
||||
|
||||
Resource = resource;
|
||||
|
||||
Attributes = resource.Attributes
|
||||
.Select(x => new FlattenedAttribute(x))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public void ShowDetailsById(string id)
|
||||
{
|
||||
RmResource result = _fimClient.FindById(id);
|
||||
_windowsManager.ObjectDetailsDialog(result);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<Window x:Class="Predica.FimExplorer.UI.WPF.Details.ObjectDetailsWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:Predica.FimExplorer.UI.WPF.Details"
|
||||
Title="{Binding ResourceForWindowTitle}" Height="353" Width="632">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<local:DetailsValueCellTemplateSelector x:Key="valueCellTemplateSelector"></local:DetailsValueCellTemplateSelector>
|
||||
<DataTemplate x:Key="normalCell">
|
||||
<TextBlock Text="{Binding Value}"></TextBlock>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="referenceCell">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock><Hyperlink Click="Hyperlink_Click">
|
||||
<TextBlock Text="{Binding Value}"></TextBlock>
|
||||
</Hyperlink></TextBlock>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<DataGrid
|
||||
ItemsSource="{Binding Attributes}"
|
||||
SelectionUnit="Cell"
|
||||
AutoGenerateColumns="False"
|
||||
>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn
|
||||
Header="Name"
|
||||
Binding="{Binding AttributeName}"
|
||||
/>
|
||||
<DataGridTemplateColumn
|
||||
Header="Value"
|
||||
CellTemplateSelector="{StaticResource valueCellTemplateSelector}"
|
||||
CopyingCellClipboardContent="ValueColumn_CopyingCellClipboardContent"
|
||||
/>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</Window>
|
|
@ -0,0 +1,40 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Documents;
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF.Details
|
||||
{
|
||||
public partial class ObjectDetailsWindow : Window
|
||||
{
|
||||
private ObjectDetailsModel _model;
|
||||
|
||||
public ObjectDetailsWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void Initialize(ObjectDetailsModel model)
|
||||
{
|
||||
_model = model;
|
||||
this.DataContext = model;
|
||||
}
|
||||
|
||||
private void Hyperlink_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var textExtractor = new HyperlinkTextExtractor();
|
||||
string id = textExtractor.ExtractText((Hyperlink) e.Source);
|
||||
_model.ShowDetailsById(id);
|
||||
}
|
||||
|
||||
private void ValueColumn_CopyingCellClipboardContent(object sender, System.Windows.Controls.DataGridCellClipboardEventArgs e)
|
||||
{
|
||||
var attribute = e.Item as FlattenedAttribute;
|
||||
|
||||
if (attribute == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
e.Content = attribute.Value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
using System.Configuration;
|
||||
using System.Net;
|
||||
using Predica.FimCommunication;
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF
|
||||
{
|
||||
public class FimClientFactory
|
||||
{
|
||||
public static IFimClient CreateClient()
|
||||
{
|
||||
var url = ConfigurationManager.AppSettings["fimAddress"];
|
||||
var username = ConfigurationManager.AppSettings["fimUser"];
|
||||
var password = ConfigurationManager.AppSettings["fimPassword"];
|
||||
|
||||
return new FimClient(url, new NetworkCredential(username, password));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
using System;
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF
|
||||
{
|
||||
/// <summary>
|
||||
/// Extracts text contained in Hyperlink contaning TextBlock, wrapped in another TextBlock
|
||||
/// </summary>
|
||||
public class HyperlinkTextExtractor
|
||||
{
|
||||
public string ExtractText(Hyperlink hyperlink)
|
||||
{
|
||||
TextBlock textBlock = (TextBlock)hyperlink.Parent;
|
||||
|
||||
DependencyObject containerVisual = VisualTreeHelper.GetChild(textBlock, 0);
|
||||
DependencyObject contentPresenter = VisualTreeHelper.GetChild(containerVisual, 0);
|
||||
|
||||
var innerTextBlock = contentPresenter as TextBlock;
|
||||
|
||||
// true for link cells in main grid
|
||||
// false for link cells in details grid
|
||||
if (contentPresenter.GetType().IsNot<TextBlock>())
|
||||
{
|
||||
innerTextBlock = (TextBlock)VisualTreeHelper.GetChild(contentPresenter, 0);
|
||||
}
|
||||
|
||||
return innerTextBlock.Text;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
using Microsoft.ResourceManagement.ObjectModel;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using Predica.FimCommunication;
|
||||
using Predica.FimCommunication.Import;
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF.Import
|
||||
{
|
||||
public class ImportedObjectsModel : INotifyPropertyChanged
|
||||
{
|
||||
private readonly Stream _inputStream;
|
||||
private readonly IXmlImporter _xmlImporter;
|
||||
private readonly WindowsManager _windowsManager;
|
||||
|
||||
private ImportResult _importResult;
|
||||
|
||||
#region ImportedValues
|
||||
|
||||
private DataTable _importedValues;
|
||||
public DataTable ImportedValues
|
||||
{
|
||||
get { return _importedValues; }
|
||||
set
|
||||
{
|
||||
_importedValues = value;
|
||||
NotifyChanged("ImportedValues");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public ImportedObjectsModel(Stream inputStream, IXmlImporter xmlImporter, WindowsManager windowsManager)
|
||||
{
|
||||
_inputStream = inputStream;
|
||||
_xmlImporter = xmlImporter;
|
||||
_windowsManager = windowsManager;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_importResult = _xmlImporter.Import(_inputStream);
|
||||
|
||||
if (_importResult.PrimaryImportObjects.IsEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var table = new DataTable();
|
||||
|
||||
var resourceWithMostAttributes = _importResult.PrimaryImportObjects.OrderByDescending(x => x.Attributes.Count).First();
|
||||
|
||||
foreach (var attr in resourceWithMostAttributes.Attributes)
|
||||
{
|
||||
var column = table.Columns.Add(attr.Key.Name);
|
||||
|
||||
// window can detect references by their 'object' type as opposed to 'string' defined for all other fields
|
||||
if (resourceWithMostAttributes[attr.Key.Name].Value is RmReference)
|
||||
{
|
||||
column.DataType = typeof(object);
|
||||
}
|
||||
else
|
||||
{
|
||||
column.DataType = typeof(string);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
foreach (var importTarget in _importResult.PrimaryImportObjects)
|
||||
{
|
||||
var newRowValues = table.Columns.Cast<DataColumn>().Select(x =>
|
||||
{
|
||||
if (importTarget.Attributes.Keys.Any(y => y.Name == x.ColumnName))
|
||||
{
|
||||
return importTarget.Attributes.First(y => y.Key.Name == x.ColumnName).Value.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.ToArray();
|
||||
|
||||
table.Rows.Add(newRowValues);
|
||||
}
|
||||
|
||||
_log.Debug("Created {0}-column table with {1} imported rows", table.Columns.Count, table.Rows.Count);
|
||||
|
||||
ImportedValues = table;
|
||||
}
|
||||
|
||||
public void DetailsById(string id)
|
||||
{
|
||||
var obj = _importResult.AllImportedObjects.FirstOrDefault(x => x.ObjectID.Value == id);
|
||||
|
||||
if (obj == null)
|
||||
{
|
||||
_windowsManager.Error("Object with id {0} was not imported".FormatWith(id));
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.Debug("showing details of imported object {0}", id);
|
||||
_windowsManager.ObjectDetailsDialog(obj);
|
||||
}
|
||||
}
|
||||
|
||||
#region INotifyPropertyChanged
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged = delegate { };
|
||||
|
||||
private void NotifyChanged(string propertyName)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static readonly Logger _log = LogManager.GetCurrentClassLogger();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<Window x:Class="Predica.FimExplorer.UI.WPF.Import.ImportedObjectsWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="Imported objects" Height="300" Width="686">
|
||||
<Grid>
|
||||
<DataGrid
|
||||
IsReadOnly="True"
|
||||
ItemsSource="{Binding ImportedValues}"
|
||||
AutoGeneratingColumn="DataGrid_AutoGeneratingColumn"
|
||||
/>
|
||||
</Grid>
|
||||
</Window>
|
|
@ -0,0 +1,37 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF.Import
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ImportedObjectsWindow.xaml
|
||||
/// </summary>
|
||||
public partial class ImportedObjectsWindow : Window
|
||||
{
|
||||
ImportedObjectsModel _model;
|
||||
ReferenceColumnDetector _referenceColumnDetector;
|
||||
|
||||
public ImportedObjectsWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_referenceColumnDetector = new ReferenceColumnDetector();
|
||||
}
|
||||
|
||||
public void Initialize(ImportedObjectsModel model)
|
||||
{
|
||||
_model = model;
|
||||
this.DataContext = model;
|
||||
}
|
||||
|
||||
private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
|
||||
{
|
||||
// only references are marked as objects, all other are strings
|
||||
_referenceColumnDetector.ProcessAutogeneratedColumn<object>(e
|
||||
, id =>
|
||||
{
|
||||
_model.DetailsById(id);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,333 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.ResourceManagement.Client;
|
||||
using Microsoft.ResourceManagement.ObjectModel;
|
||||
using Microsoft.ResourceManagement.ObjectModel.ResourceTypes;
|
||||
using Predica.FimCommunication;
|
||||
using Predica.FimCommunication.Export;
|
||||
using Predica.FimCommunication.Querying;
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF.Main
|
||||
{
|
||||
public class MainModel : INotifyPropertyChanged
|
||||
{
|
||||
private readonly MainWindow _parent;
|
||||
private readonly IFimClient _fimClient;
|
||||
private readonly WindowsManager _windowsManager;
|
||||
private readonly IXmlExporter _xmlExporter;
|
||||
|
||||
#region Bound properties
|
||||
|
||||
#region XPath
|
||||
|
||||
private string _xPath;
|
||||
|
||||
public string XPath
|
||||
{
|
||||
get { return _xPath; }
|
||||
set
|
||||
{
|
||||
_xPath = value;
|
||||
NotifyChanged("XPath");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IdForSearch
|
||||
|
||||
private string _idForSearch;
|
||||
|
||||
public string IdForSearch
|
||||
{
|
||||
get { return _idForSearch; }
|
||||
set
|
||||
{
|
||||
_idForSearch = value;
|
||||
NotifyChanged("IdForSearch");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region QueriedValues
|
||||
|
||||
private DataTable _queriedValues;
|
||||
|
||||
public DataTable QueriedValues
|
||||
{
|
||||
get { return _queriedValues; }
|
||||
set
|
||||
{
|
||||
_queriedValues = value;
|
||||
NotifyChanged("QueriedValues");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SelectedObjectType
|
||||
|
||||
private RmObjectTypeDescription _selectedObjectType;
|
||||
|
||||
public RmObjectTypeDescription SelectedObjectType
|
||||
{
|
||||
get { return _selectedObjectType; }
|
||||
set
|
||||
{
|
||||
_selectedObjectType = value;
|
||||
XPath = "/" + value.Name;
|
||||
FetchAttributesForSelectedObjectType();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private DataRowView _selectedRow;
|
||||
public DataRowView SelectedRow
|
||||
{
|
||||
get { return _selectedRow; }
|
||||
set
|
||||
{
|
||||
_selectedRow = value;
|
||||
IdForSearch = _selectedRow["Resource ID"].ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<RmObjectTypeDescription> ObjectTypes { get; private set; }
|
||||
public ObservableCollection<SelectableAttribute> CurrentAttributes { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public MainModel(MainWindow parent, IFimClient fimClient, WindowsManager windowsManager, IXmlExporter xmlExporter)
|
||||
{
|
||||
_parent = parent;
|
||||
_fimClient = fimClient;
|
||||
_windowsManager = windowsManager;
|
||||
_xmlExporter = xmlExporter;
|
||||
|
||||
ObjectTypes = new ObservableCollection<RmObjectTypeDescription>();
|
||||
CurrentAttributes = new ObservableCollection<SelectableAttribute>();
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
FetchObjectTypes();
|
||||
|
||||
// cannot use ResourceTypeExtractor here - it is unable to extract type from RmResource
|
||||
SelectedObjectType = ObjectTypes.Single(x => x.Name == "Resource");
|
||||
}
|
||||
|
||||
#region Fetching object types
|
||||
|
||||
private void FetchObjectTypes()
|
||||
{
|
||||
_parent.LongRunningOperation(_parent.loadingIndicator, () =>
|
||||
{
|
||||
var attributesToFetch = new AttributesToFetch(RmResource.AttributeNames.DisplayName.Name, RmAttributeTypeDescription.AttributeNames.Name.Name);
|
||||
|
||||
var list = _fimClient.EnumerateAll<RmObjectTypeDescription>("/ObjectTypeDescription", attributesToFetch)
|
||||
.ToList();
|
||||
ObjectTypes.Clear();
|
||||
list.ForEach(x => ObjectTypes.Add(x));
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fetching attributes
|
||||
|
||||
private readonly Dictionary<string, List<SelectableAttribute>> _attributesCache =
|
||||
new Dictionary<string, List<SelectableAttribute>>();
|
||||
|
||||
private void FetchAttributesForSelectedObjectType()
|
||||
{
|
||||
string typeName = SelectedObjectType.Name;
|
||||
|
||||
FetchAttributesForObjectType(typeName);
|
||||
|
||||
FillCurrentAttributesCollection(_attributesCache[typeName]);
|
||||
}
|
||||
|
||||
private void FetchAttributesForObjectType(string typeName)
|
||||
{
|
||||
if (_attributesCache.ContainsKey(typeName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_parent.LongRunningOperation(_parent.loadingIndicator, () =>
|
||||
{
|
||||
var attributesToFetch = new AttributesToFetch(
|
||||
|
||||
RmResource.AttributeNames.DisplayName.Name
|
||||
, RmAttributeTypeDescription.AttributeNames.Name.Name
|
||||
, RmAttributeTypeDescription.AttributeNames.DataType.Name
|
||||
);
|
||||
|
||||
string query = "/BindingDescription[BoundObjectType = "
|
||||
+ "/ObjectTypeDescription[Name = '{0}']]".FormatWith(typeName)
|
||||
+ "/BoundAttributeType";
|
||||
|
||||
var attributes = _fimClient.EnumerateAll<RmAttributeTypeDescription>(query, attributesToFetch)
|
||||
.ToList();
|
||||
|
||||
_attributesCache.Add(typeName, attributes.Select(x => new SelectableAttribute(x)).ToList());
|
||||
});
|
||||
}
|
||||
|
||||
private void FillCurrentAttributesCollection(IEnumerable<SelectableAttribute> list)
|
||||
{
|
||||
CurrentAttributes.Clear();
|
||||
list.ForEach(x => CurrentAttributes.Add(x));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Executing query
|
||||
|
||||
private bool querying_selected_type()
|
||||
{
|
||||
return XPath.StartsWith("/" + SelectedObjectType.Name);
|
||||
}
|
||||
|
||||
public void ExecuteQuery()
|
||||
{
|
||||
var requiredAttributes = new List<SelectableAttribute>();
|
||||
|
||||
// attributes selection is possible only when directly querying for type selected in the list
|
||||
// otherwise there is no smart/easy way to tell if queried object contains any of currently displayed attributes
|
||||
if (querying_selected_type())
|
||||
{
|
||||
if (CurrentAttributes.Any(x => x.IsSelected))
|
||||
{
|
||||
requiredAttributes = CurrentAttributes.Where(x => x.IsSelected).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
requiredAttributes = CurrentAttributes.ToList();
|
||||
}
|
||||
|
||||
if (requiredAttributes.None(x => x.Attribute.Name == RmResource.AttributeNames.ObjectID.Name))
|
||||
{
|
||||
requiredAttributes.Add(CurrentAttributes.Single(x => x.Attribute.Name == RmResource.AttributeNames.ObjectID.Name));
|
||||
}
|
||||
}
|
||||
|
||||
// empty array if querying for other type than selected => all attributes will be fetched
|
||||
var attributesToFetch = new AttributesToFetch(requiredAttributes.Select(x => x.Attribute.Name).ToArray());
|
||||
|
||||
string query = XPath.Replace(Environment.NewLine, string.Empty);
|
||||
|
||||
RmResource[] results = _parent.LongRunningOperation(_parent.loadingIndicator,
|
||||
() => _fimClient.EnumerateAll<RmResource>(query, attributesToFetch)
|
||||
.ToArray()
|
||||
);
|
||||
|
||||
DataTable table = new DataTable();
|
||||
|
||||
if (results.IsNotEmpty())
|
||||
{
|
||||
// assuming that all results are of the same type
|
||||
var firstResult = results.First();
|
||||
var resultType = firstResult.GetResourceType();
|
||||
var resultTypeAttributes = firstResult.Attributes;
|
||||
|
||||
SelectableAttribute[] fetchedAttributes;
|
||||
if (requiredAttributes.IsNotEmpty())
|
||||
{
|
||||
fetchedAttributes = requiredAttributes.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
FetchAttributesForObjectType(resultType);
|
||||
fetchedAttributes = _attributesCache[resultType].ToArray();
|
||||
}
|
||||
|
||||
var resultTableColumnNames = new List<string>();
|
||||
|
||||
foreach (var a in resultTypeAttributes.OrderBy(x => x.Key.Name))
|
||||
{
|
||||
var selectedAttribute = fetchedAttributes.SingleOrDefault(x => x.Attribute.Name == a.Key.Name);
|
||||
if (selectedAttribute == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var column = table.Columns.Add(selectedAttribute.Attribute.DisplayName);
|
||||
resultTableColumnNames.Add(selectedAttribute.Attribute.Name);
|
||||
|
||||
// window can detect references by their 'object' type as opposed to 'string' defined for all other fields
|
||||
if (selectedAttribute.Attribute.DataType == RmFactory.RmAttributeType.Reference.ToString())
|
||||
{
|
||||
column.DataType = typeof(object);
|
||||
}
|
||||
else
|
||||
{
|
||||
column.DataType = typeof(string);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var resource in results)
|
||||
{
|
||||
var newRowValues = resultTableColumnNames
|
||||
.Select(x =>
|
||||
{
|
||||
if (resource.Attributes.Keys.Any(y => y.Name == x))
|
||||
{
|
||||
return resource.Attributes.First(y => y.Key.Name == x)
|
||||
.Value.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.ToArray();
|
||||
|
||||
table.Rows.Add(newRowValues);
|
||||
}
|
||||
}
|
||||
|
||||
QueriedValues = table;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Showing details by object id
|
||||
|
||||
public void ShowDetailsById()
|
||||
{
|
||||
RmResource result = _parent.LongRunningOperation(_parent.loadingIndicator,
|
||||
() => _fimClient.FindById(IdForSearch)
|
||||
);
|
||||
_windowsManager.ObjectDetailsDialog(result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void ExportToXml(string filePath)
|
||||
{
|
||||
using (var fileStream = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.Write))
|
||||
{
|
||||
_xmlExporter.WriteXml(fileStream, XPath);
|
||||
}
|
||||
}
|
||||
|
||||
#region INotifyPropertyChanged
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged = delegate { };
|
||||
|
||||
private void NotifyChanged(string propertyName)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
<Window x:Class="Predica.FimExplorer.UI.WPF.Main.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="Predica FIM Explorer" Height="600" Width="1200">
|
||||
<Grid>
|
||||
<Grid x:Name="mainContainer">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="100" />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="350" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Row="0" Grid.Column="0">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox
|
||||
Width="250"
|
||||
Height="40"
|
||||
TextWrapping="Wrap" AcceptsReturn="True" VerticalScrollBarVisibility="Visible"
|
||||
Text="{Binding XPath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
/>
|
||||
<Button Content="Run query" Click="btnRunQuery_Click" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox Width="250"
|
||||
x:Name="tbIdToFind"
|
||||
Text="{Binding IdForSearch, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
/>
|
||||
<Button Content="Find by ID" Click="btnFindById_Click" />
|
||||
</StackPanel>
|
||||
<Button Click="btnExportXml_Click">Export to XML</Button>
|
||||
<Button Click="btnImportXml_Click">Import XML</Button>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal">
|
||||
<ListBox ItemsSource="{Binding ObjectTypes}"
|
||||
SelectedItem="{Binding SelectedObjectType, Mode=TwoWay}"
|
||||
DisplayMemberPath="DisplayName" />
|
||||
<ListBox
|
||||
ItemsSource="{Binding CurrentAttributes}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<CheckBox
|
||||
Content="{Binding Attribute.DisplayName}"
|
||||
IsChecked="{Binding IsSelected,Mode=TwoWay}"
|
||||
/>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</StackPanel>
|
||||
<DataGrid
|
||||
Grid.Row="0" Grid.Column="1" Grid.RowSpan="2"
|
||||
SelectionUnit="FullRow"
|
||||
IsReadOnly="True"
|
||||
ItemsSource="{Binding QueriedValues}"
|
||||
SelectedItem="{Binding SelectedRow,Mode=TwoWay}"
|
||||
AutoGeneratingColumn="DataGrid_AutoGeneratingColumn"
|
||||
AutoGeneratedColumns="DataGrid_AutoGeneratedColumns"
|
||||
MouseDoubleClick="DataGrid_MouseDoubleClick" />
|
||||
</Grid>
|
||||
<Grid x:Name="loadingIndicator"
|
||||
Visibility="Collapsed" Opacity="0.5" Background="Black">
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
|
@ -0,0 +1,150 @@
|
|||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Microsoft.Win32;
|
||||
using Predica.FimCommunication.Export;
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF.Main
|
||||
{
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
MainModel _model;
|
||||
ReferenceColumnDetector _referenceColumnDetector;
|
||||
WindowsManager _windowsManager;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
try
|
||||
{
|
||||
_windowsManager = new WindowsManager();
|
||||
_model = new MainModel(this, FimClientFactory.CreateClient(), _windowsManager, new XmlExporter());
|
||||
_referenceColumnDetector = new ReferenceColumnDetector();
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
this.DataContext = _model;
|
||||
_model.Initialize();
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
MessageBox.Show(@"There was an error during application startup. Verify that your configuration file points to a valid FIM service instance.
|
||||
Application will now close.
|
||||
|
||||
Exception details:
|
||||
|
||||
" + exc, "Predica.FimExplorer Initialization error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private void btnRunQuery_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_model.CurrentAttributes.Count == 0)
|
||||
{
|
||||
_windowsManager.Error("Object type must be selected first. Only currently selected object type can be searched by xpath.");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_model.ExecuteQuery();
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
_windowsManager.Error(exc.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void btnFindById_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_model.ShowDetailsById();
|
||||
}
|
||||
|
||||
private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
|
||||
{
|
||||
// only references are marked as objects, all other are strings
|
||||
_referenceColumnDetector.ProcessAutogeneratedColumn<object>(e
|
||||
, id =>
|
||||
{
|
||||
_model.IdForSearch = id;
|
||||
_model.ShowDetailsById();
|
||||
});
|
||||
|
||||
DecideColumnOrder(e);
|
||||
}
|
||||
|
||||
// field used to correctly set column display indexes (ID and DisplayName); reset when all columns are generated
|
||||
private bool resourceID_column_already_configured = false;
|
||||
|
||||
private void DecideColumnOrder(DataGridAutoGeneratingColumnEventArgs e)
|
||||
{
|
||||
// ObjectID always as 1st column
|
||||
if (e.PropertyName == "Resource ID")
|
||||
{
|
||||
e.Column.DisplayIndex = 0;
|
||||
resourceID_column_already_configured = true;
|
||||
}
|
||||
// DisplayName is 2nd
|
||||
if (e.PropertyName == "Display Name")
|
||||
{
|
||||
// set to 0 if ResourceID was not already configured - it will be configured later, pushing this column further
|
||||
e.Column.DisplayIndex = resourceID_column_already_configured ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void DataGrid_AutoGeneratedColumns(object sender, EventArgs e)
|
||||
{
|
||||
resourceID_column_already_configured = false;
|
||||
}
|
||||
|
||||
private void DataGrid_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
_model.ShowDetailsById();
|
||||
}
|
||||
|
||||
private void btnExportXml_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var saveFileDialog = new SaveFileDialog();
|
||||
saveFileDialog.DefaultExt = ".xml";
|
||||
saveFileDialog.Filter = "XML documents|*.xml|All files|*.*";
|
||||
|
||||
if (saveFileDialog.ShowDialog() != true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_model.ExportToXml(saveFileDialog.FileName);
|
||||
|
||||
_windowsManager.Info("Export finished");
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
_windowsManager.Error(exc.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void btnImportXml_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var openFileDialog = new OpenFileDialog();
|
||||
openFileDialog.DefaultExt = ".xml";
|
||||
openFileDialog.Filter = "XML documents|*.xml|All files|*.*";
|
||||
|
||||
if (openFileDialog.ShowDialog() != true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_windowsManager.ImportObjectsDialog(openFileDialog.FileName);
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
_windowsManager.Error(exc.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
using Microsoft.ResourceManagement.ObjectModel.ResourceTypes;
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF.Main
|
||||
{
|
||||
public class SelectableAttribute
|
||||
{
|
||||
public RmAttributeTypeDescription Attribute { get; set; }
|
||||
public bool IsSelected { get; set; }
|
||||
|
||||
public SelectableAttribute(RmAttributeTypeDescription attribute)
|
||||
{
|
||||
Attribute = attribute;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF.Main
|
||||
{
|
||||
public static class WindowExtensions
|
||||
{
|
||||
public static TResult LongRunningOperation<TResult>(this Window @this, Panel loadingIndicator, Func<TResult> action)
|
||||
{
|
||||
TResult result = default(TResult);
|
||||
|
||||
@this.LongRunningOperation(loadingIndicator, new Action(() => result = action()));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void LongRunningOperation(this Window @this, Panel loadingIndicator, Action action)
|
||||
{
|
||||
var originalCursor = @this.Cursor;
|
||||
@this.Cursor = Cursors.Wait;
|
||||
loadingIndicator.Visibility = Visibility.Visible;
|
||||
|
||||
DispatcherFrame frame = new DispatcherFrame();
|
||||
DispatcherOperation dispatcherOperation = Dispatcher.CurrentDispatcher
|
||||
.BeginInvoke(DispatcherPriority.ContextIdle,
|
||||
new Action(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
action();
|
||||
}
|
||||
finally
|
||||
{
|
||||
loadingIndicator.Visibility = Visibility.Collapsed;
|
||||
@this.Cursor = originalCursor;
|
||||
}
|
||||
})
|
||||
);
|
||||
dispatcherOperation.Completed += delegate
|
||||
{
|
||||
frame.Continue = false;
|
||||
};
|
||||
|
||||
Dispatcher.PushFrame(frame);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
[assembly: AssemblyTitle("Predica.FimExplorer")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Predica Business Solutions")]
|
||||
[assembly: AssemblyProduct("Predica.FimExplorer")]
|
||||
[assembly: AssemblyCopyright("Copyright © Predica Business Solutions")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
)]
|
||||
|
||||
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,63 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.225
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Predica.FimExplorer.UI.WPF.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
|
@ -0,0 +1,26 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.225
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
|
@ -0,0 +1,56 @@
|
|||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF
|
||||
{
|
||||
/// <summary>
|
||||
/// Detects (based on type) if given autogenerated column is a reference
|
||||
/// and replaces it with hyperlink column with 'click' event handled
|
||||
/// </summary>
|
||||
public class ReferenceColumnDetector
|
||||
{
|
||||
public void ProcessAutogeneratedColumn<TReferenceType>(DataGridAutoGeneratingColumnEventArgs e, Action<string> handleReferenceClick)
|
||||
{
|
||||
var originalColumn = (DataGridBoundColumn)e.Column;
|
||||
Type propertyType = e.PropertyType;
|
||||
|
||||
if (propertyType.Is<TReferenceType>())
|
||||
{
|
||||
var linkStyle = CreateLinkStyle(handleReferenceClick);
|
||||
|
||||
e.Column = CreateHyperlinkColumn(originalColumn, linkStyle);
|
||||
}
|
||||
}
|
||||
|
||||
private Style CreateLinkStyle(Action<string> handleReferenceClick)
|
||||
{
|
||||
var linkStyle = new Style(typeof (TextBlock));
|
||||
|
||||
RoutedEventHandler clickHandler = (o, e) =>
|
||||
{
|
||||
var textExtractor = new HyperlinkTextExtractor();
|
||||
string id = textExtractor.ExtractText((Hyperlink) e.Source);
|
||||
handleReferenceClick(id);
|
||||
};
|
||||
|
||||
linkStyle.Setters.Add(new EventSetter(Hyperlink.ClickEvent, clickHandler));
|
||||
|
||||
return linkStyle;
|
||||
}
|
||||
|
||||
private static DataGridHyperlinkColumn CreateHyperlinkColumn(DataGridBoundColumn originalColumn, Style linkStyle)
|
||||
{
|
||||
var newColumn = new DataGridHyperlinkColumn
|
||||
{
|
||||
ElementStyle = linkStyle,
|
||||
Binding = originalColumn.Binding,
|
||||
Header = originalColumn.Header,
|
||||
HeaderStringFormat = "[ref] {0}",
|
||||
};
|
||||
|
||||
return newColumn;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{72AF0280-1398-4DB7-A2FA-24DAA9B4CDAB}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Predica.FimExplorer.UI.WPF</RootNamespace>
|
||||
<AssemblyName>Predica.FimExplorer</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="NLog">
|
||||
<HintPath>..\..\FimClient\lib\NLog2.netfx40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.configuration" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Xaml">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="Details\DetailsValueCellTemplateSelector.cs" />
|
||||
<Compile Include="FimClientFactory.cs" />
|
||||
<Compile Include="HyperlinkTextExtractor.cs" />
|
||||
<Compile Include="Import\ImportedObjectsModel.cs" />
|
||||
<Compile Include="Import\ImportedObjectsWindow.xaml.cs">
|
||||
<DependentUpon>ImportedObjectsWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Main\WindowExtensions.cs" />
|
||||
<Compile Include="ReferenceColumnDetector.cs" />
|
||||
<Compile Include="WindowsManager.cs" />
|
||||
<Compile Include="_Utils\EnumerableExtensions.cs" />
|
||||
<Compile Include="_Utils\TypeExtensions.cs" />
|
||||
<Page Include="Import\ImportedObjectsWindow.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Main\MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Details\ObjectDetailsModel.cs" />
|
||||
<Compile Include="Main\SelectableAttribute.cs" />
|
||||
<Compile Include="Main\MainModel.cs" />
|
||||
<Compile Include="Main\MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Page Include="Details\ObjectDetailsWindow.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Details\FlattenedAttribute.cs" />
|
||||
<Compile Include="Details\ObjectDetailsWindow.xaml.cs">
|
||||
<DependentUpon>ObjectDetailsWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="app.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<AppDesigner Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\FimClient\src\FimCommunication\FimCommunication.csproj">
|
||||
<Project>{b296ee14-b117-4b23-8e36-3e15932d8e8e}</Project>
|
||||
<Name>FimCommunication</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\FimClient\src\_external\fim2010client\Microsoft.ResourceManagement.Client\Fim2010Client.Client.csproj">
|
||||
<Project>{6c1064e6-72b3-41aa-b543-4164ec056f68}</Project>
|
||||
<Name>Fim2010Client.Client</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\FimClient\src\_external\fim2010client\Microsoft.ResourceManagement.ObjectModel\Fim2010Client.ObjectModel.csproj">
|
||||
<Project>{cecb3a49-a780-4558-a402-1f3ff42b0b18}</Project>
|
||||
<Name>Fim2010Client.ObjectModel</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,61 @@
|
|||
using System.IO;
|
||||
using System.Windows;
|
||||
using Microsoft.ResourceManagement.ObjectModel;
|
||||
using NLog;
|
||||
using Predica.FimCommunication.Import;
|
||||
using Predica.FimExplorer.UI.WPF.Details;
|
||||
using Predica.FimExplorer.UI.WPF.Import;
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF
|
||||
{
|
||||
public class WindowsManager
|
||||
{
|
||||
public void ObjectDetailsDialog(RmResource target)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
_log.Debug("Cannot show details of null object");
|
||||
return;
|
||||
}
|
||||
|
||||
var model = new ObjectDetailsModel(target, FimClientFactory.CreateClient(), this);
|
||||
|
||||
var detailsWindow = new ObjectDetailsWindow();
|
||||
|
||||
detailsWindow.Initialize(model);
|
||||
|
||||
_log.Debug("Showing details of [{0}:{1}]", target.ObjectType, target.ObjectID);
|
||||
|
||||
detailsWindow.Show();
|
||||
}
|
||||
|
||||
public void ImportObjectsDialog(string fileName)
|
||||
{
|
||||
_log.Debug("Showing import window for file {0}", fileName);
|
||||
|
||||
var importWindow = new ImportedObjectsWindow();
|
||||
|
||||
ImportedObjectsModel model;
|
||||
using (var stream = File.OpenRead(fileName))
|
||||
{
|
||||
model = new ImportedObjectsModel(stream, new XmlImporter(), this);
|
||||
model.Initialize();
|
||||
importWindow.Initialize(model);
|
||||
}
|
||||
|
||||
importWindow.ShowDialog();
|
||||
}
|
||||
|
||||
public void Info(string message)
|
||||
{
|
||||
MessageBox.Show(message, "Information", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
|
||||
public void Error(string message)
|
||||
{
|
||||
MessageBox.Show(message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
|
||||
private static readonly Logger _log = LogManager.GetCurrentClassLogger();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF
|
||||
{
|
||||
public static class EnumerableExtensions
|
||||
{
|
||||
public static bool IsEmpty<T>(this IEnumerable<T> @this)
|
||||
{
|
||||
return !@this.Any();
|
||||
}
|
||||
|
||||
public static bool IsNotEmpty<T>(this IEnumerable<T> @this)
|
||||
{
|
||||
return !@this.IsEmpty();
|
||||
}
|
||||
|
||||
public static void ForEach<T>(this IEnumerable<T> @this, Action<T> operation)
|
||||
{
|
||||
foreach (var element in @this)
|
||||
{
|
||||
operation(element);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool None<T>(this IEnumerable<T> @this, Func<T, bool> predicate)
|
||||
{
|
||||
return !@this.Any(predicate);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
|
||||
namespace Predica.FimExplorer.UI.WPF
|
||||
{
|
||||
public static class TypeExtensions
|
||||
{
|
||||
public static bool Is<TOther>(this Type @this)
|
||||
{
|
||||
return @this == (typeof(TOther));
|
||||
}
|
||||
|
||||
public static bool IsNot<TOther>(this Type @this)
|
||||
{
|
||||
return !@this.Is<TOther>();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue