diff --git a/src/AasxCore.Samm2_2_0/SammClasses.cs b/src/AasxCore.Samm2_2_0/SammClasses.cs
index 23cce5c1e..4d163d5cf 100644
--- a/src/AasxCore.Samm2_2_0/SammClasses.cs
+++ b/src/AasxCore.Samm2_2_0/SammClasses.cs
@@ -12,6 +12,7 @@ This source code may use other Open Source software components (see LICENSE.txt)
using System.Linq.Expressions;
using System.Reflection.PortableExecutable;
using System.Runtime.Serialization;
+using AasCore.Aas3_0;
using AdminShellNS;
using Extensions;
using Newtonsoft.Json;
@@ -45,12 +46,30 @@ public interface ISammSelfDescription
/// get short name, which can als be used to distinguish elements.
/// Exmaple: samm-x
///
- public string GetSelfName();
+ string GetSelfName();
///
/// Get URN of this element class.
///
- public string GetSelfUrn();
+ string GetSelfUrn();
+ }
+
+ ///
+ /// Shall be implemented in order to give hints about the
+ /// (hierarchical) structuring of elements
+ ///
+ public interface ISammStructureModel
+ {
+ ///
+ /// True, if a top element of a hierarchy
+ ///
+ bool IsTopElement();
+
+ ///
+ /// Iterate over all the SAMM elements referenced from this instance
+ /// without further recursion (see AasCore).
+ ///
+ IEnumerable DescendOnce();
}
///
@@ -59,6 +78,10 @@ public interface ISammSelfDescription
///
public class ModelElement
{
+ // Note:
+ // The SAMM meta model details, that every element has a name.
+ // For AAS, the name is given by the Id of the ConceptDescription
+
///
/// Human readable name in a specific language. This attribute may be defined multiple
/// times for different languages but only once for a specific language. There should
@@ -237,23 +260,11 @@ public enum SammEncoding
///
public class SammReference
{
- private string Rf { get; set; }
-
- public SammReference(string rf)
- {
- Rf = rf;
- }
-
- public static implicit operator string(SammReference sr)
- {
- if (sr == null)
- return "";
- return sr.Rf;
- }
+ public string Value { get; set; }
- public static implicit operator SammReference(string rf)
+ public SammReference(string val = "")
{
- return new SammReference(rf);
+ Value = val;
}
}
@@ -404,12 +415,30 @@ public class FixedPointConstraint : Constraint
///
///
///
- public class Characteristic : ModelElement
+ public class Characteristic : ModelElement, ISammSelfDescription, ISammStructureModel
{
+ // self description
+ public string GetSelfName() => "samm-characteristic";
+ public string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Characteristic";
+
+ // structure model
+ public bool IsTopElement() => false;
+ public IEnumerable DescendOnce()
+ {
+ if (DataType != null)
+ yield return DataType;
+ }
+
///
/// Reference to a scalar or complex (Entity) data type. See Section "Type System" in the Aspect Meta Model.
+ /// Also the scalar data types (e.g. xsd:decimal) are treated as references in the first degree.
///
- public SammDataType? DataType { get; set; }
+ public SammReference DataType { get; set; }
+
+ public Characteristic()
+ {
+ DataType = new SammReference("");
+ }
}
///
@@ -422,8 +451,8 @@ public class Characteristic : ModelElement
public class Trait : Characteristic, ISammSelfDescription
{
// self description
- public string GetSelfName() => "samm-trait";
- public string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Trait";
+ public new string GetSelfName() => "samm-trait";
+ public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Trait";
///
/// The Characterstic that is being constrained.
@@ -447,8 +476,8 @@ public class Trait : Characteristic, ISammSelfDescription
public class Quantifiable : Characteristic, ISammSelfDescription
{
// self description
- public string GetSelfName() => "samm-quantifiable";
- public string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Quantifiable";
+ public new string GetSelfName() => "samm-quantifiable";
+ public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Quantifiable";
///
/// Reference to a Unit as defined in the Unit catalog
@@ -464,16 +493,13 @@ public class Quantifiable : Characteristic, ISammSelfDescription
public class Measurement : Characteristic, ISammSelfDescription
{
// self description
- public string GetSelfName() => "samm-measurement";
- public string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Measurement";
+ public new string GetSelfName() => "samm-measurement";
+ public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Measurement";
///
/// Reference to a Unit as defined in the Unit catalog
///
- [JsonIgnore]
public SammReference Unit { get; set; }
- [JsonProperty(PropertyName = "Unit")]
- public string JsonUnit { get => "" + Unit; }
public Measurement()
{
@@ -489,8 +515,8 @@ public Measurement()
public class Enumeration : Characteristic, ISammSelfDescription
{
// self description
- public string GetSelfName() => "samm-enumeration";
- public string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Enumeration";
+ public new string GetSelfName() => "samm-enumeration";
+ public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Enumeration";
///
/// List of possible values. The dataType of each of the values must match the
@@ -534,8 +560,8 @@ public State()
public class Duration : Characteristic, ISammSelfDescription
{
// self description
- public string GetSelfName() => "samm-duration";
- public string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Duration";
+ public new string GetSelfName() => "samm-duration";
+ public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Duration";
///
/// Reference to a Unit as defined in the Unit catalog. The referenced unit or its referenceUnit
@@ -551,7 +577,7 @@ public class Duration : Characteristic, ISammSelfDescription
public Duration()
{
- Unit = "";
+ Unit = new SammReference();
}
}
@@ -564,8 +590,8 @@ public Duration()
public class Collection : Characteristic, ISammSelfDescription
{
// self description
- public string GetSelfName() => "samm-collection";
- public string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Collection";
+ public new string GetSelfName() => "samm-collection";
+ public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Collection";
///
/// Reference to a Characteristic which describes the individual elements contained in the Collection.
@@ -574,7 +600,7 @@ public class Collection : Characteristic, ISammSelfDescription
public Collection()
{
- ElementCharacteristic = "";
+ ElementCharacteristic = new SammReference();
}
}
@@ -643,8 +669,8 @@ public class TimeSeries : SortedSet, ISammSelfDescription
public class Code : Characteristic, ISammSelfDescription
{
// self description
- public string GetSelfName() => "samm-code";
- public string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Code";
+ public new string GetSelfName() => "samm-code";
+ public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Code";
}
///
@@ -657,8 +683,8 @@ public class Code : Characteristic, ISammSelfDescription
public class Either : Characteristic, ISammSelfDescription
{
// self description
- public string GetSelfName() => "samm-either";
- public string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Either";
+ public new string GetSelfName() => "samm-either";
+ public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#Either";
///
/// The left side of the Either. The attribute references another Characteristic which describes the value.
@@ -686,8 +712,8 @@ public Either()
public class SingleEntity : Characteristic, ISammSelfDescription
{
// self description
- public string GetSelfName() => "samm-single-entity";
- public string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#SingleEntity";
+ public new string GetSelfName() => "samm-single-entity";
+ public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#SingleEntity";
}
///
@@ -701,8 +727,8 @@ public class SingleEntity : Characteristic, ISammSelfDescription
public class StructuredValue: Characteristic, ISammSelfDescription
{
// self description
- public string GetSelfName() => "samm-structured-value";
- public string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#StructuredValue";
+ public new string GetSelfName() => "samm-structured-value";
+ public new string GetSelfUrn() => "urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#StructuredValue";
///
/// The regular expression used to deconstruct the value into parts that are mapped to separate
@@ -725,6 +751,76 @@ public StructuredValue()
}
}
+ ///
+ /// A Property represents a named value. This element is optional and can appear multiple times in a model ([0..n]).
+ /// One Property has exactly one Characteristic.
+ ///
+ ///
+ public class Property : ModelElement, ISammSelfDescription, ISammStructureModel
+ {
+ // self description
+ public string GetSelfName() => "samm-property";
+ public string GetSelfUrn() => "urn:bamm:io.openmanufacturing:meta-model:1.0.0#Property";
+
+ // structure model
+ public bool IsTopElement() => false;
+ public IEnumerable DescendOnce()
+ {
+ if (Characteristic != null)
+ yield return Characteristic;
+ }
+
+ ///
+ /// This provides an example value for the Property, which requires that the entered data type has been defined
+ /// in a corresponding Characteristic. It is important to ensure that the data type has the correct format.
+ /// Find the Data Types (SAMM 2.1.0) with an example value.
+ ///
+ public string? ExampleValue { get; set; }
+
+ ///
+ /// One Property has exactly one Characteristic.
+ ///
+ public SammReference Characteristic { get; set; }
+
+ public Property()
+ {
+ Characteristic = new SammReference("");
+ }
+ }
+
+ ///
+ /// An Aspect is the root element of each Aspect Model and has a number of Properties, Events, and Operations.
+ /// This element is mandatory and must appear exactly once per model.
+ /// It has any number of Properties, Operations and Events ([0..n]).
+ ///
+ public class Aspect : ModelElement, ISammSelfDescription, ISammStructureModel
+ {
+ // self description
+ public string GetSelfName() => "samm-aspect";
+ public string GetSelfUrn() => "urn:bamm:io.openmanufacturing:meta-model:1.0.0#Aspect";
+
+ // structure model
+ public bool IsTopElement() => true;
+ public IEnumerable DescendOnce()
+ {
+ if (Properties != null)
+ foreach (var x in Properties)
+ yield return x;
+ }
+
+ // own
+ public List Properties { get; set; }
+ public List Events { get; set; }
+ public List Operations { get; set; }
+
+ public Aspect()
+ {
+ Properties = new List();
+ Events = new List();
+ Operations = new List();
+ }
+ }
+
///
/// Provides some constant values to the model.
///
@@ -750,6 +846,127 @@ public static class Constants
typeof(SingleEntity),
typeof(StructuredValue)
};
+
+ public static Type[] AddableElements =
+ {
+ // Top level
+ typeof(Aspect),
+ typeof(Property),
+ // Characteristic
+ typeof(Characteristic),
+ typeof(Trait),
+ typeof(Quantifiable),
+ typeof(Measurement),
+ typeof(Enumeration),
+ typeof(State),
+ typeof(Duration),
+ typeof(Collection),
+ typeof(List),
+ typeof(Set),
+ typeof(SortedSet),
+ typeof(TimeSeries),
+ typeof(Code),
+ typeof(Either),
+ typeof(SingleEntity),
+ typeof(StructuredValue)
+ };
+
+ ///
+ /// Holds information, how model element types should be rendered on the screen.
+ ///
+ public class SammElementRenderInfo
+ {
+ public string DisplayName = "";
+ public string Abbreviation = "";
+ public uint Foreground = 0x00000000;
+ public uint Background = 0x00000000;
+ }
+
+ private static Dictionary _renderInfo =
+ new Dictionary();
+
+ public static SammElementRenderInfo? GetRenderInfo(Type t)
+ {
+ if (t != null && _renderInfo.ContainsKey(t))
+ return _renderInfo[t];
+ return null;
+ }
+
+ static Constants()
+ {
+ _renderInfo.Add(typeof(Aspect), new SammElementRenderInfo() {
+ DisplayName = "Aspect",
+ Abbreviation = "A",
+ Foreground = 0xFF000000,
+ Background = 0xFF8298E0
+ });
+
+ _renderInfo.Add(typeof(Property), new SammElementRenderInfo()
+ {
+ DisplayName = "Property",
+ Abbreviation = "P",
+ Foreground = 0xFF000000,
+ Background = 0xFFC5C8D4
+ });
+
+ _renderInfo.Add(typeof(Characteristic), new SammElementRenderInfo()
+ {
+ DisplayName = "Characteristic",
+ Abbreviation = "C",
+ Foreground = 0xFF000000,
+ Background = 0xFFD6E2A6
+ });
+
+ _renderInfo.Add(typeof(IEntity), new SammElementRenderInfo()
+ {
+ DisplayName = "Entity",
+ Abbreviation = "E",
+ Foreground = 0xFF000000,
+ Background = 0xFFAEADE0
+ });
+
+ _renderInfo.Add(typeof(UnaryExpression), new SammElementRenderInfo()
+ {
+ DisplayName = "Unit",
+ Abbreviation = "U",
+ Foreground = 0xFF000000,
+ Background = 0xFFB9AB50
+ });
+
+ _renderInfo.Add(typeof(Constraint), new SammElementRenderInfo()
+ {
+ DisplayName = "Constraint",
+ Abbreviation = "C",
+ Foreground = 0xFF000000,
+ Background = 0xFF74AEAF
+ });
+
+ _renderInfo.Add(typeof(Trait), new SammElementRenderInfo()
+ {
+ DisplayName = "Trait",
+ Abbreviation = "T",
+ Foreground = 0xFF000000,
+ Background = 0xFF74AEAF
+ });
+
+ _renderInfo.Add(typeof(Operation), new SammElementRenderInfo()
+ {
+ DisplayName = "Operation",
+ Abbreviation = "O",
+ Foreground = 0xFF000000,
+ Background = 0xFFD5BFDA
+ });
+
+ _renderInfo.Add(typeof(EventArgs), new SammElementRenderInfo()
+ {
+ DisplayName = "Event",
+ Abbreviation = "E",
+ Foreground = 0xFF000000,
+ Background = 0xFFB9D8FA
+ });
+ }
+
+ public static uint RenderBackground = 0xFFEFEFF0;
}
public static class Util
@@ -776,13 +993,18 @@ public static bool HasSammSemanticId(Aas.IHasSemantics hasSem)
public static Dictionary SammUrnToType = new Dictionary();
+ public static Dictionary SammTypeToName = new Dictionary();
+
static Util()
{
// dictionary from URN to type
- foreach (var st in Constants.AddableCharacteristic)
+ foreach (var st in Constants.AddableElements)
{
if (Activator.CreateInstance(st, new object[] { }) is ISammSelfDescription ssd)
+ {
SammUrnToType.Add(ssd.GetSelfUrn().ToLower(), st);
+ SammTypeToName.Add(st, "" + ssd.GetSelfName());
+ }
}
}
@@ -794,5 +1016,63 @@ static Util()
return SammUrnToType[urn.ToLower()];
return null;
}
+
+ public static string? GetNameFromSammType(Type? sammType)
+ {
+ if (sammType == null)
+ return null;
+ if (SammTypeToName.ContainsKey(sammType))
+ return SammTypeToName[sammType];
+ return null;
+ }
+
+ ///
+ /// Any chars which are sitting between "meaningful words" within a URI
+ ///
+ public static char[] UriDelimiters = new[] {
+ ':', '/', '+', '?', '[', ']', '@', '!', '$', '&',
+ '\'', '(', ')', '*', ',', ';', '.', '=' };
+
+ public static string? ShortenUri(string? uri)
+ {
+ // corner case
+ if (uri == null)
+ return null;
+ uri = uri.Trim();
+ if (uri.Length < 1)
+ return "";
+
+ // simple case: find a anchor / '#'
+ var trimPos = uri.LastIndexOf('#');
+
+ // be more flexible?
+ if (trimPos < 0)
+ trimPos = uri.LastIndexOfAny(UriDelimiters);
+
+ // ok, trim
+ if (trimPos >= 0)
+ uri = uri.Substring(0, trimPos);
+
+ // return
+ return uri;
+ }
+
+ public static string? LastWordOfUri(string? uri, string elseStr = "")
+ {
+ // corner case
+ if (uri == null)
+ return null;
+ uri = uri.Trim();
+ if (uri.Length < 1)
+ return "";
+
+ // find delimiter?
+ var li = uri.LastIndexOf('#');
+ if (li < 0)
+ li = uri.LastIndexOfAny(UriDelimiters);
+ if (li > 0)
+ return uri.Substring(li + 1);
+ return elseStr;
+ }
}
}
\ No newline at end of file
diff --git a/src/AasxCsharpLibrary/AdminShellCollections.cs b/src/AasxCsharpLibrary/AdminShellCollections.cs
index 32e6774ab..414f16168 100644
--- a/src/AasxCsharpLibrary/AdminShellCollections.cs
+++ b/src/AasxCsharpLibrary/AdminShellCollections.cs
@@ -48,6 +48,8 @@ public IEnumerable> Keys
return dict.Values;
}
}
+
+ public void Clear() => dict.Clear();
}
public class DoubleSidedDict
diff --git a/src/AasxCsharpLibrary/Extensions/ExtendConceptDescription.cs b/src/AasxCsharpLibrary/Extensions/ExtendConceptDescription.cs
index 27a9490ad..7d764e485 100644
--- a/src/AasxCsharpLibrary/Extensions/ExtendConceptDescription.cs
+++ b/src/AasxCsharpLibrary/Extensions/ExtendConceptDescription.cs
@@ -310,5 +310,45 @@ public static void AddIsCaseOf(this IConceptDescription cd,
cd.IsCaseOf = new List();
cd.IsCaseOf.Add(ico);
}
- }
+
+ ///
+ /// Returns false, if there is another element with same idShort in the list
+ ///
+ public static bool CheckIdShortIsUnique(this List cds, string idShort)
+ {
+ idShort = idShort?.Trim();
+ if (idShort == null || idShort.Length < 1)
+ return false;
+
+ var res = true;
+ foreach (var smw in cds)
+ if (smw != null && smw.IdShort != null && smw.IdShort == idShort)
+ {
+ res = false;
+ break;
+ }
+
+ return res;
+ }
+
+ ///
+ /// Creates ids with numerical index according to template string, until a unique idShort is found
+ ///
+ public static string IterateIdShortTemplateToBeUnique(this List cds, string idShortTemplate, int maxNum)
+ {
+ if (idShortTemplate == null || maxNum < 1 || !idShortTemplate.Contains("{0"))
+ return null;
+
+ int i = 1;
+ while (i < maxNum)
+ {
+ var ids = string.Format(idShortTemplate, i);
+ if (cds.CheckIdShortIsUnique(ids))
+ return ids;
+ i++;
+ }
+
+ return null;
+ }
+ }
}
diff --git a/src/AasxPackageExplorer/options-debug.MIHO.json b/src/AasxPackageExplorer/options-debug.MIHO.json
index d0b980ff7..fbca1b4d3 100644
--- a/src/AasxPackageExplorer/options-debug.MIHO.json
+++ b/src/AasxPackageExplorer/options-debug.MIHO.json
@@ -18,7 +18,7 @@
/* "AasxToLoad": "C:\\MIHO\\Develop\\Aasx\\repo\\Festo_SPAU_VR3.aasx", */
// "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\PxC_aasT_2900542_ELR_H3_I_SC__24DC_500AC_0_6.aasx",
// "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\Festo_SPAU-B2R-H-G18FD-L-PNLK-PNVBA-M8U_V3c.aasx",
- "AasxToLoad": "C:\\Users\\homi0002\\Desktop\\TempDesktop\\230619 Digi Twin Festo AASX Assessment\\231002_Feedback_1\\8001203_64be10f8-d4c8-4226-a56b-901b9fcbe29c_fb1.aasx",
+ // "AasxToLoad": "C:\\Users\\homi0002\\Desktop\\TempDesktop\\230619 Digi Twin Festo AASX Assessment\\231002_Feedback_1\\8001203_64be10f8-d4c8-4226-a56b-901b9fcbe29c_fb1.aasx",
// "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\01_Festo_SPAU_VR3_DPPV2.aasx",
// "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\bomtest1.aasx",
// "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\leitungssatz_tier1.aasx",
@@ -26,6 +26,7 @@
// "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\SMT_Sample_B.aasx",
// "AuxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\SMT_Sample_A.aasx",
// "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\00_FestoDemoBox-Module-2-Kopie2.aasx",
+ "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\samm_spiel.aasx",
"WindowLeft": 200,
"WindowTop": -1,
"WindowWidth": 900,
diff --git a/src/AasxPackageLogic/DispEditHelperBasics.cs b/src/AasxPackageLogic/DispEditHelperBasics.cs
index c667a669d..3ce0f4540 100644
--- a/src/AasxPackageLogic/DispEditHelperBasics.cs
+++ b/src/AasxPackageLogic/DispEditHelperBasics.cs
@@ -300,7 +300,8 @@ public void AddKeyValueExRef(
string[] auxButtonToolTips = null,
AnyUiLambdaActionBase takeOverLambdaAction = null,
bool limitToOneRowForNoEdit = false,
- int comboBoxMinWidth = -1)
+ int comboBoxMinWidth = -1,
+ bool noFirstColumnWidth = false)
{
AddKeyValue(
view, key, value, nullValue, repo, setValue, comboBoxItems, comboBoxIsEditable,
@@ -308,7 +309,8 @@ public void AddKeyValueExRef(
auxButtonTitles, auxButtonToolTips, takeOverLambdaAction,
(value == null) ? 0 : value.GetHashCode(), containingObject: containingObject,
limitToOneRowForNoEdit: limitToOneRowForNoEdit,
- comboBoxMinWidth: comboBoxMinWidth);
+ comboBoxMinWidth: comboBoxMinWidth,
+ noFirstColumnWidth: noFirstColumnWidth);
}
///
@@ -344,7 +346,8 @@ public void AddKeyValue(
Nullable valueHash = null,
object containingObject = null,
bool limitToOneRowForNoEdit = false,
- int comboBoxMinWidth = -1)
+ int comboBoxMinWidth = -1,
+ bool noFirstColumnWidth = false)
{
// draw anyway?
if (repo != null && value == null)
@@ -380,7 +383,8 @@ public void AddKeyValue(
g.Margin = new AnyUiThickness(0, 1, 0, 1);
var gc1 = new AnyUiColumnDefinition();
gc1.Width = AnyUiGridLength.Auto;
- gc1.MinWidth = this.GetWidth(FirstColumnWidth.Standard);
+ if (!noFirstColumnWidth)
+ gc1.MinWidth = this.GetWidth(FirstColumnWidth.Standard);
g.ColumnDefinitions.Add(gc1);
var gc2 = new AnyUiColumnDefinition();
gc2.Width = new AnyUiGridLength(1.0, AnyUiGridUnitType.Star);
diff --git a/src/AasxPackageLogic/DispEditHelperEntities.cs b/src/AasxPackageLogic/DispEditHelperEntities.cs
index 430c356b6..a35efc61f 100644
--- a/src/AasxPackageLogic/DispEditHelperEntities.cs
+++ b/src/AasxPackageLogic/DispEditHelperEntities.cs
@@ -859,7 +859,7 @@ public void DisplayOrEditAasEntityAasEnv(
minWidth: 250,
items: new[] {
"List index", "idShort", "Identification", "By AasSubmodel",
- "By SubmodelElements"
+ "By SubmodelElements", "Structured"
}),
(o) =>
{
diff --git a/src/AasxPackageLogic/DispEditHelperMiniModules.cs b/src/AasxPackageLogic/DispEditHelperMiniModules.cs
index dba2cb78f..e90369b01 100644
--- a/src/AasxPackageLogic/DispEditHelperMiniModules.cs
+++ b/src/AasxPackageLogic/DispEditHelperMiniModules.cs
@@ -981,7 +981,8 @@ public void ExtensionHelper(
padding: new AnyUiThickness(5, 0, 5, 0));
// special case: SAMM extension
- if (Samm.Util.HasSammSemanticId(extension))
+ // TODO: enable
+ if (false && Samm.Util.HasSammSemanticId(extension))
{
substack.Add(new AnyUiLabel()
{
diff --git a/src/AasxPackageLogic/DispEditHelperModules.cs b/src/AasxPackageLogic/DispEditHelperModules.cs
index 52bc3a0b6..48ead8eab 100644
--- a/src/AasxPackageLogic/DispEditHelperModules.cs
+++ b/src/AasxPackageLogic/DispEditHelperModules.cs
@@ -7,6 +7,7 @@ This source code is licensed under the Apache License 2.0 (see LICENSE.txt).
This source code may use other Open Source software components (see LICENSE.txt).
*/
+using AasCore.Samm2_2_0;
using AasxAmlImExport;
using AasxCompatibilityModels;
using AasxIntegrationBase;
@@ -19,6 +20,8 @@ This source code may use other Open Source software components (see LICENSE.txt)
using System.Data;
using System.IO;
using System.Linq;
+using System.Windows.Media;
+using System.Xaml;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window;
using Aas = AasCore.Aas3_0;
using Samm = AasCore.Samm2_2_0;
@@ -2403,6 +2406,252 @@ public void DisplayOrEditEntityFileResource(AnyUiStackPanel stack,
//
//
+ public Type SammExtensionHelperSelectSammType(Type[] addableElements)
+ {
+ // create choices
+ var fol = new List();
+ foreach (var stp in addableElements)
+ fol.Add(new AnyUiDialogueListItem("" + stp.Name, stp));
+
+ // prompt for this list
+ var uc = new AnyUiDialogueDataSelectFromList(
+ caption: "Select SAMM element type to add ..");
+ uc.ListOfItems = fol;
+ this.context.StartFlyoverModal(uc);
+ if (uc.Result && uc.ResultItem != null && uc.ResultItem.Tag != null &&
+ ((Type)uc.ResultItem.Tag).IsAssignableTo(typeof(Samm.ModelElement)))
+ return (Type)uc.ResultItem.Tag;
+ return null;
+ }
+
+ public void SammExtensionHelperUpdateJson(Aas.IExtension se, Type sammType, Samm.ModelElement sammInst)
+ {
+ // trivial
+ if (se == null || sammType == null || sammInst == null)
+ return;
+
+ // do a full fledged, carefull serialization
+ string json = "";
+ try
+ {
+ var settings = new JsonSerializerSettings
+ {
+ // SerializationBinder = new DisplayNameSerializationBinder(new[] { typeof(AasEventMsgEnvelope) }),
+ NullValueHandling = NullValueHandling.Ignore,
+ ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
+ TypeNameHandling = TypeNameHandling.None,
+ Formatting = Formatting.Indented
+ };
+ settings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
+ //settings.Converters.Add(new AdminShellConverters.AdaptiveAasIClassConverter(
+ // AdminShellConverters.AdaptiveAasIClassConverter.ConversionMode.AasCore));
+ json = JsonConvert.SerializeObject(sammInst, sammType, settings);
+ }
+ catch (Exception ex)
+ {
+ LogInternally.That.SilentlyIgnoredError(ex);
+ }
+
+ // save this to the extension
+ se.Value = json;
+ se.ValueType = DataTypeDefXsd.String;
+ }
+
+ public void SammExtensionHelperAddSammReference(
+ Aas.Environment env, AnyUiStackPanel stack, string caption,
+ Samm.ModelElement sammInst,
+ Aas.IReferable relatedReferable,
+ Samm.SammReference sr,
+ Action setValue,
+ bool noFirstColumnWidth = false)
+ {
+ AddKeyValueExRef(
+ stack, "" + caption, sammInst,
+ value: "" + sr?.Value, null, repo,
+ setValue: v =>
+ {
+ setValue?.Invoke(new Samm.SammReference((string)v));
+ return new AnyUiLambdaActionNone();
+ },
+ noFirstColumnWidth: noFirstColumnWidth,
+ auxButtonTitles: new[] { "Existing ..", "New ..", "Jump" },
+ auxButtonToolTips: new[] {
+ "Select existing ConceptDescription.",
+ "Create a new ConceptDescription for SAMM use.",
+ "Jump to ConceptDescription with given Id."
+ },
+ auxButtonLambda: (i) =>
+ {
+ if (i == 0)
+ {
+ var k2 = SmartSelectAasEntityKeys(
+ packages,
+ PackageCentral.PackageCentral.Selector.MainAuxFileRepo,
+ "ConceptDescription");
+ if (k2 != null && k2.Count >= 1)
+ {
+ setValue?.Invoke(new Samm.SammReference("" + k2[0].Value));
+ return new AnyUiLambdaActionRedrawEntity();
+ }
+ }
+
+ if (i == 1)
+ {
+ // select type
+ var sammTypeToCreate = SammExtensionHelperSelectSammType(Samm.Constants.AddableElements);
+ if (sammTypeToCreate == null)
+ return new AnyUiLambdaActionNone();
+
+ // select name
+ var newUri = Samm.Util.ShortenUri(
+ "" + (relatedReferable as Aas.IIdentifiable)?.Id);
+ var uc = new AnyUiDialogueDataTextBox(
+ "New Id for SAMM element:",
+ symbol: AnyUiMessageBoxImage.Question,
+ maxWidth: 1400,
+ text: "" + newUri);
+ if (!this.context.StartFlyoverModal(uc))
+ return new AnyUiLambdaActionNone();
+ newUri = uc.Text;
+
+ // select idShort
+ var newIdShort = Samm.Util.LastWordOfUri(newUri);
+ var uc2 = new AnyUiDialogueDataTextBox(
+ "New idShort for SAMM element:",
+ symbol: AnyUiMessageBoxImage.Question,
+ maxWidth: 1400,
+ text: "" + newIdShort);
+ if (!this.context.StartFlyoverModal(uc2))
+ return new AnyUiLambdaActionNone();
+ newIdShort = uc2.Text;
+ if (newIdShort.HasContent() != true)
+ {
+ newIdShort = env?.ConceptDescriptions?
+ .IterateIdShortTemplateToBeUnique("samm{0:0000}", 9999);
+ }
+
+ // make sure, the name is a new, valid Id for CDs
+ if (newUri?.HasContent() != true ||
+ null != env?.FindConceptDescriptionById(newUri))
+ {
+ Log.Singleton.Error("Invalid (used?) Id for a new ConceptDescriptin. Aborting!");
+ return new AnyUiLambdaActionNone();
+ }
+
+ // add the new name to the current element
+ setValue?.Invoke(new Samm.SammReference(newUri));
+
+ // now create a new CD for the new SAMM element
+ var newCD = new Aas.ConceptDescription(
+ id: newUri,
+ idShort: newIdShort);
+
+ // create new SAMM element
+ var newSamm = Activator.CreateInstance(
+ sammTypeToCreate, new object[] { }) as Samm.ModelElement;
+
+ var newSammSsd = newSamm as Samm.ISammSelfDescription;
+
+ var newSammExt = new Aas.Extension(
+ name: "" + newSammSsd?.GetSelfName(),
+ semanticId: new Aas.Reference(ReferenceTypes.ExternalReference,
+ (new[] { new Aas.Key(KeyTypes.GlobalReference,
+ newSammSsd.GetSelfUrn()) })
+ .Cast().ToList()),
+ value: "");
+ newCD.Extensions = new List { newSammExt };
+
+ // fill with empty data content for SAMM
+ SammExtensionHelperUpdateJson(newSammExt, sammTypeToCreate, newSamm);
+
+ // save CD
+ env?.ConceptDescriptions?.Add(newCD);
+
+ // now, jump to this new CD
+ return new AnyUiLambdaActionRedrawAllElements(nextFocus: newCD, isExpanded: true);
+ }
+
+ if (i == 2 && sr?.Value?.HasContent() == true)
+ {
+ return new AnyUiLambdaActionNavigateTo(
+ new Aas.Reference(
+ Aas.ReferenceTypes.ModelReference,
+ new Aas.IKey[] {
+ new Aas.Key(KeyTypes.ConceptDescription, sr.Value)
+ }.ToList()));
+ }
+
+ return new AnyUiLambdaActionNone();
+ });
+ }
+
+ ///
+ /// Shall provide rather quick access to information ..
+ ///
+ public static Type CheckReferableForSammExtensionType(Aas.IReferable rf)
+ {
+ // access
+ if (rf?.Extensions == null)
+ return null;
+
+ // find any?
+ foreach (var se in rf.Extensions)
+ {
+ var sammType = Samm.Util.GetTypeFromUrn(Samm.Util.GetSammUrn(se));
+ if (sammType != null)
+ return sammType;
+ }
+
+ // no?
+ return null;
+ }
+
+ public static IEnumerable CheckReferableForSammElements(Aas.IReferable rf)
+ {
+ // access
+ if (rf?.Extensions == null)
+ yield break;
+
+ // find any?
+ foreach (var se in rf.Extensions)
+ {
+ // get type
+ var sammType = Samm.Util.GetTypeFromUrn(Samm.Util.GetSammUrn(se));
+ if (sammType == null)
+ continue;
+
+ // get instance data
+ ModelElement sammInst = null;
+
+ // try to de-serializa extension value
+ try
+ {
+ if (se.Value != null)
+ sammInst = JsonConvert.DeserializeObject(se.Value, sammType) as ModelElement;
+ }
+ catch (Exception ex)
+ {
+ LogInternally.That.SilentlyIgnoredError(ex);
+ sammInst = null;
+ }
+
+ if (sammInst == null)
+ continue;
+
+ // give back
+ yield return sammInst;
+ }
+ }
+
+ ///
+ /// Shall provide rather quick access to information ..
+ ///
+ /// Null, if not a SAMM model element
+ public static string CheckReferableForSammExtensionTypeName(Type sammType)
+ {
+ return Samm.Util.GetNameFromSammType(sammType);
+ }
+
public void DisplayOrEditEntitySammExtensions(
Aas.Environment env, AnyUiStackPanel stack,
List sammExtension,
@@ -2451,10 +2700,10 @@ public void DisplayOrEditEntitySammExtensions(
stack, "Spec. records:", repo: repo,
superMenu: superMenu,
ticketMenu: new AasxMenu()
- .AddAction("add-quantifiable", "Add Quantifiable",
- "A value which can be quantified and may have a unit.")
- .AddAction("add-measurement", "Add Measurement",
- "A measurement is a numeric value with an associated unit and quantity kind.")
+ .AddAction("add-aspect", "Add Aspect",
+ "Add single top level of any SAMM aspect model.")
+ .AddAction("add-property", "Add Property",
+ "Add a named value element to the aspect or its sub-entities.")
.AddAction("auto-enumeration", "Add Enumeration",
"An enumeration represents a list of possible values.")
.AddAction("auto-collection", "Add Collection",
@@ -2468,14 +2717,14 @@ public void DisplayOrEditEntitySammExtensions(
"Deletes last extension."),
ticketAction: (buttonNdx, ticket) =>
{
- Samm.Characteristic newChar = null;
+ Samm.ModelElement newChar = null;
switch (buttonNdx)
{
case 0:
- newChar = new Samm.Quantifiable();
+ newChar = new Samm.Aspect();
break;
case 1:
- newChar = new Samm.Measurement();
+ newChar = new Samm.Property();
break;
case 2:
newChar = new Samm.Enumeration();
@@ -2490,22 +2739,14 @@ public void DisplayOrEditEntitySammExtensions(
if (buttonNdx == 5)
{
- // add other
- var fol = new List();
- foreach (var stp in Samm.Constants.AddableCharacteristic)
- fol.Add(new AnyUiDialogueListItem("" + stp.Name, stp));
-
- // prompt for this list
- var uc = new AnyUiDialogueDataSelectFromList(
- caption: "Select SAMM element to add ..");
- uc.ListOfItems = fol;
- this.context.StartFlyoverModal(uc);
- if (uc.Result && uc.ResultItem != null && uc.ResultItem.Tag != null &&
- ((Type)uc.ResultItem.Tag).IsAssignableTo(typeof(Samm.Characteristic)))
+ // select
+ var sammTypeToCreate = SammExtensionHelperSelectSammType(Samm.Constants.AddableElements);
+
+ if (sammTypeToCreate != null)
{
// to which?
newChar = Activator.CreateInstance(
- (Type)uc.ResultItem.Tag, new object[] { }) as Samm.Characteristic;
+ sammTypeToCreate, new object[] { }) as Samm.ModelElement;
}
}
@@ -2535,6 +2776,8 @@ public void DisplayOrEditEntitySammExtensions(
// now use the normal mechanism to deal with editMode or not ..
if (sammExtension != null && sammExtension.Count > 0)
{
+ var numSammExt = 0;
+
for (int i = 0; i < sammExtension.Count; i++)
{
// get type
@@ -2542,15 +2785,53 @@ public void DisplayOrEditEntitySammExtensions(
var sammType = Samm.Util.GetTypeFromUrn(Samm.Util.GetSammUrn(se));
if (sammType == null)
{
- stack.Add(new AnyUiLabel() { Content = "(unknown SAMM type)" });
continue;
}
+ // more then one?
+ this.AddHintBubble(
+ stack, hintMode,
+ new[] {
+ new HintCheck(
+ () => numSammExt > 0,
+ "Only one SAMM extension per ConceptDescription allowed!",
+ breakIfTrue: true)});
+
// indicate
- this.AddGroup(stack, $"SAMM extension [{i+1}]: {sammType.Name}", levelColors.SubSection);
+ numSammExt++;
+
+ AnyUiFrameworkElement iconElem = null;
+ var ri = Samm.Constants.GetRenderInfo(sammType);
+ if (ri != null)
+ {
+ iconElem = new AnyUiBorder()
+ {
+ Background = new AnyUiBrush(ri.Background),
+ BorderBrush = new AnyUiBrush(ri.Foreground),
+ BorderThickness = new AnyUiThickness(2.0f),
+ MinHeight = 25,
+ MinWidth = 25,
+ Child = new AnyUiTextBlock()
+ {
+ Text = "" + ri.Abbreviation,
+ HorizontalAlignment = AnyUiHorizontalAlignment.Center,
+ VerticalAlignment = AnyUiVerticalAlignment.Center,
+ Foreground = new AnyUiBrush(ri.Foreground),
+ Background = AnyUi.AnyUiBrushes.Transparent,
+ },
+ HorizontalAlignment = AnyUiHorizontalAlignment.Center,
+ VerticalAlignment = AnyUiVerticalAlignment.Center,
+ Margin = new AnyUiThickness(0, 0, 10, 0),
+ SkipForTarget = AnyUiTargetPlatform.Browser
+ };
+ }
+
+ this.AddGroup(stack, $"SAMM extension [{i + 1}]: {sammType.Name}",
+ levelColors.SubSection.Bg, levelColors.SubSection.Fg,
+ iconElement: iconElem);
- // get instance data
- object sammInst = null;
+ // get instance data
+ object sammInst = null;
if (false)
{
// Note: right now, create fresh instance
@@ -2584,30 +2865,7 @@ public void DisplayOrEditEntitySammExtensions(
// editing actions need to asynchronously write back values
Action WriteSammInstBack = () =>
{
- // do a full fledged, carefull serialization
- string json = "";
- try
- {
- var settings = new JsonSerializerSettings
- {
- // SerializationBinder = new DisplayNameSerializationBinder(new[] { typeof(AasEventMsgEnvelope) }),
- NullValueHandling = NullValueHandling.Ignore,
- ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
- TypeNameHandling = TypeNameHandling.None,
- Formatting = Formatting.Indented
- };
- settings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
- //settings.Converters.Add(new AdminShellConverters.AdaptiveAasIClassConverter(
- // AdminShellConverters.AdaptiveAasIClassConverter.ConversionMode.AasCore));
- json = JsonConvert.SerializeObject(sammInst, sammType, settings);
- } catch (Exception ex)
- {
- LogInternally.That.SilentlyIgnoredError(ex);
- }
-
- // save this to the extension
- se.Value = json;
- se.ValueType = DataTypeDefXsd.String;
+ SammExtensionHelperUpdateJson(se, sammType, sammInst as Samm.ModelElement);
};
// okay, try to build up a edit field by reflection
@@ -2624,8 +2882,117 @@ public void DisplayOrEditEntitySammExtensions(
// List of SammReference?
if (pii.PropertyType.IsAssignableTo(typeof(List)))
{
- ;
- }
+ var lsr = (List)pii.GetValue(sammInst);
+
+ Action> lambdaSetValue = (v) =>
+ {
+ pii.SetValue(sammInst, v);
+ WriteSammInstBack();
+ };
+
+ if (this.SafeguardAccess(stack, repo, lsr, "" + pii.Name + ":",
+ "Create data element!",
+ v => {
+ lambdaSetValue(new List());
+ return new AnyUiLambdaActionRedrawEntity();
+ }))
+ {
+ // Head
+ var sg = this.AddSubGrid(stack, "" + pii.Name + ":",
+ rows: 1 + lsr.Count, cols: 2,
+ minWidthFirstCol: GetWidth(FirstColumnWidth.Standard),
+ colWidths: new[] { "*", "#" });
+
+ AnyUiUIElement.RegisterControl(
+ AddSmallButtonTo(sg, 0, 1,
+ margin: new AnyUiThickness(2, 2, 2, 2),
+ padding: new AnyUiThickness(5, 0, 5, 0),
+ content: "\u2795"),
+ (v) =>
+ {
+ lsr.Add(new Samm.SammReference());
+ lambdaSetValue(lsr);
+ return new AnyUiLambdaActionRedrawEntity();
+ });
+
+ // single references
+ for (int lsri = 0; lsri < lsr.Count; lsri++)
+ {
+ // remember lambda safe
+ var theLsri = lsri;
+
+ // Stack in the 1st column
+ var sp1 = AddSmallStackPanelTo(sg, 1 + lsri, 0);
+ SammExtensionHelperAddSammReference(
+ env, sp1, $"[{lsri}]",
+ (Samm.ModelElement)sammInst, relatedReferable,
+ lsr[lsri],
+ noFirstColumnWidth: true,
+ setValue: (v) => {
+ lsr[theLsri] = v;
+ lambdaSetValue(lsr);
+ });
+
+ if (false)
+ {
+ // remove button
+ AnyUiUIElement.RegisterControl(
+ AddSmallButtonTo(sg, 1 + lsri, 1,
+ margin: new AnyUiThickness(2, 2, 2, 2),
+ padding: new AnyUiThickness(5, 0, 5, 0),
+ content: "-"),
+ (v) =>
+ {
+ lsr.RemoveAt(theLsri);
+ lambdaSetValue(lsr);
+ return new AnyUiLambdaActionRedrawEntity();
+ });
+ }
+ else
+ {
+ // button [hamburger]
+ AddSmallContextMenuItemTo(
+ sg, 1 + lsri, 1,
+ "\u22ee",
+ repo, new[] {
+ "\u2702", "Delete",
+ "\u25b2", "Move Up",
+ "\u25bc", "Move Down",
+ },
+ margin: new AnyUiThickness(2, 2, 2, 2),
+ padding: new AnyUiThickness(5, 0, 5, 0),
+ menuItemLambda: (o) =>
+ {
+ var action = false;
+
+ if (o is int ti)
+ switch (ti)
+ {
+ case 0:
+ lsr.RemoveAt(theLsri);
+ action = true;
+ break;
+ case 1:
+ MoveElementInListUpwards(lsr, lsr[theLsri]);
+ action = true;
+ break;
+ case 2:
+ MoveElementInListDownwards(lsr, lsr[theLsri]);
+ action = true;
+ break;
+ }
+
+ if (action)
+ {
+ lambdaSetValue(lsr);
+ return new AnyUiLambdaActionRedrawEntity();
+ }
+ return new AnyUiLambdaActionNone();
+ });
+ }
+ }
+ }
+ }
// List of Constraint?
if (pii.PropertyType.IsAssignableTo(typeof(List)))
@@ -2636,52 +3003,73 @@ public void DisplayOrEditEntitySammExtensions(
// single SammReference?
if (pii.PropertyType.IsAssignableTo(typeof(Samm.SammReference)))
{
- // var tempKeys = new Aas.IKey[] {
- // new Aas.Key(KeyTypes.ConceptDescription, (string)pii.GetValue(sammInst))
- // }.ToList();
-
- //AddKeyListKeys(
- // stack, "" + pii.Name,
- // keys: tempKeys,
- // repo: repo,
- // packages: packages,
- // selector: PackageCentral.PackageCentral.Selector.MainAuxFileRepo,
- // addExistingEntities: "ConceptDescription",
- // emitCustomEvent: (o) =>
- // {
- // var valBack = "";
- // if (tempKeys.Count >= 1)
- // valBack = tempKeys[0].Value;
- // pii.SetValue(sammInst, valBack);
- // WriteSammInstBack();
- // });
-
var sr = (Samm.SammReference)pii.GetValue(sammInst);
- AddKeyValueExRef(
- stack, "" + pii.Name, sammInst,
- value: "" + sr, null, repo,
- setValue: v =>
- {
- pii.SetValue(sammInst, new Samm.SammReference((string) v));
+ SammExtensionHelperAddSammReference(
+ env, stack, "" + pii.Name, (Samm.ModelElement) sammInst, relatedReferable,
+ sr,
+ setValue: (v) => {
+ pii.SetValue(sammInst, v);
WriteSammInstBack();
- return new AnyUiLambdaActionNone();
- },
- auxButtonTitles: new[] { "Existing ..", "Jump" },
- auxButtonToolTips: new[] {
- "Select existing ConceptDescription",
- "Jump to ConceptDescription with id"
- },
- auxButtonLambda: (i) =>
- {
- return new AnyUiLambdaActionNone();
});
}
// List of string?
if (pii.PropertyType.IsAssignableTo(typeof(List)))
{
- ;
+ var ls = (List)pii.GetValue(sammInst);
+ if (ls == null)
+ {
+ Log.Singleton.Error("Internal error in SAMM element. Aborting.");
+ continue;
+ }
+
+ var sg = this.AddSubGrid(stack, "" + pii.Name + ":",
+ rows: 1 + ls.Count, cols: 2,
+ minWidthFirstCol: GetWidth(FirstColumnWidth.Standard),
+ colWidths: new[] { "*", "#" });
+
+ AnyUiUIElement.RegisterControl(
+ AddSmallButtonTo(sg, 0, 1,
+ margin: new AnyUiThickness(2, 2, 2, 2),
+ padding: new AnyUiThickness(5, 0, 5, 0),
+ content: "Add blank"),
+ (v) =>
+ {
+ ls.Add("");
+ pii.SetValue(sammInst, ls);
+ WriteSammInstBack();
+ return new AnyUiLambdaActionRedrawEntity();
+ });
+
+ for (int lsi=0; lsi
+ {
+ ls[theLsi] = (string)v;
+ pii.SetValue(sammInst, ls);
+ WriteSammInstBack();
+ return new AnyUiLambdaActionRedrawEntity();
+ });
+
+ AnyUiUIElement.RegisterControl(
+ AddSmallButtonTo(sg, 1 + lsi, 1,
+ margin: new AnyUiThickness(2, 2, 2, 2),
+ padding: new AnyUiThickness(5, 0, 5, 0),
+ content: "-"),
+ (v) =>
+ {
+ ls.RemoveAt(theLsi);
+ pii.SetValue(sammInst, ls);
+ WriteSammInstBack();
+ return new AnyUiLambdaActionRedrawEntity();
+ });
+ }
}
// single string?
diff --git a/src/AasxPackageLogic/VisualAasxElements.cs b/src/AasxPackageLogic/VisualAasxElements.cs
index 6339c216e..1070d7ea0 100644
--- a/src/AasxPackageLogic/VisualAasxElements.cs
+++ b/src/AasxPackageLogic/VisualAasxElements.cs
@@ -12,6 +12,7 @@ This source code may use other Open Source software components (see LICENSE.txt)
using AdminShellNS;
using AnyUi;
using Extensions;
+using Namotion.Reflection;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@@ -19,6 +20,7 @@ This source code may use other Open Source software components (see LICENSE.txt)
using System.Globalization;
using System.Linq;
using Aas = AasCore.Aas3_0;
+using Samm = AasCore.Samm2_2_0;
// ReSharper disable VirtualMemberCallInConstructor
@@ -561,7 +563,7 @@ public enum ItemType
"Environment", "AdministrationShells", "ConceptDescriptions", "Package", "OrphanSubmodels",
"AllSubmodels", "SupplementalFiles", "Value.Aas.Reference", "Empty", "Dummy" };
- public enum ConceptDescSortOrder { None = 0, IdShort, Id, BySubmodel, BySme }
+ public enum ConceptDescSortOrder { None = 0, IdShort, Id, BySubmodel, BySme, Structured }
public string thePackageSourceFn;
public AdminShellPackageEnv thePackage = null;
@@ -1229,7 +1231,27 @@ public override void RefreshFromMainData()
this.Info += " = " + vl;
}
- //TODO (jtikekar, 0000-00-00): support DataSpecificationPhysicalUnit
+ // SAMM?
+ var sammType = DispEditHelperModules.CheckReferableForSammExtensionType(theCD);
+ var sammName = DispEditHelperModules.CheckReferableForSammExtensionTypeName(sammType);
+ if (sammName?.HasContent() == true)
+ {
+ // completely reformat the Caption
+ this.Caption = $"\"{"" + theCD.IdShort}\" \uff5f{sammName}\uff60 {"" + theCD.Id}";
+
+ // do model element colors?
+ var ri = Samm.Constants.GetRenderInfo(sammType);
+ if (ri != null)
+ {
+ this.TagString = "" + ri.Abbreviation;
+ this.Border = new AnyUiColor(ri.Background);
+ this.Background = new AnyUiColor(Samm.Constants.RenderBackground);
+ this.TagBg = new AnyUiColor(ri.Background);
+ this.TagFg = new AnyUiColor(ri.Foreground);
+ }
+ }
+
+ //TODO (jtikekar, 0000-00-00): support DataSpecificationPhysicalUnit
#if SupportDataSpecificationPhysicalUnit
var dspu = theCD.GetPhysicalUnit();
if (dspu != null)
@@ -1242,7 +1264,7 @@ public override void RefreshFromMainData()
}
#endif
- }
+ }
}
// sorting
@@ -1502,6 +1524,9 @@ public class ListOfVisualElement : ObservableCollection
private VisualElementEnvironmentItem
tiPackage = null, tiEnv = null, tiShells = null, tiCDs = null;
+ private MultiValueDictionary _idToReferable =
+ new MultiValueDictionary();
+
private MultiValueDictionary _cdReferred =
new MultiValueDictionary();
@@ -1870,6 +1895,45 @@ private void GenerateInnerElementsForConceptDescriptions(
if (env == null || tiCDs == null || root == null)
return;
+ //
+ // try to approach structures first
+ //
+
+ if (tiCDs.CdSortOrder == VisualElementEnvironmentItem.ConceptDescSortOrder.Structured)
+ {
+ // recursive lambda!!
+ Action lambdaAddRecurse = null;
+ lambdaAddRecurse = (tiParent, cd) =>
+ {
+ // add
+ var tiCD = GenerateVisualElementsForSingleCD(cache, env, cd, tiParent);
+ _cdReferred.Add(cd, tiCD);
+
+ // look for descendants
+ foreach (var me in DispEditHelperModules.CheckReferableForSammElements(cd))
+ if (me is Samm.ISammStructureModel ssm)
+ foreach (var sr in ssm.DescendOnce())
+ {
+ // try to find SAMM elements
+ if (sr?.Value?.HasContent() != true || !_idToReferable.ContainsKey(sr.Value))
+ continue;
+
+ foreach (var y in _idToReferable[sr.Value])
+ if (y is Aas.IConceptDescription foundCD)
+ lambdaAddRecurse(tiCD, foundCD);
+ }
+ };
+
+ // visit top nodes to start the lambda
+ foreach (var cd in env.ConceptDescriptions)
+ foreach (var me in DispEditHelperModules.CheckReferableForSammElements(cd))
+ if (me is Samm.ISammStructureModel ssm && ssm.IsTopElement())
+ {
+ // add && recurse
+ lambdaAddRecurse(tiCDs, cd);
+ }
+ }
+
//
// create
//
@@ -1885,7 +1949,11 @@ private void GenerateInnerElementsForConceptDescriptions(
&& _cdToSm.ContainsKey(cd))
continue;
- GenerateVisualElementsForSingleCD(cache, env, cd, tiCDs);
+ if (tiCDs.CdSortOrder == VisualElementEnvironmentItem.ConceptDescSortOrder.Structured
+ && _cdReferred.ContainsKey(cd))
+ continue;
+
+ GenerateVisualElementsForSingleCD(cache, env, cd, tiCDs);
}
//
@@ -1938,19 +2006,33 @@ public void AddVisualElementsFromShellEnv(
OptionLazyLoadingFirst = lazyLoadingFirst;
// quickly connect the Identifiables to the environment
+ // and index them in order to quickly look them up
{
- foreach (var aas in env.AssetAdministrationShells)
+ _idToReferable.Clear();
+ _cdReferred.Clear();
+ _cdToSm.Clear();
+
+ foreach (var aas in env.AssetAdministrationShells)
if (aas != null)
+ {
aas.Parent = env;
+ _idToReferable.Add(aas.Id, aas);
+ }
foreach (var sm in env.Submodels)
if (sm != null)
+ {
sm.Parent = env;
+ _idToReferable.Add(sm.Id, sm);
+ }
- foreach (var cd in env.ConceptDescriptions)
+ foreach (var cd in env.ConceptDescriptions)
if (cd != null)
+ {
cd.Parent = env;
- }
+ _idToReferable.Add(cd.Id, cd);
+ }
+ }
// many operations
try
diff --git a/src/AasxWpfControlLibrary/DiplayVisualAasxElements.xaml.cs b/src/AasxWpfControlLibrary/DiplayVisualAasxElements.xaml.cs
index a370c194d..29462827a 100644
--- a/src/AasxWpfControlLibrary/DiplayVisualAasxElements.xaml.cs
+++ b/src/AasxWpfControlLibrary/DiplayVisualAasxElements.xaml.cs
@@ -475,8 +475,6 @@ public bool TrySelectVisualElement(VisualElementGeneric ve, bool? wishExpanded)
if (ve == null)
return false;
- // select (but no callback!)
- SelectSingleVisualElement(ve, preventFireItem: true);
if (wishExpanded == true)
{
@@ -490,7 +488,11 @@ public bool TrySelectVisualElement(VisualElementGeneric ve, bool? wishExpanded)
}
if (wishExpanded == false)
ve.IsExpanded = false;
- Woodoo(ve);
+
+ // select (but no callback!)
+ SelectSingleVisualElement(ve, preventFireItem: true);
+
+ Woodoo(ve);
this.Refresh();
diff --git a/src/AnyUi/AnyUiSmallWidgetToolkit.cs b/src/AnyUi/AnyUiSmallWidgetToolkit.cs
index 79c7c76c7..32968992d 100644
--- a/src/AnyUi/AnyUiSmallWidgetToolkit.cs
+++ b/src/AnyUi/AnyUiSmallWidgetToolkit.cs
@@ -620,9 +620,10 @@ public void AddGroup(AnyUiStackPanel view, string name, AnyUiBrushTuple colors,
public void AddGroup(AnyUiStackPanel view, string name, AnyUiBrush background, AnyUiBrush foreground,
bool requestAuxButton = false,
string auxButtonTitle = null, Func