diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..1ff0c42
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,63 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg binary
+#*.png binary
+#*.gif binary
+
+###############################################################################
+# diff behavior for common document formats
+#
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the
+# entries below.
+###############################################################################
+#*.doc diff=astextplain
+#*.DOC diff=astextplain
+#*.docx diff=astextplain
+#*.DOCX diff=astextplain
+#*.dot diff=astextplain
+#*.DOT diff=astextplain
+#*.pdf diff=astextplain
+#*.PDF diff=astextplain
+#*.rtf diff=astextplain
+#*.RTF diff=astextplain
diff --git a/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTree.xml b/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTree.xml
index 40aa006..f2c5477 100644
--- a/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTree.xml
+++ b/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTree.xml
@@ -6,6 +6,7 @@
using Xpp = Microsoft.Dynamics.Ax.Xpp;
using ArbelaXpp = Arbela.Dynamics.Ax.Xpp;
using Microsoft.Dynamics.AX.Metadata.MetaModel;
+using CoreMetaModel = Microsoft.Dynamics.AX.Metadata.Core.MetaModel;
using System.Reflection;
using System.Linq.Enumerable;
@@ -14,6 +15,7 @@ using System.Linq.Enumerable;
///
public class ARBAOTObjectTree
{
+ public static Microsoft.Dynamics.AX.Metadata.Providers.IMetadataProvider MetadataProvider;
protected FormTreeControl treeControl;
protected ARBAOTObjectType aotObjectType;
protected boolean extensionsInline;
@@ -23,6 +25,18 @@ public class ARBAOTObjectTree
}
]]>
+
+ typenew
+
+
parmTreeControl
+
+
+ addExtensionCollection
+
+ /// Adds a collection of extensions to the tree
+ ///
+ /// The collection to add
+ /// The collection name
+ /// The extension name
+ protected void addExtensionCollection(System.Collections.IEnumerable _collection, str _collectionName, str _extensionName)
+ {
+ System.Collections.IEnumerator modEnum = _collection.GetEnumerator();
+ if (strEndsWith(_collectionName, 'Modifications'))
+ {
+ str modName = strReplace(_collectionName, 'Modifications', 's');
+ System.Collections.IEnumerator modsEnum = _collection.GetEnumerator();
+ if (collectionMap.exists(modName))
+ {
+ Map valuesMap = collectionMap.lookup(modName);
+ while (modsEnum.MoveNext())
+ {
+ FormTreeItem control = treeControl.getItem(valuesMap.lookup(this.getObjectName(modsEnum.Current)));
+ this.addExtensionModification(control, modsEnum.Current, _extensionName);
+ }
+ }
+ }
+ else
+ {
+ if (collectionMap.exists(_collectionName))
+ {
+ Map modMap = collectionMap.lookup(_collectionName);
+ TreeItemIdx rootNodeIdx = modMap.lookup('RootNode');
+ while (modEnum.MoveNext())
+ {
+ if (modEnum.Current is AxExtensionModification)
+ {
+ FormTreeItem control = treeControl.getItem(modMap.lookup(this.getObjectName(modEnum.Current)));
+ this.addExtensionModification(control, modEnum.Current, _extensionName);
+ }
+ else
+ {
+ this.addExtension(modEnum.Current, rootNodeIdx, _extensionName);
+ }
+ }
+ }
+ }
+ }
+
]]>
@@ -343,7 +440,7 @@ public class ARBAOTObjectTree
/// If true, skip adding the header node
/// The name of the extension it came from, if any
/// The tree index of the new node
- public TreeItemIdx addTreeNode(anytype _object, TreeItemIdx _idx, FormTreeAdd _formTreeAdd = FormTreeAdd::Sort, boolean _skipAddHeader = false, str _extensionName = '')
+ public TreeItemIdx addTreeNode(anytype _object, TreeItemIdx _idx, int _formTreeAdd = FormTreeAdd::Sort, boolean _skipAddHeader = false, str _extensionName = '')
{
System.Type t = _object.GetType();
@@ -420,7 +517,7 @@ public class ARBAOTObjectTree
/// The parent index to add the collection to
/// The method for adding the collection to the tree
/// The index of the collection
- protected TreeItemIdx addCollectionToTree(System.Collections.IEnumerable _collection, str _collectionName, TreeItemIdx _parentIdx, FormTreeAdd _formTreeAdd)
+ protected TreeItemIdx addCollectionToTree(System.Collections.IEnumerable _collection, str _collectionName, TreeItemIdx _parentIdx, int _formTreeAdd)
{
boolean insertIntoMap = false;
if (treeControl.getRoot() == _parentIdx)
@@ -438,7 +535,8 @@ public class ARBAOTObjectTree
}
TreeItemIdx idx = _parentIdx;
- if (_collectionName != 'Controls')
+ if ((_collectionName != 'Controls' && _collectionName != 'Elements')
+ || (treeControl.getItem(_parentIdx).data() is AxFormExtension))
{
idx = SysFormTreeControl::addTreeItem(treeControl, _collectionName, _parentIdx, _collection, 0, true, 0, _formTreeAdd);
}
@@ -474,9 +572,24 @@ public class ARBAOTObjectTree
/// The extension
/// The parent index
/// The extension name
- protected void addExtension(anytype _extension, TreeItemIdx _parentIdx, str _extensionName)
+ /// The position the control should be added
+ /// The index where the control should be inserted after
+ protected void addExtension(anytype _extension, TreeItemIdx _parentIdx, str _extensionName, CoreMetaModel.ExtensionItemPositionType _positionType =CoreMetaModel.ExtensionItemPositionType::End, int _afterItemIdx = 0)
{
- TreeItemIdx extIdx = this.addTreeNode(_extension, _parentIdx, FormTreeAdd::Last, false, _extensionName);
+ int formTreeAdd;
+ switch (_positionType)
+ {
+ case CoreMetaModel.ExtensionItemPositionType::Begin:
+ formTreeAdd = FormTreeAdd::First;
+ break;
+ case CoreMetaModel.ExtensionItemPositionType::End:
+ formTreeAdd = FormTreeAdd::Last;
+ break;
+ case CoreMetaModel.ExtensionItemPositionType::AfterItem:
+ formTreeAdd = _afterItemIdx;
+ break;
+ }
+ TreeItemIdx extIdx = this.addTreeNode(_extension, _parentIdx, formTreeAdd, false, _extensionName);
FormTreeItem control = treeControl.getItem(extIdx);
control.stateBold(true);
treeControl.setItem(control);
@@ -509,6 +622,32 @@ public class ARBAOTObjectTree
treeControl.setItem(_control);
}
+]]>
+
+
+ getNamedNode
+
+ /// Get the index of the node in a sibling group based on the name
+ ///
+ /// The parent index
+ /// The node name
+ /// The index of the node
+ protected TreeItemIdx getNamedNode(TreeItemIdx _parentIdx, str _nodeName)
+ {
+ TreeItemIdx childIdx = treeControl.getChild(_parentIdx);
+ FormTreeItem ret;
+
+ do
+ {
+ ret = treeControl.getItem(childIdx);
+ childIdx = treeControl.getNextSibling(childIdx);
+ }
+ while (ret.text() != _nodeName && childIdx > 0);
+
+ return ret.idx();
+ }
+
]]>
diff --git a/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeBaseEnum.xml b/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeBaseEnum.xml
new file mode 100644
index 0000000..4f30a54
--- /dev/null
+++ b/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeBaseEnum.xml
@@ -0,0 +1,53 @@
+
+
+ ARBAOTObjectTreeBaseEnum
+
+
+/// Override the Object Tree for Base Enums
+///
+[ARBAOTObjectType(ARBAOTObjectType::BaseEnum)]
+class ARBAOTObjectTreeBaseEnum extends ARBAOTObjectTree
+{
+}
+]]>
+
+
+ addExtensionCollection
+
+ /// Adds a collection of extensions to the tree
+ ///
+ /// The collection to add
+ /// The collection name
+ /// The extension name
+ protected void addExtensionCollection(System.Collections.IEnumerable _collection, str _collectionName, str _extensionName)
+ {
+ switch (_collectionName)
+ {
+ case 'ValueModifications':
+ System.Collections.IEnumerator valueModsEnum = _collection.GetEnumerator();
+ if (collectionMap.exists('EnumValues'))
+ {
+ Map valuesMap = collectionMap.lookup('EnumValues');
+ while (valueModsEnum.MoveNext())
+ {
+ FormTreeItem control = treeControl.getItem(valuesMap.lookup(this.getObjectName(valueModsEnum.Current)));
+ this.addExtensionModification(control, valueModsEnum.Current, _extensionName);
+ }
+ }
+ break;
+ default:
+ super(_collection, _collectionName, _extensionName);
+ break;
+ }
+ }
+
+]]>
+
+
+
+
\ No newline at end of file
diff --git a/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeDataEntity.xml b/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeDataEntity.xml
index a766b72..61d5076 100644
--- a/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeDataEntity.xml
+++ b/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeDataEntity.xml
@@ -8,34 +8,100 @@ using ArbelaXpp = Arbela.Dynamics.Ax.Xpp;
using Microsoft.Dynamics.AX.Metadata.MetaModel;
///
-/// Override the Object Tree for Data entities
+/// Override the Object Tree for Views
///
[ARBAOTObjectType(ARBAOTObjectType::DataEntity)]
class ARBAOTObjectTreeDataEntity extends ARBAOTObjectTree
{
+ Map dataSourceMap = new Map(Types::String, Types::Integer);
+ Map currentDsMap;
+
}
]]>
- update
+ addExtensionCollection
- /// Update the object tree
+ /// Adds a collection of extensions to the tree
///
- /// The name of the AOT object
- public void update(TreeNodeName _aotNodeName)
+ /// The collection to add
+ /// The collection name
+ /// The extension name
+ protected void addExtensionCollection(System.Collections.IEnumerable _collection, str _collectionName, str _extensionName)
{
- AxDataEntityView dataEntityView = Xpp.MetadataSupport::GetDataEntityView(_aotNodeName);
- TreeItemIdx rootIdx = this.updateObjectTree(dataEntityView, dataEntityView.Name);
- var aotObjectExtensions = ArbelaXpp.MetadataSupport::GetDataEntityViewExtensionsForDataEntityView(_aotNodeName);
- System.Collections.IEnumerator enumerator = aotObjectExtensions.GetEnumerator();
+ System.Collections.IEnumerator modsEnum;
+ switch (_collectionName)
+ {
+ case 'DataSources':
+ modsEnum = _collection.GetEnumerator();
+ while (modsEnum.MoveNext())
+ {
+ AxQueryExtensionEmbeddedDataSource ds = modsEnum.Current;
+ this.addExtension(ds.DataSource, this.getNamedNode(dataSourceMap.lookup(ds.Parent), 'DataSources'), _extensionName);
+ }
+ break;
+ case 'FieldGroupExtensions':
+ System.Collections.IEnumerator fieldGroupEnum = _collection.GetEnumerator();
+ if (collectionMap.exists('FieldGroups'))
+ {
+ Map fieldGroupsMap = collectionMap.lookup('FieldGroups');
+ while (fieldGroupEnum.MoveNext())
+ {
+ AxTableFieldGroupExtension fieldGroupExtension = fieldGroupEnum.Current;
+ TreeItemIdx parentIdx = fieldGroupsMap.lookup(fieldGroupExtension.Name);
+ parentIdx = treeControl.getChild(parentIdx); // Get the index of the Fields node
+ var fieldsEnum = fieldGroupExtension.Fields.GetEnumerator();
+ while (fieldsEnum.MoveNext())
+ {
+ this.addExtension(fieldsEnum.Current, parentIdx, _extensionName);
+ }
+ }
+ }
+ break;
+ default:
+ super(_collection, _collectionName, _extensionName);
+ break;
+ }
+ }
- TreeItemIdx extensionsIdx = SysFormTreeControl::addTreeItem(treeControl, 'Extensions', rootIdx, aotObjectExtensions, 0, true);
- while (enumerator.moveNext())
+]]>
+
+
+ addTreeNode
+
+ /// Adds a new node to the tree
+ ///
+ /// The object to add
+ /// The tree index to add it under
+ /// The order it should add the node
+ /// The name of the extension it came from, if any
+ /// The tree index of the new node
+ public TreeItemIdx addTreeNode(anytype _object, TreeItemIdx _idx, int _formTreeAdd = FormTreeAdd::Sort, boolean _skipAddHeader = false, str _extensionName = '')
+ {
+ str objectName = this.getObjectName(_object);
+ boolean insertIntoMap = false;
+ if (_object is AxQuerySimpleRootDataSource)
+ {
+ insertIntoMap = true;
+ currentDsMap = dataSourceMap;
+ }
+
+ TreeItemIdx parentIdx = super(_object, _idx, _formTreeAdd, _skipAddHeader, _extensionName);
+
+ if (currentDsMap != null
+ && (_object is AxQuerySimpleDataSource))
{
- this.addTreeNode(enumerator.Current, extensionsIdx);
+ currentDsMap.insert(objectName, parentIdx);
}
- treeControl.select(rootIdx);
+
+ if (insertIntoMap)
+ {
+ currentDsMap = null;
+ }
+
+ return parentIdx;
}
]]>
diff --git a/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeForm.xml b/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeForm.xml
index 1026594..1d7b80b 100644
--- a/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeForm.xml
+++ b/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeForm.xml
@@ -6,6 +6,7 @@
using Xpp = Microsoft.Dynamics.Ax.Xpp;
using ArbelaXpp = Arbela.Dynamics.Ax.Xpp;
using Microsoft.Dynamics.AX.Metadata.MetaModel;
+using CoreMetaModel = Microsoft.Dynamics.AX.Metadata.Core.MetaModel;
///
/// Override the Object Tree for Forms
@@ -19,75 +20,37 @@ class ARBAOTObjectTreeForm extends ARBAOTObjectTree
]]>
- update
+ addExtensionCollection
- /// Update the object tree
+ /// Adds a collection of extensions to the tree
///
- /// The name of the AOT object
- public void update(TreeNodeName _aotNodeName)
+ /// The collection to add
+ /// The collection name
+ /// The extension name
+ protected void addExtensionCollection(System.Collections.IEnumerable _collection, str _collectionName, str _extensionName)
{
- AxForm form = Xpp.MetadataSupport::GetForm(_aotNodeName);
- TreeItemIdx rootIdx = this.updateObjectTree(form, form.Name);
- var aotObjectExtensions = ArbelaXpp.MetadataSupport::GetFormExtensionsForForm(_aotNodeName);
- System.Collections.IEnumerator enumerator = aotObjectExtensions.GetEnumerator();
-
- TreeItemIdx extensionsIdx;
- if (!extensionsInline)
- {
- extensionsIdx = SysFormTreeControl::addTreeItem(treeControl, 'Extensions', rootIdx, aotObjectExtensions, 0, true);
- }
- while (enumerator.moveNext())
+ System.Collections.IEnumerator modsEnum;
+ switch (_collectionName)
{
- AxFormExtension formExtension = enumerator.Current;
- if (extensionsInline)
- {
- str extensionName = conPeek(list2Con(strSplit(formExtension.Name, '.')),2);
- var controlsEnum = formExtension.Controls.GetEnumerator();
- while (controlsEnum.moveNext())
- {
- this.addExtension(controlsEnum.Current, controlMap.lookup(controlsEnum.Current.Parent), extensionName);
- }
- var controlsModEnum = formExtension.ControlModifications.GetEnumerator();
- while (controlsModEnum.moveNext())
- {
- FormTreeItem control = treeControl.getItem(controlMap.lookup(controlsModEnum.Current.Name));
- this.addExtensionModification(control, controlsModEnum.Current, extensionName);
- }
- Map dataSourceMap = collectionMap.lookup('DataSources');
- TreeItemIdx dataSourcesIdx = dataSourceMap.lookup('RootNode');
- var datasourcesEnum = formExtension.DataSources.GetEnumerator();
- while (datasourcesEnum.moveNext())
- {
- this.addExtension(datasourcesEnum.Current, dataSourcesIdx, extensionName);
- }
- var dataSourcesModEnum = formExtension.DataSourceModifications.GetEnumerator();
- while (dataSourcesModEnum.moveNext())
- {
- FormTreeItem control = treeControl.getItem(datasourceMap.lookup(dataSourcesModEnum.Current.Name));
- this.addExtensionModification(control, dataSourcesModEnum.Current, extensionName);
- }
- Map partsMap = collectionMap.lookup('Parts');
- TreeItemIdx partsIdx = partsMap.lookup('RootNode');
- var partsEnum = formExtension.Parts.GetEnumerator();
- while (partsEnum.moveNext())
- {
- this.addExtension(partsEnum.Current, partsIdx, extensionName);
- }
- if (formExtension.PropertyModifications != null)
+ case 'Controls':
+ modsEnum = _collection.GetEnumerator();
+ while (modsEnum.moveNext())
{
- FormTreeItem rootNode = treeControl.getItem(treeControl.getRoot());
- AxExtensionModification extMod = new AxExtensionModification();
- extMod.PropertyModifications = formExtension.PropertyModifications;
- this.addExtensionModification(rootNode, extMod, extensionName);
+ AxFormExtensionControl controlExt = modsEnum.Current;
+ TreeItemIdx parentIdx = controlMap.lookup(controlExt.Parent);
+ TreeItemIdx afterIdx;
+ if (controlExt.PositionType == CoreMetaModel.ExtensionItemPositionType::AfterItem)
+ {
+ afterIdx = SysFormTreeControl::findInsertAfterIdx(treeControl, parentIdx, controlExt.PreviousSibling);
+ }
+ this.addExtension(controlExt.FormControl, parentIdx, _extensionName, controlExt.PositionType, afterIdx);
}
- }
- else
- {
- this.addTreeNode(formExtension, extensionsIdx);
- }
+ break;
+ default:
+ super(_collection, _collectionName, _extensionName);
+ break;
}
- treeControl.select(rootIdx);
}
]]>
@@ -103,7 +66,7 @@ class ARBAOTObjectTreeForm extends ARBAOTObjectTree
/// The order it should add the node
/// The name of the extension it came from, if any
/// The tree index of the new node
- public TreeItemIdx addTreeNode(anytype _object, TreeItemIdx _idx, FormTreeAdd _formTreeAdd = FormTreeAdd::Sort, boolean _skipAddHeader = false, str _extensionName = '')
+ public TreeItemIdx addTreeNode(anytype _object, TreeItemIdx _idx, int _formTreeAdd = FormTreeAdd::Sort, boolean _skipAddHeader = false, str _extensionName = '')
{
str objectName = this.getObjectName(_object);
boolean insertIntoMap = false;
@@ -111,6 +74,7 @@ class ARBAOTObjectTreeForm extends ARBAOTObjectTree
{
insertIntoMap = true;
currentMap = controlMap;
+ collectionMap.insert('Controls', controlMap);
}
TreeItemIdx parentIdx = super(_object, _idx, _formTreeAdd, _skipAddHeader, _extensionName);
diff --git a/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeMenu.xml b/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeMenu.xml
new file mode 100644
index 0000000..8eceb6c
--- /dev/null
+++ b/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeMenu.xml
@@ -0,0 +1,109 @@
+
+
+ ARBAOTObjectTreeMenu
+
+
+/// Override the Object Tree for Views
+///
+[ARBAOTObjectType(ARBAOTObjectType::Menu)]
+class ARBAOTObjectTreeMenu extends ARBAOTObjectTree
+{
+ Map elementMap = new Map(Types::String, Types::Integer);
+ Map currentElementMap;
+
+}
+]]>
+
+
+ addExtensionCollection
+
+ /// Adds a collection of extensions to the tree
+ ///
+ /// The collection to add
+ /// The collection name
+ /// The extension name
+ protected void addExtensionCollection(System.Collections.IEnumerable _collection, str _collectionName, str _extensionName)
+ {
+ System.Collections.IEnumerator modsEnum;
+ switch (_collectionName)
+ {
+ case 'Elements':
+ modsEnum = _collection.GetEnumerator();
+ while (modsEnum.MoveNext())
+ {
+ AxMenuExtensionElement menuExt = modsEnum.Current;
+ TreeItemIdx parentIdx;
+ if (menuExt.Parent == '')
+ {
+ parentIdx = treeControl.getRoot();
+ }
+ else
+ {
+ parentIdx = elementMap.lookup(menuExt.Parent);
+ }
+ TreeItemIdx afterIdx;
+ if (menuExt.PositionType == CoreMetaModel.ExtensionItemPositionType::AfterItem)
+ {
+ afterIdx = SysFormTreeControl::findInsertAfterIdx(treeControl, parentIdx, menuExt.PreviousSibling);
+ }
+ this.addExtension(menuExt.MenuElement, parentIdx, _extensionName, menuExt.PositionType, afterIdx);
+ }
+ break;
+ default:
+ super(_collection, _collectionName, _extensionName);
+ break;
+ }
+ }
+
+]]>
+
+
+ addTreeNode
+
+ /// Adds a new node to the tree
+ ///
+ /// The object to add
+ /// The tree index to add it under
+ /// The order it should add the node
+ /// The name of the extension it came from, if any
+ /// The tree index of the new node
+ public TreeItemIdx addTreeNode(anytype _object, TreeItemIdx _idx, int _formTreeAdd = FormTreeAdd::Sort, boolean _skipAddHeader = false, str _extensionName = '')
+ {
+ str objectName = this.getObjectName(_object);
+ boolean insertIntoMap = false;
+ if (_object is AxMenu)
+ {
+ insertIntoMap = true;
+ currentElementMap = elementMap;
+ collectionMap.insert('MenuElements', elementMap);
+ }
+
+ TreeItemIdx parentIdx = super(_object, _idx, _formTreeAdd, _skipAddHeader, _extensionName);
+
+ if (currentElementMap != null
+ && (_object is AxMenuElement))
+ {
+ currentElementMap.insert(objectName, parentIdx);
+ }
+
+ if (insertIntoMap)
+ {
+ currentElementMap = null;
+ }
+
+ return parentIdx;
+ }
+
+]]>
+
+
+
+
\ No newline at end of file
diff --git a/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeQuery.xml b/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeQuery.xml
new file mode 100644
index 0000000..c366f76
--- /dev/null
+++ b/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeQuery.xml
@@ -0,0 +1,157 @@
+
+
+ ARBAOTObjectTreeQuery
+
+
+/// Override the Object Tree for Queries
+///
+[ARBAOTObjectType(ARBAOTObjectType::Query)]
+class ARBAOTObjectTreeQuery extends ARBAOTObjectTree
+{
+ Map dataSourceMap = new Map(Types::String, Types::Integer);
+ Map currentDsMap;
+ Map rangesMap = new Map(Types::String, Types::Integer);
+ Map currentRangesMap;
+
+}
+]]>
+
+
+ addExtensionCollection
+
+ /// Adds a collection of extensions to the tree
+ ///
+ /// The collection to add
+ /// The collection name
+ /// The extension name
+ protected void addExtensionCollection(System.Collections.IEnumerable _collection, str _collectionName, str _extensionName)
+ {
+ System.Collections.IEnumerator modsEnum;
+ switch (_collectionName)
+ {
+ case 'RootDataSources':
+ modsEnum = _collection.GetEnumerator();
+ if (collectionMap.exists('DataSources'))
+ {
+ Map fieldGroupsMap = collectionMap.lookup('DataSources');
+ TreeItemIdx rootNodeIdx = fieldGroupsMap.lookup('RootNode');
+ while (modsEnum.MoveNext())
+ {
+ this.addExtension(modsEnum.Current, rootNodeIdx, _extensionName);
+ }
+ }
+ break;
+ case 'DataSources':
+ modsEnum = _collection.GetEnumerator();
+ while (modsEnum.MoveNext())
+ {
+ AxQueryExtensionEmbeddedDataSource ds = modsEnum.Current;
+ this.addExtension(ds.DataSource, this.getNamedNode(dataSourceMap.lookup(ds.Parent), 'DataSources'), _extensionName);
+ }
+ break;
+ case 'Ranges':
+ modsEnum = _collection.GetEnumerator();
+ while (modsEnum.MoveNext())
+ {
+ AxQueryExtensionQueryDataSourceRange range = modsEnum.Current;
+ this.addExtension(range.QueryDataSourceRange, this.getNamedNode(dataSourceMap.lookup(range.Parent), 'Ranges'), _extensionName);
+ }
+ break;
+ case 'Relations':
+ modsEnum = _collection.GetEnumerator();
+ while (modsEnum.MoveNext())
+ {
+ AxQueryExtensionQueryDataSourceRelation relation = modsEnum.Current;
+ this.addExtension(relation.QueryDataSourceRelation, this.getNamedNode(dataSourceMap.lookup(relation.Parent), 'Relations'), _extensionName);
+ }
+ break;
+ case 'Fields':
+ modsEnum = _collection.GetEnumerator();
+ while (modsEnum.MoveNext())
+ {
+ AxQueryExtensionQueryDataSourceField field = modsEnum.Current;
+ this.addExtension(field.QueryDataSourceField, this.getNamedNode(dataSourceMap.lookup(field.Parent), 'Fields'), _extensionName);
+ }
+ break;
+ case 'OrderByFields':
+ modsEnum = _collection.GetEnumerator();
+ while (modsEnum.MoveNext())
+ {
+ AxQueryExtensionQueryOrderByField field = modsEnum.Current;
+ this.addExtension(field.QueryOrderByField, this.getNamedNode(dataSourceMap.lookup(field.Parent), 'OrderBy'), _extensionName);
+ }
+ break;
+ default:
+ super(_collection, _collectionName, _extensionName);
+ break;
+ }
+ }
+
+]]>
+
+
+ addTreeNode
+
+ /// Adds a new node to the tree
+ ///
+ /// The object to add
+ /// The tree index to add it under
+ /// The order it should add the node
+ /// The name of the extension it came from, if any
+ /// The tree index of the new node
+ public TreeItemIdx addTreeNode(anytype _object, TreeItemIdx _idx, int _formTreeAdd = FormTreeAdd::Sort, boolean _skipAddHeader = false, str _extensionName = '')
+ {
+ str objectName = this.getObjectName(_object);
+ boolean insertIntoMap = false;
+ if (_object is AxQuerySimpleRootDataSource)
+ {
+ insertIntoMap = true;
+ currentDsMap = dataSourceMap;
+ }
+
+ boolean insertIntoRangeMap = false;
+ if (_object is AxQuerySimpleDataSource)
+ {
+ insertIntoRangeMap = true;
+ currentRangesMap = rangesMap;
+ collectionMap.insert('Ranges', rangesMap);
+ }
+
+ TreeItemIdx parentIdx = super(_object, _idx, _formTreeAdd, _skipAddHeader, _extensionName);
+
+ if (currentDsMap != null
+ && (_object is AxQuerySimpleDataSource))
+ {
+ currentDsMap.insert(objectName, parentIdx);
+ }
+
+ if (insertIntoMap)
+ {
+ currentDsMap = null;
+ }
+
+ if (currentRangesMap != null
+ && (_object is AxQuerySimpleDataSourceRange))
+ {
+ currentRangesMap.insert(objectName, parentIdx);
+ }
+
+ if (insertIntoRangeMap)
+ {
+ currentRangesMap = null;
+ }
+
+ return parentIdx;
+ }
+
+]]>
+
+
+
+
\ No newline at end of file
diff --git a/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeTable.xml b/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeTable.xml
index 2f46872..ac8a9a2 100644
--- a/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeTable.xml
+++ b/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeTable.xml
@@ -27,16 +27,7 @@ class ARBAOTObjectTreeTable extends ARBAOTObjectTree
AxTable table = Xpp.MetadataSupport::GetTable(_aotNodeName);
if (table != null)
{
- TreeItemIdx rootIdx = this.updateObjectTree(table, table.Name);
- var tableExtensions = Xpp.MetadataSupport::GetTableExtensionsForTable(_aotNodeName);
- System.Collections.IEnumerator enumerator = tableExtensions.GetEnumerator();
-
- TreeItemIdx extensionsIdx = SysFormTreeControl::addTreeItem(treeControl, 'Extensions', rootIdx, tableExtensions, 0, true);
- while (enumerator.moveNext())
- {
- this.addTreeNode(enumerator.Current, extensionsIdx);
- }
- treeControl.select(rootIdx);
+ super(_aotNodeName);
}
else
{
@@ -45,6 +36,63 @@ class ARBAOTObjectTreeTable extends ARBAOTObjectTree
}
}
+]]>
+
+
+ addExtensionCollection
+
+ /// Adds a collection of extensions to the tree
+ ///
+ /// The collection to add
+ /// The collection name
+ /// The extension name
+ protected void addExtensionCollection(System.Collections.IEnumerable _collection, str _collectionName, str _extensionName)
+ {
+ switch (_collectionName)
+ {
+ case 'FieldGroupExtensions':
+ System.Collections.IEnumerator fieldGroupEnum = _collection.GetEnumerator();
+ if (collectionMap.exists('FieldGroups'))
+ {
+ Map fieldGroupsMap = collectionMap.lookup('FieldGroups');
+ while (fieldGroupEnum.MoveNext())
+ {
+ AxTableFieldGroupExtension fieldGroupExtension = fieldGroupEnum.Current;
+ TreeItemIdx parentIdx = fieldGroupsMap.lookup(fieldGroupExtension.Name);
+ parentIdx = treeControl.getChild(parentIdx); // Get the index of the Fields node
+ var fieldsEnum = fieldGroupExtension.Fields.GetEnumerator();
+ while (fieldsEnum.MoveNext())
+ {
+ this.addExtension(fieldsEnum.Current, parentIdx, _extensionName);
+ }
+ }
+ }
+ break;
+ case 'RelationExtensions':
+ System.Collections.IEnumerator relationEnum = _collection.GetEnumerator();
+ if (collectionMap.exists('Relations'))
+ {
+ Map relationsMap = collectionMap.lookup('Relations');
+ while (relationEnum.MoveNext())
+ {
+ AxTableRelationExtension relationExtension = relationEnum.Current;
+ TreeItemIdx parentIdx = relationsMap.lookup(relationExtension.Name);
+ parentIdx = treeControl.getChild(parentIdx); // Get the index of the Constraints node
+ var constraintsEnum = relationExtension.RelationConstraints.GetEnumerator();
+ while (constraintsEnum.MoveNext())
+ {
+ this.addExtension(constraintsEnum.Current, parentIdx, _extensionName);
+ }
+ }
+ }
+ break;
+ default:
+ super(_collection, _collectionName, _extensionName);
+ break;
+ }
+ }
+
]]>
diff --git a/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeView.xml b/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeView.xml
index 68a68b9..a55906d 100644
--- a/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeView.xml
+++ b/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTreeView.xml
@@ -13,6 +13,11 @@ using Microsoft.Dynamics.AX.Metadata.MetaModel;
[ARBAOTObjectType(ARBAOTObjectType::View)]
class ARBAOTObjectTreeView extends ARBAOTObjectTree
{
+ Map dataSourceMap = new Map(Types::String, Types::Integer);
+ Map currentDsMap;
+ Map rangesMap = new Map(Types::String, Types::Integer);
+ Map currentRangesMap;
+
}
]]>
@@ -28,16 +33,7 @@ class ARBAOTObjectTreeView extends ARBAOTObjectTree
AxView view = Xpp.MetadataSupport::GetView(_aotNodeName);
if (view != null)
{
- TreeItemIdx rootIdx = this.updateObjectTree(view, view.Name);
- var aotObjectExtensions = ArbelaXpp.MetadataSupport::GetViewExtensionsForView(_aotNodeName);
- System.Collections.IEnumerator enumerator = aotObjectExtensions.GetEnumerator();
-
- TreeItemIdx extensionsIdx = SysFormTreeControl::addTreeItem(treeControl, 'Extensions', rootIdx, aotObjectExtensions, 0, true);
- while (enumerator.moveNext())
- {
- this.addTreeNode(enumerator.Current, extensionsIdx);
- }
- treeControl.select(rootIdx);
+ super(_aotNodeName);
}
else
{
@@ -46,6 +42,120 @@ class ARBAOTObjectTreeView extends ARBAOTObjectTree
}
}
+]]>
+
+
+ addExtensionCollection
+
+ /// Adds a collection of extensions to the tree
+ ///
+ /// The collection to add
+ /// The collection name
+ /// The extension name
+ protected void addExtensionCollection(System.Collections.IEnumerable _collection, str _collectionName, str _extensionName)
+ {
+ System.Collections.IEnumerator modsEnum;
+ switch (_collectionName)
+ {
+ case 'DataSources':
+ modsEnum = _collection.GetEnumerator();
+ while (modsEnum.MoveNext())
+ {
+ AxQueryExtensionEmbeddedDataSource ds = modsEnum.Current;
+ this.addExtension(ds.DataSource, this.getNamedNode(dataSourceMap.lookup(ds.Parent), 'DataSources'), _extensionName);
+ }
+ break;
+ case 'Ranges':
+ modsEnum = _collection.GetEnumerator();
+ while (modsEnum.MoveNext())
+ {
+ AxQueryExtensionQueryDataSourceRange range = modsEnum.Current;
+ this.addExtension(range.QueryDataSourceRange, this.getNamedNode(dataSourceMap.lookup(range.Parent), 'Ranges'), _extensionName);
+ }
+ break;
+ case 'FieldGroupExtensions':
+ System.Collections.IEnumerator fieldGroupEnum = _collection.GetEnumerator();
+ if (collectionMap.exists('FieldGroups'))
+ {
+ Map fieldGroupsMap = collectionMap.lookup('FieldGroups');
+ while (fieldGroupEnum.MoveNext())
+ {
+ AxTableFieldGroupExtension fieldGroupExtension = fieldGroupEnum.Current;
+ TreeItemIdx parentIdx = fieldGroupsMap.lookup(fieldGroupExtension.Name);
+ parentIdx = treeControl.getChild(parentIdx); // Get the index of the Fields node
+ var fieldsEnum = fieldGroupExtension.Fields.GetEnumerator();
+ while (fieldsEnum.MoveNext())
+ {
+ this.addExtension(fieldsEnum.Current, parentIdx, _extensionName);
+ }
+ }
+ }
+ break;
+ default:
+ super(_collection, _collectionName, _extensionName);
+ break;
+ }
+ }
+
+]]>
+
+
+ addTreeNode
+
+ /// Adds a new node to the tree
+ ///
+ /// The object to add
+ /// The tree index to add it under
+ /// The order it should add the node
+ /// The name of the extension it came from, if any
+ /// The tree index of the new node
+ public TreeItemIdx addTreeNode(anytype _object, TreeItemIdx _idx, int _formTreeAdd = FormTreeAdd::Sort, boolean _skipAddHeader = false, str _extensionName = '')
+ {
+ str objectName = this.getObjectName(_object);
+ boolean insertIntoMap = false;
+ if (_object is AxQuerySimpleRootDataSource)
+ {
+ insertIntoMap = true;
+ currentDsMap = dataSourceMap;
+ }
+
+ boolean insertIntoRangeMap = false;
+ if (_object is AxQuerySimpleDataSource)
+ {
+ insertIntoRangeMap = true;
+ currentRangesMap = rangesMap;
+ collectionMap.insert('Ranges', rangesMap);
+ }
+
+ TreeItemIdx parentIdx = super(_object, _idx, _formTreeAdd, _skipAddHeader, _extensionName);
+
+ if (currentDsMap != null
+ && (_object is AxQuerySimpleDataSource))
+ {
+ currentDsMap.insert(objectName, parentIdx);
+ }
+
+ if (insertIntoMap)
+ {
+ currentDsMap = null;
+ }
+
+ if (currentRangesMap != null
+ && (_object is AxQuerySimpleDataSourceRange))
+ {
+ currentRangesMap.insert(objectName, parentIdx);
+ }
+
+ if (insertIntoRangeMap)
+ {
+ currentRangesMap = null;
+ }
+
+ return parentIdx;
+ }
+
]]>
diff --git a/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTypeAttribute.xml b/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTypeAttribute.xml
index d45931b..d2d6f79 100644
--- a/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTypeAttribute.xml
+++ b/Metadata/AOTBrowser/AOTBrowser/AxClass/ARBAOTObjectTypeAttribute.xml
@@ -43,7 +43,7 @@ public class ARBAOTObjectTypeAttribute extends SysAttribute implements SysExtens
/// The cache key
public str parmCacheKey()
{
- return classStr(ARBAOTObjectTypeAttribute) + ';' + enum2Symbol(enumNum(ARBAOTObjectType), objectType);
+ return classStr(ARBAOTObjectTypeAttribute) + ';' + int2str(enum2int(objectType));
}
]]>
diff --git a/Projects/AOTBrowser/AOTBrowser/AOTBrowser.rnrproj b/Projects/AOTBrowser/AOTBrowser/AOTBrowser.rnrproj
index bae4a31..2df7560 100644
--- a/Projects/AOTBrowser/AOTBrowser/AOTBrowser.rnrproj
+++ b/Projects/AOTBrowser/AOTBrowser/AOTBrowser.rnrproj
@@ -64,6 +64,11 @@
ARBAOTObjectTree
Classes\ARBAOTObjectTree
+
+ Content
+ ARBAOTObjectTreeBaseEnum
+ Classes\ARBAOTObjectTreeBaseEnum
+
Content
ARBAOTObjectTreeDataEntity
@@ -74,6 +79,16 @@
ARBAOTObjectTreeForm
Classes\ARBAOTObjectTreeForm
+
+ Content
+ ARBAOTObjectTreeMenu
+ Classes\ARBAOTObjectTreeMenu
+
+
+ Content
+ ARBAOTObjectTreeQuery
+ Classes\ARBAOTObjectTreeQuery
+
Content
ARBAOTObjectTreeTable
diff --git a/Projects/ARB_TestExtensions/ARB_TestExtensions.sln b/Projects/ARB_TestExtensions/ARB_TestExtensions.sln
new file mode 100644
index 0000000..c9e61b3
--- /dev/null
+++ b/Projects/ARB_TestExtensions/ARB_TestExtensions.sln
@@ -0,0 +1,19 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FC65038C-1B2F-41E1-A629-BED71D161FFF}") = "ARB_TestExtensions (ISV) [Fleet Management]", "ARB_TestExtensions\ARB_TestExtensions.rnrproj", "{6AB4B3C7-DA0E-4E26-94DF-40C165B1366A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6AB4B3C7-DA0E-4E26-94DF-40C165B1366A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6AB4B3C7-DA0E-4E26-94DF-40C165B1366A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Projects/ARB_TestExtensions/ARB_TestExtensions/ARB_TestExtensions.rnrproj b/Projects/ARB_TestExtensions/ARB_TestExtensions/ARB_TestExtensions.rnrproj
new file mode 100644
index 0000000..9346d1d
--- /dev/null
+++ b/Projects/ARB_TestExtensions/ARB_TestExtensions/ARB_TestExtensions.rnrproj
@@ -0,0 +1,61 @@
+
+
+
+ Debug
+ AnyCPU
+ $(MSBuildProgramFiles32)\MSBuild\Microsoft\Dynamics\AX
+ ARBTestExt
+ v4.6
+ bin
+ 2.0
+ {6ab4b3c7-da0e-4e26-94df-40c165b1366a}
+ ARB_TestExtensions
+ ARB_TestExtensions
+ Class
+
+
+ Debug
+ False
+ False
+
+
+ initial
+ AnyCPU
+ False
+ False
+
+
+ true
+ false
+
+
+
+
+
+
+
+
+
+ Content
+ ABC.ARBTestExt
+ Base Enum Extensions\ABC.ARBTestExt
+
+
+ Content
+ AssetTableDepreciation.ARBTestExt
+ Simple Query Extensions\AssetTableDepreciation.ARBTestExt
+
+
+ Content
+ AbbreviationsStaging.ARBTestExt
+ Table Extensions\AbbreviationsStaging.ARBTestExt
+
+
+ Content
+ AccountantElectronicAddressView_BR.ARBTestExt
+ View Extensions\AccountantElectronicAddressView_BR.ARBTestExt
+
+
+
+
+
\ No newline at end of file