Partager via


Personnalisation du comportement de la commande copier

Dans un langage spécifique au domaine créé (DSL) avec la visualisation de Visual Studio et modélisant le Kit de développement, vous pouvez modifier ce qui se produit lorsque l'utilisateur copier et coller des éléments.

Copie standard et comportement de collage

Pour activer la copie, affectez à la propriété d' activez le collage de copie du nœud d' Éditeur dans l'explorateur DÉSOLÉ.

Par défaut, lorsque l'utilisateur copie des éléments dans le presse-papiers, les éléments suivants sont également copiés :

  • Descendants incorporés des éléments sélectionnés.(Autrement dit, éléments les cibles des relations d'incorporation qui sont générés à des éléments copiés.)

  • liens de relation entre les éléments copiés.

cette règle s'applique de manière récursive aux éléments et aux liens copiés.

Éléments copiés et collés

Les éléments et les liens copiés sont sérialisés et stockés dans ElementGroupPrototype (EGP), qui est placé dans le presse-papiers.

Une idée des éléments copiés est également placée dans le presse-papiers.Cela permet à l'utilisateur de coller dans d'autres applications telles que Word.

L'utilisateur peut coller les éléments copiés vers une cible qui peut accepter des éléments selon la définition de langage spécifique à un domaine.Par exemple, dans un domaine (généré à partir de le modèle de solution de composants, l'utilisateur peut coller des ports sur les composants, mais pas sur le diagramme ; et peuvent coller des composants sur le diagramme, mais pas sur d'autres composants.

personnaliser la copie et le comportement de collage

Pour plus d'informations sur la personnalisation du modèle à l'aide de le code de programme, consultez Navigation et mise à jour d'un modèle dans le code de programme.

  • Activez ou désactivez copier, couper, et la coller.
    Dans l'explorateur DÉSOLÉ, affectez à la propriété d' activez le collage de copie du nœud d' Éditeur .

  • Les liens de copie vers la même cible. Par exemple, pour avoir un commentaire copié la zone boîte lié au même élément de la rubrique.
    définissez la propriété de copie de propagations du rôle à Copie de propagation à lier uniquement.Pour plus d'informations, consultez personnaliser le comportement de copie de lien.

  • éléments liés de copie. Par exemple, lorsque vous copiez un nouvel élément, des copies de tous les domaines liées de commentaire sont également exécutées.
    définissez la propriété de copie de propagations du rôle à Propagez la copie pour le lier et le rôle lecteur opposé.Pour plus d'informations, consultez personnaliser le comportement de copie de lien.

  • Dupliquez rapidement des éléments en copiant et collant. Normalement, l'élément que vous venez de copier est encore sélectionné, et vous ne pouvez pas coller le même type d'élément sur celui-ci.
    Ajoutez une directive de fusion d'élément à la classe de domaine, et définissez -le pour transférer des fusions à la classe parente.Cela qui le même effet sur les opérations glisser.Pour plus d'informations, consultez Personnalisation de la création et du mouvement des éléments.

    - ou -

    Sélectionnez le diagramme avant de coller des éléments, en substituant ClipboardCommandSet.ProcessOnPasteCommand().ajoutez ce code dans un fichier personnalisé dans le projet de DslPackage :

    namespace Company.MyDsl {
    using System.Linq;
    using Microsoft.VisualStudio.Modeling.Diagrams; 
    using Microsoft.VisualStudio.Modeling.Shell;
    partial class MyDslClipboardCommandSet
    {
      protected override void ProcessOnMenuPasteCommand()
      {
     // Deselect the current selection after copying:
     Diagram diagram = (this.CurrentModelingDocView as SingleDiagramDocView).Diagram;
        this.CurrentModelingDocView
         .SelectObjects(1, new object[] { diagram }, 0);
      }
    } }
    
  • Créez des liens supplémentaires lorsque les collages d'utilisateur vers une cible sélectionnée. Par exemple, lorsqu'une zone de commentaire est collé sur un élément, un lien est effectuée entre eux.
    Ajoutez une directive de fusion d'élément à la classe de domaine cible, et définissez -le pour traiter la fusion en ajoutant des liens.Cela qui le même effet sur les opérations glisser.Pour plus d'informations, consultez Personnalisation de la création et du mouvement des éléments.

    - ou -

    Substituez ClipboardCommandSet.ProcessOnPasteCommand() pour créer des liens supplémentaires après avoir appelé la méthode de base.

  • Personnalisez les formats dans lesquels les éléments peuvent être copiés dans les applications externes (par exemple, d'ajouter une bordure au formulaire bitmap.
    substitution MyDslClipboardCommandSet.ProcessOnMenuCopyCommand() dans le projet de DslPackage.

  • Personnaliser la façon dont les éléments sont copiés dans le presse-papiers par la Commande de copie, mais pas dans une opération glisser.
    substitution MyDslClipboardCommandSet.CopyModelElementsIntoElementGroupPrototype() dans le projet de DslPackage.

  • Conservez la disposition de forme via la copie et la coller.
    Lorsque l'utilisateur copie de plusieurs formes, vous pouvez conserver leurs positions relatives lorsqu'elles sont collées.Cette technique est illustrée par l'exemple dans VMSDK: Circuit Diagrams sample.

    Pour atteindre cet effet, ajoutez des formes et des connecteurs à l'ElementGroupPrototype copié.La méthode la plus pratique à substituer est ElementOperations.CreateElementGroupPrototype().Pour ce faire, ajoutez le code suivant au projet DÉSOLÉ :

    public class MyElementOperations : DesignSurfaceElementOperations
    {
      // Create an EGP to add to the clipboard.
      // Called when the elements to be copied have been
      // collected into an ElementGroup.
     protected override ElementGroupPrototype CreateElementGroupPrototype(ElementGroup elementGroup, ICollection<ModelElement> elements, ClosureType closureType)
      {
     // Add the shapes and connectors:
     // Get the elements already in the group:
        ModelElement[] mels = elementGroup.ModelElements
            .Concat(elementGroup.ElementLinks) // Omit if the paste target is not the diagram.
            .ToArray();
     // Get their shapes:
        IEnumerable<PresentationElement> shapes = 
           mels.SelectMany(mel => 
                PresentationViewsSubject.GetPresentation(mel));
        elementGroup.AddRange(shapes);
    
     return base.CreateElementGroupPrototype
               (elementGroup, elements, closureType);
      }
    
     public MyElementOperations(IServiceProvider serviceProvider, ElementOps1Diagram diagram)
          : base(serviceProvider, diagram)
      { }
    }
    
    // Replace the standard ElementOperations
    // singleton with your own:
    partial class MyDslDiagram // EDIT NAME
    {
     /// <summary>
     /// Singleton ElementOperations attached to this diagram.
     /// </summary>
     public override DesignSurfaceElementOperations ElementOperations
      {
     get
        {
     if (singleton == null)
          {
            singleton = new MyElementOperations(this.Store as IServiceProvider, this);
          }
     return singleton;
        }
      }
     private MyElementOperations singleton = null;
    }
    
  • Le collage formes dans un emplacement choisi, tel que la position du curseur actuelle.
    Lorsque l'utilisateur copie de plusieurs formes, vous pouvez conserver leurs positions relatives lorsqu'ils sont collés.Cette technique est illustrée par l'exemple dans VMSDK: Circuit Diagrams sample.

    Pour atteindre cet effet, substituez ClipboardCommandSet.ProcessOnMenuPasteCommand() pour utiliser la version d'emplacement-détail d' ElementOperations.Merge().Pour ce faire, ajoutez le code suivant dans le projet de DslPackage :

    
    partial class MyDslClipboardCommandSet // EDIT NAME
    {
       /// <summary>
        /// This method assumes we only want to paste things onto the diagram
        /// - not onto anything contained in the diagram.
        /// The base method pastes in a free space on the diagram.
        /// But if the menu was used to invoke paste, we want to paste in the cursor position.
        /// </summary>
        protected override void ProcessOnMenuPasteCommand()
        {
    
      NestedShapesSampleDocView docView = this.CurrentModelingDocView as NestedShapesSampleDocView;
    
          // Retrieve data from clipboard:
          System.Windows.Forms.IDataObject data = System.Windows.Forms.Clipboard.GetDataObject();
    
          Diagram diagram = docView.CurrentDiagram;
          if (diagram == null) return;
    
          if (!docView.IsContextMenuShowing)
          {
            // User hit CTRL+V - just use base method.
    
            // Deselect anything that's selected, otherwise
            // pasted item will be incompatible:
            if (!this.IsDiagramSelected())
            {
              docView.SelectObjects(1, new object[] { diagram }, 0);
            }
    
            // Paste into a convenient spare space on diagram:
        base.ProcessOnMenuPasteCommand();
          }
          else
          {
            // User right-clicked - paste at mouse position.
    
            // Utility class:
            DesignSurfaceElementOperations op = diagram.ElementOperations;
    
            ShapeElement pasteTarget = diagram;
    
            // Check whether what's in the paste buffer is acceptable on the target.
            if (pasteTarget != null && op.CanMerge(pasteTarget, data))
            {
    
            // Although op.Merge would be a no-op if CanMerge failed, we check CanMerge first
              // so that we don't create an empty transaction (after which Undo would be no-op).
              using (Transaction t = diagram.Store.TransactionManager.BeginTransaction("paste"))
              {
                PointD place = docView.ContextMenuMousePosition;
                op.Merge(pasteTarget, data, PointD.ToPointF(place));
                t.Commit();
              }
            }
          }
        }
      }
    
  • Conservez les éléments depuis l'utilisateur.
    Consultez Comment : ajouter un gestionnaire glisser-déplacer.

personnaliser le comportement de copie de lien

Lorsque l'utilisateur copie un élément, le comportement standard est que tous les éléments imbriqués sont également copiés.vous pouvez modifier le comportement standard de copie.Dans la définition DÉSOLÉ, sélectionnez un rôle sur un côté d'une relation et dans la fenêtre Propriétés affectez la valeur à copie de propagations .

Propage la propriété de copie du rôle de domaine

Il existe trois valeurs suivantes :

  • Ne propager pas la copie

  • Propagez la copie pour le lier uniquement )lorsque le groupe est collé, la nouvelle copie de ce lien fait référence à l'élément existant à l'autre extrémité du lien.

  • Propagez la copie pour le lier et le rôle lecteur opposé - le groupe copié inclut une copie de l'élément à l'autre extrémité du lien.

Effet de la copie avec PropagateCopyToLinkOnly

les modifications que vous apportez affecteront les éléments et l'image qui est copiée.

copie et comportement de programmation de collage

De nombreux aspects du comportement d'un DÉSOLÉ quant à copier, coller, la conception, et la suppression d'objets est régi par l'instance d' ElementOperations qui est associée au diagramme.Vous pouvez modifier le comportement de votre DÉSOLÉ en dérivant votre propre classe d' ElementOperations et en remplaçant la propriété d' ElementOperations de votre classe de diagramme.

ConseilConseil

Pour plus d'informations sur la personnalisation du modèle à l'aide de le code de programme, consultez Navigation et mise à jour d'un modèle dans le code de programme.

Diagramme de séquence de l'opération de copieDiagramme de séquence de l'opération de collage

pour définir votre propre ElementOperations

  1. Dans un fichier dans votre projet DÉSOLÉ, créez une classe dérivée d' DesignSurfaceElementOperations.

  2. ajoutez une définition de classe partielle pour votre classe de diagramme.Le nom de cette classe se trouve dans Dsl\GeneratedCode\Diagrams.cs.

    Dans la classe de diagramme, substitution ElementOperations pour retourner une instance de votre sous-classe d'ElementOperations.Vous devez retourner la même instance à chaque appel.

Ajoutez ce code dans un fichier de code dans le projet de DslPackage :

using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
using Microsoft.VisualStudio.Modeling.Diagrams.ExtensionEnablement;

  public partial class MyDslDiagram
  {
    public override DesignSurfaceElementOperations ElementOperations
    {
      get
      {
        if (this.elementOperations == null)
        {
          this.elementOperations = new MyElementOperations(this.Store as IServiceProvider, this);
        }
        return this.elementOperations;
      }
    }
    private MyElementOperations elementOperations = null;
  }

  public class MyElementOperations : DesignSurfaceElementOperations
  {
    public MyElementOperations(IServiceProvider serviceProvider, MyDslDiagram diagram)
      : base(serviceProvider, diagram)
    { }
    // Overridden methods follow
  }

Recevant des éléments déplacés d'autres modèles

ElementOperations peut également être utilisé pour définir la copie, le déplacement, la suppression et le comportement de glisser-déplacer.Comme exemple de l'utilisation d'ElementOperations, l'exemple indiqué ici définit le comportement glisser-déplacer personnalisé.Toutefois, étant donné que cet objectif vous pouvez considérer l'autre approche décrite dans Comment : ajouter un gestionnaire glisser-déplacer, qui est plus flexible.

définissez deux méthodes dans votre classe d'ElementOperations :

  • CanMerge(ModelElement targetElement, System.Windows.Forms.IDataObject data) qui détermine si l'élément source peut être déplacé sur la forme, le connecteur ou le schéma cible.

  • MergeElementGroupPrototype(ModelElement targetElement, ElementGroupPrototype sourcePrototype) qui combine l'élément source dans la cible.

Ff521398.collapse_all(fr-fr,VS.110).gifCanMerge()

[CanMerge()] est appelé pour déterminer les commentaires qui doit être attribuée à l'utilisateur lorsque la souris se déplace à travers le diagramme.Les paramètres à la méthode sont l'élément sur laquelle la souris passe, et les données relatives à la source de laquelle l'opération glisser est exécutée.l'utilisateur peut faire glisser n'importe où en fonction de l'écran.Par conséquent, l'objet source peut être de différents types et peut être sérialisé dans différents formats.Si la source est un DÉSOLÉ ou un modèle UML, le paramètre de données est la sérialisation d' ElementGroupPrototype.Faites glisser, copie et utilisation ElementGroupPrototypes d'opérations de boîte à outils pour représenter des fragments de modèles.

Un prototype de groupe d'élément peut contenir un nombre quelconque d'éléments et de liens.Les types d'éléments peuvent être identifiés par leurs GUID.GUID est de la forme qui a été glissé, pas l'élément de modèle sous-jacent.Dans l'exemple suivant, le retour d' CanMerge() true si une forme de classe d'un diagramme UML sont glissées sur ce diagramme.

public override bool CanMerge(ModelElement targetShape, System.Windows.Forms.IDataObject data)
 {
  // Extract the element prototype from the data.
  ElementGroupPrototype prototype = ElementOperations.GetElementGroupPrototype(this.ServiceProvider, data);
  if (targetShape is MyTargetShape && prototype != null &&
        prototype.RootProtoElements.Any(rootElement => 
          rootElement.DomainClassId.ToString() 
          ==  "3866d10c-cc4e-438b-b46f-bb24380e1678")) // Guid of UML Class shapes
          // or SourceClass.DomainClassId
        return true;
   return base.CanMerge(targetShape, data);
 }

MergeElementGroupPrototype()

Cette méthode est appelée lorsque l'utilisateur supprime un élément sur un diagramme, une forme, ou un connecteur.Il doit fusionner le contenu fait glisser l'élément cible.Dans cet exemple, le code détermine s'il identifie la combinaison de types de cible et de prototype ; si tel est le cas, la méthode convertit les éléments déplacés dans un prototype des éléments qui doivent être ajoutés au modèle.La méthode de base est appelée pour exécuter une fusion, les éléments convertit ou inconvertis.

    public override void MergeElementGroupPrototype(ModelElement targetShape, ElementGroupPrototype sourcePrototype)
    {
      ElementGroupPrototype prototypeToMerge = sourcePrototype;
      MyTargetShape pel = targetShape as MyTargetShape;
      if (pel != null)
      {
        prototypeToMerge = ConvertDraggedTypeToLocal(pel, sourcePrototype);
      }
      if (prototypeToMerge != null)
        base.MergeElementGroupPrototype(targetShape, prototypeToMerge);
    }

Cet exemple traite des éléments de classe UML glissé à partir d'un diagramme de classes UML.Le langage DÉSOLÉ n'est pas conçu pour stocker des classes UML directement, mais à la place, nous créons un élément DÉSOLÉ pour chaque classe UML glissées.Ce est utile, par exemple, si le langage DÉSOLÉ est un diagramme d'instance.L'utilisateur peut faire glisser des classes sur le diagramme pour créer des instances de ces classes.

    private ElementGroupPrototype ConvertDraggedTypeToLocal (MyTargetShape snapshot, ElementGroupPrototype prototype)
    {
      // Find the UML project:
      EnvDTE.DTE dte = snapshot.Store.GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
      foreach (EnvDTE.Project project in dte.Solution.Projects)
      {
        IModelingProject modelingProject = project as IModelingProject;
        if (modelingProject == null) continue; // not a modeling project
        IModelStore store = modelingProject.Store;
        if (store == null) continue;
        // Look for the shape that was dragged:
        foreach (IDiagram umlDiagram in store.Diagrams())
        {
          // Get modeling diagram that implements UML diagram:
          Diagram diagram = umlDiagram.GetObject<Diagram>();
          Guid elementId = prototype.SourceRootElementIds.FirstOrDefault();
          ShapeElement shape = diagram.Partition.ElementDirectory.FindElement(elementId) as ShapeElement;
          if (shape == null) continue;
          IClass classElement = shape.ModelElement as IClass;
          if (classElement == null) continue;
          
          // Create a prototype of elements in my DSL, based on the UML element:
          Instance instance = new Instance(snapshot.Store);
          instance.Type = classElement.Name;
          // Pack them into a prototype:
          ElementGroup group = new ElementGroup(instance);
          return group.CreatePrototype();
        }
      }
      return null;
    }

Comportement de copie standard

Le code dans cette section affiche les méthodes que vous pouvez substituer pour modifier le comportement de copie.Vous aidait pour voir comment accomplir vos propres personnalisations, cette section indique que le code qui substitue les méthodes relatives à la copie, mais ne modifie pas le comportement standard.

Lorsque l'utilisateur appuie sur CTRL+C ou utilise la commande de menu de copie, la méthode ProcessOnMenuCopyCommand est appelée.Vous pouvez voir comment il est configuré dans DslPackage\Generated Code\CommandSet.cs.Pour plus d'informations sur la façon dont les commandes sont installation, consultez Comment : ajouter une commande au menu contextuel.

vous pouvez substituer ProcessOnMenuCopyCommand en ajoutant une définition de classe partielle de MyDslClipboardCommandSet dans le projet de DslPackage.

using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;

partial class MyDslClipboardCommandSet
{
  /// <summary>
  /// Override ProcessOnMenuCopyCommand() to copy elements to the
  /// clipboard in different formats, or to perform additional tasks
  /// before or after copying – for example deselect the copied elements.
  /// </summary>
  protected override void ProcessOnMenuCopyCommand()
  {
    IList<ModelElement> selectedModelElements = this.SelectedElements;
    if (selectedModelElements.Count == 0) return;

    // System container for clipboard data.
    // The IDataObject can contain data in several formats.
    IDataObject dataObject = new DataObject();
      
    Bitmap bitmap = null; // For export to other programs.
    try
    {
      #region Create EGP for copying to a DSL.
      this.CopyModelElementsIntoElementGroupPrototype
                     (dataObject, selectedModelElements);
      #endregion
      
      #region Create bitmap for copying to another application. 
      // Find all the shapes associated with this selection:
      List<ShapeElement> shapes = new List<ShapeElement>(
        this.ResolveExportedShapesForClipboardImages
              (dataObject, selectedModelElements));

      bitmap = this.CreateBitmapForClipboard(shapes);
      if (bitmap != null)
      {
        dataObject.SetData(DataFormats.Bitmap, bitmap);
      }
      #endregion 
     
      // Add the data to the clipboard:
      Clipboard.SetDataObject(dataObject, true, 5, 100);
    }
    finally
    {
      // Dispose bitmap after SetDataObject:
      if (bitmap != null) bitmap.Dispose();
    }
  }
/// <summary>
/// Override this to customize the element group that is copied to the clipboard.
/// </summary>
protected override void CopyModelElementsIntoElementGroupPrototype(IDataObject dataObject, IList<ModelElement> selectedModelElements)
{
  return this.ElementOperations.Copy(dataObject, selectedModelElements);
}
}

chaque diagramme a une instance de singleton d'ElementOperations.vous pouvez fournir votre propre dérivé.Ce fichier, pouvant être placé dans le projet DÉSOLÉ, se comporterait le même que le code qu'il substitue :

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;

namespace Company.MyDsl
{
  partial class MyDslDiagram
  {
    /// <summary>
    /// Singleton ElementOperations attached to this diagram.
    /// </summary>
    public override DesignSurfaceElementOperations ElementOperations
    {
      get
      {
        if (this.elementOperations == null)
        {
          this.elementOperations = new MyElementOperations(this.Store as IServiceProvider, this);
        }
        return this.elementOperations;
      }
    }
    private MyElementOperations elementOperations = null;
  }

  // Our own version of ElementOperations so that we can override:
  public class MyElementOperations : DesignSurfaceElementOperations
  {
    public MyElementOperations(IServiceProvider serviceProvider, ElementOps1Diagram diagram)
      : base(serviceProvider, diagram)
    { }


     
    /// <summary>
    /// Copy elements to the clipboard data.
    /// Provides a hook for adding custom data.
    /// </summary>
    public override void Copy(System.Windows.Forms.IDataObject data, 
      ICollection<ModelElement> elements, 
      ClosureType closureType, 
      System.Drawing.PointF sourcePosition)
    {
      if (CanAddElementGroupFormat(elements, closureType))
      {
        AddElementGroupFormat(data, elements, closureType); 
      }

      // Override these to store additional data:
      if (CanAddCustomFormat(elements, closureType))
      {
        AddCustomFormat(data, elements, closureType, sourcePosition);
      }
    }
     
    
    protected override void AddElementGroupFormat(System.Windows.Forms.IDataObject data, ICollection<ModelElement> elements, ClosureType closureType)
    {
      // Add the selected elements and those implied by the propagate copy rules:
      ElementGroup elementGroup = this.CreateElementGroup(elements, closureType);

      // Mark all the elements that are not embedded under other elements:
      this.MarkRootElements(elementGroup, elements, closureType);

      // Store in the clipboard data:
      ElementGroupPrototype elementGroupPrototype = this.CreateElementGroupPrototype(elementGroup, elements, closureType);
      data.SetData(ElementGroupPrototype.DefaultDataFormatName, elementGroupPrototype);
    }

    /// <summary>
    /// Override this to store additional elements in the element group:
    /// </summary>
    protected override ElementGroupPrototype CreateElementGroupPrototype(ElementGroup elementGroup, ICollection<ModelElement> elements, ClosureType closureType)
    {
      ElementGroupPrototype prototype = new ElementGroupPrototype(this.Partition, elementGroup.RootElements, elementGroup);
      return prototype;
    }

    /// <summary>
    /// Create an element group from the given starting elements, using the 
    /// copy propagation rules specified in the DSL Definition.
    /// By default, this includes all the embedded descendants of the starting elements,
    /// and also includes reference links where both ends are already included.
    /// </summary>
    /// <param name="startElements">model elements to copy</param>
    /// <param name="closureType"></param>
    /// <returns></returns>
    protected override ElementGroup CreateElementGroup(ICollection<ModelElement> startElements, ClosureType closureType)
    {
      // ElementClosureWalker finds all the connected elements, 
      // according to the propagate copy rules specified in the DSL Definition:
      ElementClosureWalker walker = new ElementClosureWalker(this.Partition, 
        closureType, // Normally ClosureType.CopyClosure
        startElements, 
        true, // Do not load other models.
        null, // Optional list of domain roles not to traverse.
        true); // Include relationship links where both ends are already included.
      
      walker.Traverse(startElements);
      IList<ModelElement> closureList = walker.ClosureList;
      Dictionary<object, object> closureContext = walker.Context;

      // create a group for this closure
      ElementGroup group = new ElementGroup(this.Partition);
      group.AddRange(closureList, false);

      // create the element group prototype for the group
      foreach (object key in closureContext.Keys)
      {
        group.SourceContext.ContextInfo[key] = closureContext[key];
      }

      return group;
    }
  }
}

Voir aussi

Concepts

Personnalisation de la création et du mouvement des éléments

Comment : ajouter un gestionnaire glisser-déplacer

Personnalisation du comportement de la commande de suppression

Autres ressources

Sample: VMSDK Circuit Diagrams sample