DSL Tools #13 - Changing the Appearance of a Shape at Runtime

Finally I found some time to document this simple customization to the DSL Tools designers.

The requirement is as follows:

  • I have a given domain class - called Module Reference - that has a property called Main.
  • This domain property indicates if that particular class is the "most important" of that kind in the model.
  • This domain class as an association with another domain class - called Entity. That association allows me to connect multiple entities to any given module reference.
  • All the entities connected to the main module reference need to presented with a different color (different from the default shape color defined in the DSL definition model).

The domain model is the following:

Achieving this is quite simple:

1. Create a change rule to respond to the change in the Main property of the ModuleReference domain class:

   1: using System;
   2: using Microsoft.VisualStudio.Modeling;
   3: using Microsoft.VisualStudio.Modeling.Diagrams;
   4:  
   5: namespace MyModel
   6: {
   7:     /// <summary>
   8:     /// Defines a change rule for the ModuleReference domain class.
   9:     /// </summary>
  10:     [RuleOn(typeof(Primavera.Athena.Models.Reporting.ModuleReference), FireTime = TimeToFire.TopLevelCommit)]
  11:     public class ModuleReferenceChangeRule : ChangeRule
  12:     {
  13:         #region Public Methods
  14:  
  15:         /// <summary>
  16:         /// Alerts listeners that a property for an element has changed.
  17:         /// </summary>
  18:         /// <param name="e">Provides data for the ElementPropertyChanged event.</param>
  19:         public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
  20:         {
  21:             // Validations
  22:  
  23:             if (e == null)
  24:             {
  25:                 throw new ArgumentNullException("e");
  26:             }
  27:  
  28:             if (e.DomainProperty.Id.Equals(ModuleReference.MainDomainPropertyId))
  29:             {
  30:                 HandleMainChanged(e);
  31:             }
  32:  
  33:             // Default behavior
  34:  
  35:             base.ElementPropertyChanged(e);
  36:         }
  37:         
  38:         #endregion
  39:  
  40:         #region Private Methods
  41:  
  42:         /// <summary>
  43:         /// Handles changes in Main.
  44:         /// </summary>
  45:         /// <param name="e">The <see cref="Microsoft.VisualStudio.Modeling.ElementPropertyChangedEventArgs"/> instance containing the event data.</param>
  46:         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
  47:         private void HandleMainChanged(ElementPropertyChangedEventArgs e)
  48:         {
  49:             // Something changed?
  50:  
  51:             if (!e.OldValue.Equals(e.NewValue))
  52:             {
  53:                 // Get the current shape
  54:  
  55:                 ModuleReference moduleReference = e.ModelElement as ModuleReference;
  56:                 if (moduleReference != null)
  57:                 {
  58:                     // Update all entities colors
  59:  
  60:                     foreach (Entity entity in moduleReference.Entities)
  61:                     {
  62:                         LinkedElementCollection<PresentationElement> presentations =
  63:                             PresentationViewsSubject.GetPresentation(entity);
  64:                         EntityShape entityShape = null;
  65:  
  66:                         if (presentations.Count > 0)
  67:                         {
  68:                             entityShape = presentations[0] as EntityShape;
  69:                         }
  70:  
  71:                         if (entityShape != null)
  72:                         {
  73:                             entityShape.UpdateMainModuleReferencePresentation((bool)e.NewValue);
  74:                         }
  75:                     }
  76:                 }
  77:             }
  78:         }
  79:  
  80:         #endregion
  81:     }
  82: }

Note: I first find all the EntityShape instances that are connected with the current ModuleReference and then call the UpdateMainModuleReferencePresentation passing in the new value of the Main property.

2. Register this change rule:

   1: using System;
   2:  
   3: namespace MyModel
   4: {
   5:     /// <summary>
   6:     /// Custom ReportingModel domain model methods.
   7:     /// </summary>
   8:     public partial class ReportingModelDomainModel
   9:     {
  10:         #region Protected Methods
  11:  
  12:         /// <summary>
  13:         /// Returns the non-generated domain model types.
  14:         /// </summary>
  15:         /// <returns>An array of types.</returns>
  16:         protected override Type[] GetCustomDomainModelTypes()
  17:         {
  18:             // Return the rules that should be evaluated for
  19:             // the model
  20:  
  21:             return new System.Type[] 
  22:             {
  23:                 typeof(AssociationConnectorChangeRule), typeof(GenerateDefaultListChangeRule), typeof(ModuleReferenceChangeRule)
  24:             };
  25:         }
  26:  
  27:         #endregion
  28:     }
  29: }

3. Create a new partial class for the EntityShape class and implement the UpdateMainModuleReferencePresentation method:

   1: using System;
   2: using System.Drawing;
   3: using Microsoft.VisualStudio.Modeling.Diagrams;
   4:  
   5: namespace MyModel
   6: {
   7:     /// <summary>
   8:     /// Provides custom code for the EntityShape domain class.
   9:     /// </summary>
  10:     public partial class EntityShape
  11:     {
  12:         #region Internal Methods
  13:  
  14:         /// <summary>
  15:         /// Updates the entity presentation to reflect if the corresponding module reference is the main.
  16:         /// </summary>
  17:         /// <param name="moduleRefereceIsMain">A boolean that indicates if the entity is associated with the main module.</param>
  18:         internal void UpdateMainModuleReferencePresentation(bool moduleRefereceIsMain)
  19:         {
  20:             StyleSet style = this.StyleSet;
  21:             BrushSettings brush = style.GetOverriddenBrushSettings(DiagramBrushes.ShapeBackground);
  22:             if (brush == null)
  23:             {
  24:                 brush = new BrushSettings();
  25:             }
  26:  
  27:             if (moduleRefereceIsMain)
  28:             {
  29:                 brush.Color = Color.FromKnownColor(KnownColor.CadetBlue);
  30:             }
  31:             else
  32:             {
  33:                 brush.Color = Color.FromKnownColor(KnownColor.Lavender);
  34:             }
  35:  
  36:             style.OverrideBrush(DiagramBrushes.ShapeBackground, brush);
  37:         }
  38:  
  39:         #endregion
  40:     }
  41: }

That's it.

Published 30 October 08 05:43 by hgr
Filed under: ,

Comments

# Hugo Ribeiro said on October 30, 2008 5:45 PM:

Since I've been doing a number of posts on the DSL Tools, I thought it would be helpful to have a list

# Websites tagged "boolean" on Postsaver said on February 26, 2009 1:32 AM:

PingBack from http://www.postsaver.org/tags/boolean

Anonymous comments are disabled