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