From cb91a46dfcab3f466ce9f5569e72ad2f42b4bca6 Mon Sep 17 00:00:00 2001 From: Michael Hoffmeister Date: Wed, 8 Nov 2023 19:14:19 +0100 Subject: [PATCH] * update --- .../DispEditHelperEntities.cs | 23 +- .../DispEditHelperExtensions.cs | 592 ++++++++++++++++++ .../DispEditHelperSammModules.cs | 98 +-- src/AasxPackageLogic/VisualAasxElements.cs | 15 + 4 files changed, 627 insertions(+), 101 deletions(-) create mode 100644 src/AasxPackageLogic/DispEditHelperExtensions.cs diff --git a/src/AasxPackageLogic/DispEditHelperEntities.cs b/src/AasxPackageLogic/DispEditHelperEntities.cs index 49a289b74..67e758744 100644 --- a/src/AasxPackageLogic/DispEditHelperEntities.cs +++ b/src/AasxPackageLogic/DispEditHelperEntities.cs @@ -2301,13 +2301,27 @@ public void DisplayOrEditAasEntityConceptDescription( relatedReferable: cd, superMenu: superMenu); }; - // check if to display special order for SAMM - var specialOrderSAMM = DispEditHelperSammModules.CheckReferableForSammExtensionType(cd) != null; - if (specialOrderSAMM) + // experimental: SMT elements + + Action lambdaSmtExt = () => + { + DisplayOrEditEntitySmtExtensions( + env, stack, cd.Extensions, + (v) => { cd.Extensions = v; }, + relatedReferable: cd, superMenu: superMenu); + }; + + // check if to display special order for SAMM, SMT + var specialOrderSAMM_SMT = + DispEditHelperSammModules.CheckReferableForSammExtensionType(cd) != null + || DispEditHelperExtensions.CheckReferableForSmtExtensionType(cd) != null; + + if (specialOrderSAMM_SMT) { lambdaIdf(); lambdaRf(true); lambdaSammExt(); + lambdaSmtExt(); this.AddGroup(stack, "Continue Referable:", levelColors.MainSection); lambdaIsCaseOf(); @@ -2326,7 +2340,8 @@ public void DisplayOrEditAasEntityConceptDescription( lambdaIsCaseOf(); lambdaEDS(false); lambdaSammExt(); - } + lambdaSmtExt(); + } } public void DisplayOrEditAasEntityValueReferencePair( diff --git a/src/AasxPackageLogic/DispEditHelperExtensions.cs b/src/AasxPackageLogic/DispEditHelperExtensions.cs new file mode 100644 index 000000000..44d6328f5 --- /dev/null +++ b/src/AasxPackageLogic/DispEditHelperExtensions.cs @@ -0,0 +1,592 @@ +/* +Copyright (c) 2018-2023 Festo SE & Co. KG +Author: Michael Hoffmeister + +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; +using AdminShellNS; +using AnyUi; +using Extensions; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Windows.Media; +using System.Xaml; +using VDS.RDF.Parsing; +using VDS.RDF; +using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window; +using Aas = AasCore.Aas3_0; +using Samm = AasCore.Samm2_2_0; +using System.Text.RegularExpressions; +using System.Runtime.Intrinsics.X86; +using Lucene.Net.Tartarus.Snowball.Ext; +using Lucene.Net.Util; +using System.Runtime.Serialization; +using J2N.Text; +using Lucene.Net.Codecs; +using VDS.RDF.Writing; +using AngleSharp.Text; +using System.Web.Services.Description; +using static AasxPackageLogic.DispEditHelperBasics; +using System.Collections; +using static Lucene.Net.Documents.Field; +using VDS.RDF.Query.Algebra; +using Microsoft.VisualBasic.ApplicationServices; +using static Lucene.Net.Queries.Function.ValueSources.MultiFunction; +using System.Windows.Controls; +using System.DirectoryServices; +using AngleSharp.Dom; +using Aml.Engine.CAEX; + +namespace AasxPackageLogic +{ + /// + /// This class extends the AAS meta model editing function for those related to + /// SAMM (Semantic Aspect Meta Model) elements. + /// + public class DispEditHelperExtensions : DispEditHelperModules + { + public static void SammExtensionHelperUpdateJson(Aas.IExtension se, Type smtType, SmtModelElement smtInst) + { + // trivial + if (se == null || smtType == null || smtInst == 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(smtInst, smtType, settings); + } + catch (Exception ex) + { + LogInternally.That.SilentlyIgnoredError(ex); + } + + // save this to the extension + se.Value = json; + se.ValueType = DataTypeDefXsd.String; + } + + /// + /// Shall provide rather quick access to information .. + /// + public static SmtModelElement CheckReferableForSmtExtensionType(Aas.IReferable rf) + { + // access + if (rf?.Extensions == null) + return null; + + // find any? + foreach (var se in rf.Extensions) + if (se.SemanticId?.IsValid() == true && se.SemanticId.Keys.Count == 1) + { + var t = SmtModelElements.GetTypeInstFromUri(se.SemanticId.Keys[0].Value); + if (t != null) + return t; + } + + // 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) + if (se.SemanticId?.IsValid() == true && se.SemanticId.Keys.Count == 1) + { + // get type + var smtTypeInst = SmtModelElements.GetTypeInstFromUri(se.SemanticId.Keys[0].Value); + if (smtTypeInst == null) + continue; + + // get instance data + SmtModelElement sammInst = null; + + // try to de-serializa extension value + try + { + if (se.Value != null) + sammInst = JsonConvert.DeserializeObject(se.Value, smtTypeInst.GetType()) as SmtModelElement; + } + 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.SammIdSets.GetAnyNameFromSammType(sammType); + } + + public void DisplayOrEditEntitySmtExtensions( + Aas.Environment env, + AnyUiStackPanel stack, + List smtExtension, + Action> setOutput, + string[] addPresetNames = null, List[] addPresetKeyLists = null, + Aas.IReferable relatedReferable = null, + AasxMenu superMenu = null) + { + // access + if (stack == null) + return; + + // members + this.AddGroup(stack, "SMT extensions \u00ab experimental \u00bb :", levelColors.MainSection); + + this.AddHintBubble( + stack, hintMode, + new[] { + new HintCheck( + () => { return smtExtension == null || + smtExtension.Count < 1; }, + "For modelling Submodel template specifications (SMT), a set of particular attributes " + + "to the elements of SMTs are specified. These attributes can be added as specific " + + "Qualifiers or via adding an extension as a whole.", + breakIfTrue: true, severityLevel: HintCheck.Severity.Notice), + new HintCheck( + () => { return smtExtension.Where(p => Samm.Util.HasSammSemanticId(p)).Count() > 1; }, + "Only one SMT extension is allowed per element.", + breakIfTrue: true), + }); + if (this.SafeguardAccess( + stack, this.repo, smtExtension, "SMT extensions:", "Create data element!", + v => + { + setOutput?.Invoke(new List()); + return new AnyUiLambdaActionRedrawEntity(); + })) + { + // head control + if (editMode) + { + // let the user control the number of references + this.AddActionPanel( + stack, "Spec. records:", repo: repo, + superMenu: superMenu, + ticketMenu: new AasxMenu() + .AddAction("add-smt-attributes", "Add attribute set", + "Add the attribute set as a whole.") + .AddAction("delete-last", "Delete last extension", + "Deletes last extension."), + ticketAction: (buttonNdx, ticket) => + { + if (buttonNdx == 0) + { + // new + var newSet = new SmtAttributeSet(); + + // now add + smtExtension.Add( + new Aas.Extension( + name: newSet.GetSelfName(), + semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, + (new[] { + new Aas.Key(KeyTypes.GlobalReference, + "" + newSet.GetSelfUri()) + }) + .Cast().ToList()), + value: "")); + } + + // remove + if (buttonNdx == 1) + { + if (smtExtension.Count > 0) + smtExtension.RemoveAt(smtExtension.Count - 1); + else + setOutput?.Invoke(null); + } + + this.AddDiaryEntry(relatedReferable, new DiaryEntryStructChange()); + return new AnyUiLambdaActionRedrawEntity(); + }); + } + + // now use the normal mechanism to deal with editMode or not .. + if (smtExtension != null && smtExtension.Count > 0) + { + var numSammExt = 0; + + for (int i = 0; i < smtExtension.Count; i++) + { + // get type + var se = smtExtension[i]; + var idSetType = Samm.SammIdSets.GetAnyIdSetTypeFromUrn(Samm.Util.GetSammUrn(se)); + if (idSetType?.Item1 == null || idSetType.Item2 == null) + continue; + var sammType = idSetType.Item2; + var idSet = idSetType.Item1; + + // remeber as detected .. (for later dialogs described above!) + if (detectedIdSet == null) + detectedIdSet = idSet; + + // more then one? + this.AddHintBubble( + stack, hintMode, + new[] { + new HintCheck( + () => numSammExt > 0, + "Only one SAMM extension per ConceptDescription allowed!", + breakIfTrue: true)}); + + // indicate + 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 = 50, + MinWidth = 50, + Child = new AnyUiTextBlock() + { + Text = "" + ri.Abbreviation, + HorizontalAlignment = AnyUiHorizontalAlignment.Center, + VerticalAlignment = AnyUiVerticalAlignment.Center, + Foreground = new AnyUiBrush(ri.Foreground), + Background = AnyUi.AnyUiBrushes.Transparent, + FontSize = 2.0, + FontWeight = AnyUiFontWeight.Bold + }, + HorizontalAlignment = AnyUiHorizontalAlignment.Center, + VerticalAlignment = AnyUiVerticalAlignment.Center, + Margin = new AnyUiThickness(5, 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 + Samm.ModelElement sammInst = null; + if (false) + { + // Note: right now, create fresh instance + sammInst = Activator.CreateInstance(sammType, new object[] { }) as Samm.ModelElement; + if (sammInst == null) + { + stack.Add(new AnyUiLabel() { Content = "(unable to create instance data)" }); + continue; + } + } + else + { + // try to de-serializa extension value + try + { + if (se.Value != null) + sammInst = JsonConvert.DeserializeObject(se.Value, sammType) as Samm.ModelElement; + } + catch (Exception ex) + { + LogInternally.That.SilentlyIgnoredError(ex); + sammInst = null; + } + + if (sammInst == null) + { + sammInst = Activator.CreateInstance(sammType, new object[] { }) as Samm.ModelElement; + } + } + + SammExtensionHelperAddCompleteModelElement( + env, idSet, stack, + sammInst: sammInst, + relatedReferable: relatedReferable, + setValue: (si) => + { + SammExtensionHelperUpdateJson(se, si.GetType(), si); + }); + + } + } + } + } + + } + + /// + /// Shall be implemented by all non-abstract model elements + /// + public interface ISmtSelfDescription + { + /// + /// get short name, which can als be used to distinguish elements. + /// + string GetSelfName(); + + /// + /// Get URN of this element class. + /// + string GetSelfUri(); + } + + /// + /// This class provides generators for Qualifiers, Extension etc. + /// in order to express preset-based information e.g. Cardinality + /// + public static class AasPresetHelper + { + /// + /// Semantically different, but factually equal to FormMultiplicity + /// + public enum SmtCardinality { ZeroToOne = 0, One, ZeroToMany, OneToMany }; + + public static Aas.IQualifier CreateQualifierSmtCardinality(SmtCardinality card) + { + return new Aas.Qualifier( + type: "SMT/Cardinality", + valueType: DataTypeDefXsd.String, + kind: QualifierKind.TemplateQualifier, + semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, + (new Aas.IKey[] { + new Aas.Key(KeyTypes.GlobalReference, + "https://admin-shell.io/SubmodelTemplates/Cardinality/1/0") + }).ToList()), + value: "" + card); + } + + public static Aas.IQualifier CreateQualifierSmtAllowedValue(string regex) + { + return new Aas.Qualifier( + type: "SMT/AllowedValue", + valueType: DataTypeDefXsd.String, + kind: QualifierKind.TemplateQualifier, + semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, + (new Aas.IKey[] { + new Aas.Key(KeyTypes.GlobalReference, + "https://admin-shell.io/SubmodelTemplates/AllowedValue/1/0") + }).ToList()), + value: "" + regex); + } + + public static Aas.IQualifier CreateQualifierSmtExampleValue(string exampleValue) + { + return new Aas.Qualifier( + type: "SMT/ExampleValue", + valueType: DataTypeDefXsd.String, + kind: QualifierKind.TemplateQualifier, + semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, + (new Aas.IKey[] { + new Aas.Key(KeyTypes.GlobalReference, + "https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0") + }).ToList()), + value: "" + exampleValue); + } + + public static Aas.IQualifier CreateQualifierSmtDefaultValue(string defaultValue) + { + return new Aas.Qualifier( + type: "SMT/DefaultValue", + valueType: DataTypeDefXsd.String, + kind: QualifierKind.TemplateQualifier, + semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, + (new Aas.IKey[] { + new Aas.Key(KeyTypes.GlobalReference, + "https://admin-shell.io/SubmodelTemplates/DefaultValue/1/0") + }).ToList()), + value: "" + defaultValue); + } + + public static Aas.IQualifier CreateQualifierSmtEitherOr(string equivalencyClass) + { + return new Aas.Qualifier( + type: "SMT/EitherOr", + valueType: DataTypeDefXsd.String, + kind: QualifierKind.TemplateQualifier, + semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, + (new Aas.IKey[] { + new Aas.Key(KeyTypes.GlobalReference, + "https://admin-shell.io/SubmodelTemplates/Cardinality/1/0") + }).ToList()), + value: "" + equivalencyClass); + } + + public static Aas.IQualifier CreateQualifierSmtRequiredLang(string reqLang) + { + return new Aas.Qualifier( + type: "SMT/RequiredLang", + valueType: DataTypeDefXsd.String, + kind: QualifierKind.TemplateQualifier, + semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, + (new Aas.IKey[] { + new Aas.Key(KeyTypes.GlobalReference, + "https://admin-shell.io/SubmodelTemplates/RequiredLang/1/0") + }).ToList()), + value: "" + reqLang); + } + } + + /// + /// Abstract base class for information for Submodel template specifications. + /// + public class SmtModelElement + { + } + + /// + /// Holds the possible attributes for an SMT specification per element + /// as a whole. + /// + public class SmtAttributeSet : SmtModelElement, ISmtSelfDescription + { + // self description + public string GetSelfName() => "smt-attrtibute-set"; + public string GetSelfUri() => "https://admin-shell.io/SubmodelTemplates/smt-attribute-set/v1/0"; + + // attributes + + /// + /// This Qualifier allows to specify, how many SubmodelElement + /// instances of this SMT element are allowed in the actual + /// collection (hierarchy level of the Submodel). + /// + public AasPresetHelper.SmtCardinality Cardinality { get; set; } = AasPresetHelper.SmtCardinality.One; + + /// + /// The Qualifier.value defines an id of an equivalence class. + /// Only ids in the range[A-Za-z0-9] are allowed. + /// If multiple SMT elements feature the same equivalence class, + /// only one of these are allowed in the actual collection + /// (hierarchy level of the Submodel). + /// + public string EitherOr { get; set; } = ""; + + /// + /// Specifies the initial value of the SubmodelElement instance, + /// when it is created for the first time. + /// + public string InitialValue { get; set; } = ""; + + /// + /// Specifies the default value of the SubmodelElement instance. + /// Often, this might designate a neutral, zero or empty value + /// depending on the valueType of a SMT element. + /// + public string DefaultValue { get; set; } = ""; + + /// + /// Specifies an example value of the SubmodelElement instance, + /// in order to allow the user to better understand the intention + /// and possible values of a SubmodelElement instance. + /// + public string ExampleValue { get; set; } = ""; + + /// + /// Specifies a set of allowed continous numerical ranges. + /// Multiple ranges can be given by delimiting them by '|'. + /// A single range is defined by interval start and end, + /// either including or excluding the given number. + /// Interval start and end are delimited by ','; + /// '.' is the decimal point. + /// '*' allows to enter the default value + /// + public string AllowedRange { get; set; } = ""; + + /// + /// Specifies a regular expression validating the idShort of the + /// created SubmodelElement instance. The format shall + /// conform to POSIX extended regular expressions. + /// + public string AllowedIdShort { get; set; } = ""; + + /// + /// Specifies a regular expression validating the value of the created + /// SubmodelElement instance in its string representation. The format + /// shall conform to POSIX extended regular expressions. + /// + public string AllowedValue { get; set; } = ""; + + /// + /// If the SMT element is a multi language property (MLP), + /// specifies the required languages, which shall be given. + /// Multiple languages can be given by multiple Qualifiers. + /// Multiple languages can be given by delimiting them by '|' . + /// Languages are specified either by ISO 639-1 or ISO 639-2 codes. + /// + public string RequiredLang { get; set; } = ""; + + /// + /// Specifies the user access mode for SubmodelElement instance. + /// When a Submodel is received from another party, if set to + /// Read/Only, then the user shall not change the value. + /// + public string AccessMode { get; set; } = ""; + } + + public class SmtModelElements + { + public static Dictionary AllElements = + new Dictionary(); + + static SmtModelElements() + { + Action add = (sme) => + { + if (sme is ISmtSelfDescription sd) + AllElements.Add(sd.GetSelfUri(), sme); + }; + + add(new SmtAttributeSet()); + } + + public static SmtModelElement GetTypeInstFromUri(string uri) + { + foreach (var x in AllElements.Values) + if (x is ISmtSelfDescription ssd && ssd.GetSelfUri() == uri) + return x; + return null; + } + } + +} diff --git a/src/AasxPackageLogic/DispEditHelperSammModules.cs b/src/AasxPackageLogic/DispEditHelperSammModules.cs index 01e17bb4b..65f8a0c7c 100644 --- a/src/AasxPackageLogic/DispEditHelperSammModules.cs +++ b/src/AasxPackageLogic/DispEditHelperSammModules.cs @@ -48,7 +48,7 @@ namespace AasxPackageLogic /// This class extends the AAS meta model editing function for those related to /// SAMM (Semantic Aspect Meta Model) elements. /// - public class DispEditHelperSammModules : DispEditHelperModules + public class DispEditHelperSammModules : DispEditHelperExtensions { public SammIdSet SammExtensionHelperSelectSammVersion(IEnumerable idsets) { @@ -2306,102 +2306,6 @@ public void ExportSammModelFromConceptDescription( } } - /// - /// This class provides generators for Qualifiers, Extension etc. - /// in order to express preset-based information e.g. Cardinality - /// - public static class AasPresetHelper - { - /// - /// Semantically different, but factually equal to FormMultiplicity - /// - public enum SmtCardinality { ZeroToOne = 0, One, ZeroToMany, OneToMany }; - - public static Aas.IQualifier CreateQualifierSmtCardinality(SmtCardinality card) - { - return new Aas.Qualifier( - type: "SMT/Cardinality", - valueType: DataTypeDefXsd.String, - kind: QualifierKind.TemplateQualifier, - semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, - (new Aas.IKey[] { - new Aas.Key(KeyTypes.GlobalReference, - "https://admin-shell.io/SubmodelTemplates/Cardinality/1/0") - }).ToList()), - value: "" + card); - } - - public static Aas.IQualifier CreateQualifierSmtAllowedValue(string regex) - { - return new Aas.Qualifier( - type: "SMT/AllowedValue", - valueType: DataTypeDefXsd.String, - kind: QualifierKind.TemplateQualifier, - semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, - (new Aas.IKey[] { - new Aas.Key(KeyTypes.GlobalReference, - "https://admin-shell.io/SubmodelTemplates/AllowedValue/1/0") - }).ToList()), - value: "" + regex); - } - - public static Aas.IQualifier CreateQualifierSmtExampleValue(string exampleValue) - { - return new Aas.Qualifier( - type: "SMT/ExampleValue", - valueType: DataTypeDefXsd.String, - kind: QualifierKind.TemplateQualifier, - semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, - (new Aas.IKey[] { - new Aas.Key(KeyTypes.GlobalReference, - "https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0") - }).ToList()), - value: "" + exampleValue); - } - - public static Aas.IQualifier CreateQualifierSmtDefaultValue(string defaultValue) - { - return new Aas.Qualifier( - type: "SMT/DefaultValue", - valueType: DataTypeDefXsd.String, - kind: QualifierKind.TemplateQualifier, - semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, - (new Aas.IKey[] { - new Aas.Key(KeyTypes.GlobalReference, - "https://admin-shell.io/SubmodelTemplates/DefaultValue/1/0") - }).ToList()), - value: "" + defaultValue); - } - - public static Aas.IQualifier CreateQualifierSmtEitherOr(string equivalencyClass) - { - return new Aas.Qualifier( - type: "SMT/EitherOr", - valueType: DataTypeDefXsd.String, - kind: QualifierKind.TemplateQualifier, - semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, - (new Aas.IKey[] { - new Aas.Key(KeyTypes.GlobalReference, - "https://admin-shell.io/SubmodelTemplates/Cardinality/1/0") - }).ToList()), - value: "" + equivalencyClass); - } - - public static Aas.IQualifier CreateQualifierSmtRequiredLang(string reqLang) - { - return new Aas.Qualifier( - type: "SMT/RequiredLang", - valueType: DataTypeDefXsd.String, - kind: QualifierKind.TemplateQualifier, - semanticId: new Aas.Reference(ReferenceTypes.ExternalReference, - (new Aas.IKey[] { - new Aas.Key(KeyTypes.GlobalReference, - "https://admin-shell.io/SubmodelTemplates/RequiredLang/1/0") - }).ToList()), - value: "" + reqLang); - } - } - /// /// This class provides a layered access to a list (a IEnumerable) of /// Aas.IIdentifiable. This access could be provided by each time diff --git a/src/AasxPackageLogic/VisualAasxElements.cs b/src/AasxPackageLogic/VisualAasxElements.cs index 520fe7dc3..5c54077e5 100644 --- a/src/AasxPackageLogic/VisualAasxElements.cs +++ b/src/AasxPackageLogic/VisualAasxElements.cs @@ -1251,6 +1251,21 @@ public override void RefreshFromMainData() } } + // SMT + var smtTypeInst = DispEditHelperExtensions.CheckReferableForSmtExtensionType(theCD); + if (smtTypeInst != null && smtTypeInst is ISmtSelfDescription ssd) + { + // completely reformat the Caption + this.Caption = $"\"{"" + theCD.IdShort}\" \u29fc{ssd.GetSelfName()}\u29fd {"" + theCD.Id}"; + + // see https://colors.muz.li/palette/0028CD/004190/2915cd/00cd90/009064 + this.TagString = "SMT"; + this.Border = new AnyUiColor(0xff009064); + this.Background = new AnyUiColor(0xff00cd90); + this.TagBg = new AnyUiColor(0xff009064); + this.TagFg = new AnyUiColor(0xffffffff); + } + //TODO (jtikekar, 0000-00-00): support DataSpecificationPhysicalUnit #if SupportDataSpecificationPhysicalUnit var dspu = theCD.GetPhysicalUnit();