Udostępnij za pośrednictwem


Dostosowywanie tworzenia i przesuwania elementów

Można zezwolić na przeciągnięcie elementu na inny element z przybornika lub w operacji wklejania lub przenoszenia. Możesz mieć przeniesione elementy połączone z elementami docelowymi przy użyciu podanych relacji.

Dyrektywa scalania elementów (EMD) określa, co się stanie, gdy jeden element modelu zostanie scalony z innym elementem modelu. Dzieje się tak, gdy:

  • Użytkownik przeciąga z przybornika na diagram lub kształt.

  • Użytkownik tworzy element przy użyciu menu Dodaj w eksploratorze lub kształcie przedziału.

  • Użytkownik przenosi element z jednego toru do drugiego.

  • Użytkownik wkleja element.

  • Kod programu wywołuje dyrektywę scalania elementu.

Chociaż operacje tworzenia mogą się różnić od operacji kopiowania, działają one w ten sam sposób. Po dodaniu elementu, na przykład z przybornika, jest replikowany prototyp. Prototyp jest scalony z modelem w taki sam sposób, jak elementy skopiowane z innej części modelu.

Obowiązkiem EMD jest podjęcie decyzji, w jaki sposób należy scalić obiekt lub grupę obiektów w określonej lokalizacji w modelu. W szczególności decyduje o utworzeniu wystąpienia relacji w celu połączenia scalonej grupy z modelem. Można go również dostosować, aby ustawić właściwości i utworzyć dodatkowe obiekty.

Diagram showing a before and after look at a tree of elements and their reference relationships when An E M D determines how a new element is added.

EMD jest generowany automatycznie podczas definiowania relacji osadzania. To domyślne EMD tworzy wystąpienie relacji, gdy użytkownicy dodają nowe wystąpienia podrzędne do elementu nadrzędnego. Możesz zmodyfikować te domyślne dyski EMD, na przykład dodając kod niestandardowy.

Możesz również dodać własne dyski EMD w definicji DSL, aby umożliwić użytkownikom przeciąganie lub wklejanie różnych kombinacji scalonych i odbierających klas.

Definiowanie dyrektywy scalania elementu

Można dodawać dyrektywy scalania elementów do klas domen, relacji domeny, kształtów, łączników i diagramów. Można je dodać lub znaleźć w Eksploratorze DSL w klasie domeny odbierającego. Klasa odbierania jest klasą domeny elementu, który jest już w modelu, i na którym zostanie scalony nowy lub skopiowany element.

Screenshot of DSL Explorer showing an E M D being added with ExampleElement selected as the Indexing class and the Applies to subclasses option checked.

Klasa indeksowania to klasa domeny elementów, które można scalić z elementami członkowskimi klasy odbierającej. Wystąpienia podklas klasy indeksowania będą również scalane przez tę usługę EMD, chyba że ustawiono opcję Dotyczy podklas na False.

Istnieją dwa rodzaje dyrektywy scalania:

  • Dyrektywa Scalanie procesów określa relacje, za pomocą których nowy element powinien być połączony z drzewem.

  • Dyrektywa Forward Merge przekierowuje nowy element do innego elementu odbierającego, zazwyczaj nadrzędnego.

Możesz dodać kod niestandardowy do dyrektyw scalania:

  • Ustaw opcję Użyj niestandardowej akceptacji , aby dodać własny kod w celu określenia, czy określone wystąpienie elementu indeksowania ma zostać scalone z elementem docelowym. Gdy użytkownik przeciągnie z przybornika, wskaźnik "invalid" pokazuje, czy kod nie zezwala na scalanie.

    Na przykład można zezwolić na scalanie tylko wtedy, gdy element odbierający jest w określonym stanie.

  • Ustaw opcję Użyj niestandardowego scalania , aby dodać własny kod w celu zdefiniowania zmian wprowadzonych do modelu podczas scalania.

    Można na przykład ustawić właściwości w scalanych elementach przy użyciu danych z nowej lokalizacji w modelu.

Uwaga

W przypadku pisania niestandardowego kodu scalania ma to wpływ tylko na scalania wykonywane przy użyciu tej EMD. Jeśli istnieją inne dyski EMD, które scalają ten sam typ obiektu, lub jeśli istnieje inny kod niestandardowy, który tworzy te obiekty bez użycia EMD, nie będzie to miało wpływu na niestandardowy kod scalania.

Jeśli chcesz upewnić się, że nowy element lub nowa relacja jest zawsze przetwarzany przez kod niestandardowy, rozważ zdefiniowanie AddRule elementu w relacji osadzania i DeleteRule klasy domeny elementu. Aby uzyskać więcej informacji, zobacz Reguły propagacji zmian w modelu.

Przykład: Definiowanie EMD bez kodu niestandardowego

Poniższy przykład umożliwia użytkownikom tworzenie elementu i łącznika w tym samym czasie przez przeciągnięcie z przybornika na istniejący kształt. W przykładzie dodano EMD do definicji DSL. Przed wprowadzeniem tej modyfikacji użytkownicy mogą przeciągać narzędzia na diagram, ale nie na istniejące kształty.

Użytkownicy mogą również wklejać elementy do innych elementów.

Aby umożliwić użytkownikom tworzenie elementu i łącznika w tym samym czasie

  1. Utwórz nową bibliotekę DSL przy użyciu szablonu rozwiązania Minimalne języki .

    Po uruchomieniu tego rozszerzenia DSL można tworzyć kształty i łączniki między kształtami. Nie można przeciągnąć nowego kształtu ExampleElement z przybornika do istniejącego kształtu.

  2. Aby umożliwić użytkownikom scalanie elementów z ExampleElement kształtami, utwórz nową EMD w ExampleElement klasie domeny:

    1. W Eksploratorze DSL rozwiń węzeł Klasy domeny. Kliknij prawym przyciskiem myszy ExampleElement , a następnie kliknij polecenie Dodaj nową dyrektywę scalania elementów.

    2. Upewnij się, że okno Szczegóły DSL jest otwarte, aby wyświetlić szczegóły nowego pakietu EMD. (Menu: View, Other Windows, DSL Details).)

  3. Ustaw klasę Indeksowanie w oknie Szczegóły DSL, aby zdefiniować, jaką klasę elementów można scalić na ExampleElement obiekty.

    W tym przykładzie wybierz pozycję ExampleElements, aby użytkownik mógł przeciągać nowe elementy na istniejące elementy.

    Zwróć uwagę, że klasa Indeksowanie staje się nazwą EMD w Eksploratorze DSL.

  4. W obszarze Scalanie procesów, tworząc łącza, dodaj dwie ścieżki:

    • Jedna ścieżka łączy nowy element z modelem nadrzędnym. Wyrażenie ścieżki, które należy wprowadzić, przechodzi z istniejącego elementu za pośrednictwem relacji osadzania do modelu nadrzędnego. Na koniec określa rolę w nowym linku, do którego zostanie przypisany nowy element. Ścieżka jest następująca:

      ExampleModelHasElements.ExampleModel/!ExampleModel/.Elements

    • Druga ścieżka łączy nowy element z istniejącym elementem. Wyrażenie ścieżki określa relację odwołania i rolę, do której zostanie przypisany nowy element. Ta ścieżka jest następująca:

      ExampleElementReferencesTargets.Sources

      Aby utworzyć każdą ścieżkę, możesz użyć narzędzia nawigacji ścieżki:

      1. W obszarze Scalanie procesów, tworząc linki w ścieżkach, kliknij pozycję< Dodaj ścieżkę>.

      2. Kliknij strzałkę listy rozwijanej po prawej stronie elementu listy. Zostanie wyświetlony widok drzewa.

      3. Rozwiń węzły w drzewie, aby utworzyć ścieżkę, którą chcesz określić.

  5. Przetestuj rozszerzenie DSL:

    1. Naciśnij klawisz F5 , aby ponownie skompilować i uruchomić rozwiązanie.

      Ponowne kompilowanie trwa dłużej niż zwykle, ponieważ wygenerowany kod zostanie zaktualizowany z szablonów tekstowych w celu zachowania zgodności z nową definicją DSL.

    2. Po uruchomieniu eksperymentalnego wystąpienia programu Visual Studio otwórz plik modelu dsL. Utwórz kilka przykładowych elementów.

    3. Przeciągnij z narzędzia Example Element na istniejący kształt.

      Zostanie wyświetlony nowy kształt połączony z istniejącym kształtem z łącznikiem.

    4. Skopiuj istniejący kształt. Wybierz inny kształt i wklej.

      Zostanie utworzona kopia pierwszego kształtu. Ma nową nazwę i jest połączona z drugim kształtem z łącznikiem.

Zwróć uwagę na następujące kwestie z tej procedury:

  • Tworząc dyrektywy scalania elementów, można zezwolić dowolnej klasie elementu na akceptowanie innych. EMD jest tworzony w klasie domeny odbierającego, a zaakceptowana klasa domeny jest określona w polu Klasa indeksu.

  • Definiując ścieżki, można określić, które linki mają być używane do łączenia nowego elementu z istniejącym modelem.

    Określone linki powinny zawierać jedną relację osadzania.

  • EMD wpływa zarówno na tworzenie z przybornika, jak i operacje wklejania.

    Jeśli napiszesz kod niestandardowy, który tworzy nowe elementy, możesz jawnie wywołać EMD przy użyciu ElementOperations.Merge metody . Dzięki temu kod łączy nowe elementy z modelem w taki sam sposób jak inne operacje. Aby uzyskać więcej informacji, zobacz Dostosowywanie zachowania kopiowania.

Przykład: dodawanie niestandardowego kodu akceptuj do EMD

Dodając kod niestandardowy do EMD, można zdefiniować bardziej złożone zachowanie scalania. Ten prosty przykład uniemożliwia użytkownikowi dodanie więcej niż stałej liczby elementów do diagramu. Przykład modyfikuje domyślną EMD, która towarzyszy relacji osadzania.

Aby napisać kod niestandardowej akceptacji w celu ograniczenia tego, co użytkownik może dodać

  1. Utwórz rozszerzenie DSL przy użyciu szablonu rozwiązania Minimalne języki . Otwórz diagram definicji DSL.

  2. W Eksploratorze DSL rozwiń węzeł Klasy domen, ExampleModel, Dyrektywy scalania elementów. Wybierz dyrektywę scalania elementu o nazwie ExampleElement.

    To EMD steruje sposobem, w jaki użytkownik może tworzyć nowe ExampleElement obiekty w modelu, na przykład przeciągając z przybornika.

  3. W oknie Szczegóły DSL wybierz pozycję Używa akceptacji niestandardowej.

  4. Skompiluj ponownie rozwiązanie. Potrwa to dłużej niż zwykle, ponieważ wygenerowany kod zostanie zaktualizowany z modelu.

    Zostanie zgłoszony błąd kompilacji podobny do: "Company.ElementMergeSample.ExampleElement nie zawiera definicji elementu CanMergeExampleElement..."

    Należy zaimplementować metodę CanMergeExampleElement.

  5. Utwórz nowy plik kodu w projekcie Dsl . Zastąp jego zawartość następującym kodem i zmień przestrzeń nazw na przestrzeń nazw projektu.

    using Microsoft.VisualStudio.Modeling;
    
    namespace Company.ElementMergeSample // EDIT.
    {
      partial class ExampleModel
      {
        /// <summary>
        /// Called whenever an ExampleElement is to be merged into this ExampleModel.
        /// This happens when the user pastes an ExampleElement
        /// or drags from the toolbox.
        /// Determines whether the merge is allowed.
        /// </summary>
        /// <param name="rootElement">The root element in the merging EGP.</param>
        /// <param name="elementGroupPrototype">The EGP that the user wants to merge.</param>
        /// <returns>True if the merge is allowed</returns>
        private bool CanMergeExampleElement(ProtoElementBase rootElement, ElementGroupPrototype elementGroupPrototype)
        {
          // Allow no more than 4 elements to be added:
          return this.Elements.Count < 4;
        }
      }
    }
    

    Ten prosty przykład ogranicza liczbę elementów, które można scalić z modelem nadrzędnym. Aby uzyskać bardziej interesujące warunki, metoda może sprawdzić dowolne właściwości i łącza obiektu odbierającego. Może również sprawdzić właściwości scalanych elementów, które są przenoszone w obiekcie ElementGroupPrototype. Aby uzyskać więcej informacji na temat ElementGroupPrototypesprogramu , zobacz Dostosowywanie zachowania kopiowania. Aby uzyskać więcej informacji na temat pisania kodu odczytującego model, zobacz Nawigowanie i aktualizowanie modelu w kodzie programu.

  6. Przetestuj rozszerzenie DSL:

    1. Naciśnij klawisz F5 , aby ponownie skompilować rozwiązanie. Po otwarciu eksperymentalnego wystąpienia programu Visual Studio otwórz wystąpienie dsl.

    2. Utwórz nowe elementy na kilka sposobów:

      • Przeciągnij z narzędzia Przykładowy element na diagram.

      • W Przykładowym Eksploratorze modeli kliknij prawym przyciskiem myszy węzeł główny, a następnie kliknij polecenie Dodaj nowy przykładowy element.

      • Skopiuj i wklej element na diagramie.

    3. Sprawdź, czy nie można użyć żadnego z tych sposobów, aby dodać do modelu więcej niż cztery elementy. Dzieje się tak, ponieważ wszystkie używają dyrektywy Scalanie elementów.

Przykład: dodawanie niestandardowego kodu scalania do EMD

W niestandardowym kodzie scalania można zdefiniować, co się stanie, gdy użytkownik przeciąga narzędzie lub wkleja na element. Istnieją dwa sposoby definiowania niestandardowego scalania:

  1. Ustaw opcję Używa niestandardowego scalania i podaj wymagany kod. Kod zastępuje wygenerowany kod scalania. Użyj tej opcji, jeśli chcesz całkowicie ponownie zdefiniować działanie scalania.

  2. Zastąpi metodę MergeRelate i opcjonalnie metodę MergeDisconnect . W tym celu należy ustawić właściwość Generates Double Derived klasy domeny. Kod może wywołać wygenerowany kod scalania w klasie bazowej. Użyj tej opcji, jeśli chcesz wykonać dodatkowe operacje po wykonaniu scalania.

    Te podejścia mają wpływ tylko na scalania wykonywane przy użyciu tej EMD. Jeśli chcesz mieć wpływ na wszystkie sposoby, w jaki można utworzyć scalony element, alternatywą jest zdefiniowanie AddRule elementu w relacji osadzania i klasy DeleteRule w scalonej klasie domeny. Aby uzyskać więcej informacji, zobacz Reguły propagacji zmian w modelu.

Aby przesłonić metodę MergeRelate

  1. W definicji DSL upewnij się, że zdefiniowano identyfikator EMD, do którego chcesz dodać kod. Jeśli chcesz, możesz dodać ścieżki i zdefiniować niestandardowy kod akceptowania zgodnie z opisem w poprzednich sekcjach.

  2. Na diagramie DslDefinition wybierz klasę odbierania scalania. Zazwyczaj jest to klasa na końcu źródłowej relacji osadzania.

    Na przykład w języku DSL wygenerowanym na podstawie rozwiązania Minimalne języki wybierz pozycję ExampleModel.

  3. W oknie Właściwości ustaw wartość Generates Double Derived na true.

  4. Skompiluj ponownie rozwiązanie.

  5. Sprawdź zawartość pliku Dsl\Generated Files\DomainClasses.cs. Wyszukaj metody o nazwie MergeRelate i sprawdź ich zawartość. Pomoże ci to napisać własne wersje.

  6. W nowym pliku kodu napisz klasę częściową dla klasy odbierającego i przesłoń metodę MergeRelate . Pamiętaj, aby wywołać metodę podstawową. Na przykład:

    partial class ExampleModel
    {
      /// <summary>
      /// Called when the user drags or pastes an ExampleElement onto the diagram.
      /// Sets the time of day as the name.
      /// </summary>
      /// <param name="sourceElement">Element to be added</param>
      /// <param name="elementGroup">Elements to be merged</param>
      protected override void MergeRelate(ModelElement sourceElement, ElementGroup elementGroup)
      {
        // Connect the element according to the EMD:
        base.MergeRelate(sourceElement, elementGroup);
    
        // Custom actions:
        ExampleElement mergingElement = sourceElement as ExampleElement;
        if (mergingElement != null)
        {
          mergingElement.Name = DateTime.Now.ToLongTimeString();
        }
      }
    }
    

Aby napisać niestandardowy kod scalania

  1. W pliku Dsl\Generated Code\DomainClasses.cs sprawdź metody o nazwie MergeRelate. Te metody tworzą łącza między nowym elementem a istniejącym modelem.

    Sprawdź również metody o nazwie MergeDisconnect. Te metody odłączą element z modelu, gdy ma zostać usunięty.

  2. W Eksploratorze DSL wybierz lub utwórz dyrektywę scalania elementów, którą chcesz dostosować. W oknie Szczegóły DSL ustaw opcję Używa scalania niestandardowego.

    Po ustawieniu tej opcji opcje Scalanie procesów i Scalanie dalej są ignorowane. Zamiast tego jest używany kod.

  3. Skompiluj ponownie rozwiązanie. Trwa to dłużej niż zwykle, ponieważ wygenerowane pliki kodu zostaną zaktualizowane z modelu.

    Zostaną wyświetlone komunikaty o błędach. Kliknij dwukrotnie komunikaty o błędach, aby wyświetlić instrukcje w wygenerowanym kodzie. Te instrukcje proszą o podanie dwóch metod: MergeRelateYourDomainClass i MergeDisconnectYourDomainClass

  4. Napisz metody w częściowej definicji klasy w osobnym pliku kodu. Sprawdzone wcześniej przykłady powinny sugerować, czego potrzebujesz.

    Niestandardowy kod scalania nie będzie mieć wpływu na kod, który bezpośrednio tworzy obiekty i relacje, i nie będzie mieć wpływu na inne EMD. Aby upewnić się, że dodatkowe zmiany są implementowane niezależnie od sposobu tworzenia elementu, rozważ napisanie elementu AddRule i DeleteRule zamiast tego. Aby uzyskać więcej informacji, zobacz Reguły propagacji zmian w modelu.

Przekierowywanie operacji scalania

Dyrektywa scalania do przodu przekierowuje element docelowy operacji scalania. Zazwyczaj nowy element docelowy jest elementem nadrzędnym osadzania początkowego obiektu docelowego.

Na przykład w języku DSL utworzonym za pomocą szablonu diagramu składników porty są osadzone w składnikach. Porty są wyświetlane jako małe kształty na krawędzi kształtu składnika. Użytkownik tworzy porty, przeciągając narzędzie Port do kształtu Składnik. Czasami jednak użytkownik błędnie przeciąga narzędzie Port na istniejący port, a nie składnik, a operacja kończy się niepowodzeniem. Jest to łatwy błąd, gdy istnieje kilka istniejących portów. Aby pomóc użytkownikowi uniknąć tego uciążliwości, możesz zezwolić na przeciąganie portów na istniejący port, ale akcja została przekierowana do składnika nadrzędnego. Operacja działa tak, jakby element docelowy był składnikiem.

Dyrektywę scalania do przodu można utworzyć w rozwiązaniu Model składników. Jeśli skompilujesz i uruchomisz oryginalne rozwiązanie, użytkownicy powinni zobaczyć, że użytkownicy mogą przeciągać dowolną liczbę elementów portów wejściowych lub portów wyjściowych z przybornika do elementu Component. Nie mogą jednak przeciągać portu do istniejącego portu. Wskaźnik Niedostępny ostrzega ich, że ten ruch nie jest włączony. Można jednak utworzyć dyrektywę scalania do przodu, tak aby port, który przypadkowo spadł na istniejącym porcie wejściowym, jest przekazywany do elementu Component .

Aby utworzyć dyrektywę scalania do przodu

  1. Utwórz rozwiązanie narzędzi językowych specyficznych dla domeny przy użyciu szablonu Model składników.

  2. Wyświetl Eksplorator DSL, otwierając plik DslDefinition.dsl.

  3. W Eksploratorze DSL rozwiń węzeł Klasy domeny.

  4. Klasa domeny abstrakcyjnej ComponentPort jest klasą bazową zarówno InPort, jak i OutPort. Kliknij prawym przyciskiem myszy pozycję ComponentPort , a następnie kliknij polecenie Dodaj nową dyrektywę scalania elementów.

    Nowy węzeł dyrektywy scalania elementu jest wyświetlany w węźle Dyrektywy scalania elementów.

  5. Wybierz węzeł Dyrektywy scalania elementów i otwórz okno Szczegóły rozszerzenia DSL.

  6. Na liście Klasy indeksowania wybierz pozycję ComponentPort.

  7. Wybierz pozycję Prześlij scalanie do innej klasy domeny.

  8. Na liście wyboru ścieżki rozwiń węzeł ComponentPort, rozwiń węzeł ComponentHasPorts, a następnie wybierz pozycję Składnik.

    Nowa ścieżka powinna przypominać następującą:

    ComponentHasPorts.Component/! Składnik

  9. Zapisz rozwiązanie, a następnie przekształć szablony, klikając prawym przyciskiem na pasku narzędzi Eksplorator rozwiązań.

  10. Skompiluj i uruchom rozwiązanie. Zostanie wyświetlone nowe wystąpienie programu Visual Studio.

  11. W Eksplorator rozwiązań otwórz plik Sample.mydsl. Zostanie wyświetlony diagram i przybornik ComponentLanguage.

  12. Przeciągnij port wejściowy z przybornika do innego portu wejściowego. Następnie przeciągnij element OutputPort do elementu InputPort, a następnie do innego elementu OutputPort.

    Nie powinien być widoczny wskaźnik Niedostępny i powinno być możliwe usunięcie nowego portu wejściowego w istniejącym. Wybierz nowy port wejściowy i przeciągnij go do innego punktu w składniku.