복사 동작 사용자 지정
사용 하 여 만든 도메인 관련 언어 (DSL)에 있는 Visual Studio SDK, 모델링 및 시각화 복사 하 고 요소를 붙여 넣는 경우 변경할 수 있습니다.
표준 복사 및 붙여넣기 동작
복사 가능 하도록 설정의 복사 붙여넣기 사용 속성에는 편집기 DSL 탐색기에서에서 노드를.
기본적으로 사용자가 요소를 클립보드로 복사 하는 경우 다음 요소 또한 복사 됩니다.
선택된 된 요소에 포함 된 하위 항목입니다.(즉, 목표를 기반으로 하는 관계를 포함 시키는 요소 요소가 복사 합니다.)
복사한 요소 간의 관계 링크입니다.
이 규칙에 복사 요소 및 링크에 재귀적으로 적용 됩니다.
복사 요소 및 링크 직렬화 할 및 저장 된 ElementGroupPrototype (EGP) 클립보드에 배치 합니다.
또한 이미지를 복사한 요소를 클립보드에 놓입니다.이 Word 등 다른 응용 프로그램에 붙여 넣을 수 있습니다.
사용자가 DSL 정의에 따라 요소를 사용 하 여 대상에 붙여 넣을 수 있습니다.예를 들어, 구성 요소 솔루션 템플릿에서 생성 된 DSL에, 사용자가 포트 구성 요소를 끌어온 있지만 않는 다이어그램에 붙여넣을 수 있습니다. 및 구성 요소 다이어그램, 있지만 않은 다른 구성 요소에 붙여 넣을 수 있습니다.
복사 및 붙여넣기 동작 사용자 지정
프로그램 코드를 사용 하 여 모델을 사용자 지정 하는 방법에 대 한 자세한 내용은 참조 하십시오. 프로그램 코드에서 모델 탐색 및 업데이트.
복사, 잘라내기 및 붙여넣기 사용 여부.
DSL 탐색기에서 설정의 복사 붙여넣기 사용 속성에는 편집기 노드.링크를 동일한 대상으로 복사 합니다. 예를 들어, 복사 설명 상자에 같은 제목 요소를 연결 합니다.
설정에서 전파 복사 속성의 역할에 전파에 복사만 링크를.자세한 내용은 링크 복사 동작을 사용자 지정.연결 된 요소를 복사 합니다. 예를 들어, 새 요소를 복사 하면 복사본에 있는 모든 연결 된 메모 상자도 이루어집니다.
설정에서 전파 복사 속성의 역할에 전파 복사본에 연결 하 고 반대 역할 수행자.자세한 내용은 링크 복사 동작을 사용자 지정.복사 및 붙여 넣는 방법으로 신속 하 게 중복 요소가 있습니다. 일반적으로 방금 복사한 항목을 선택 하 고 같은 종류의 요소를 붙여 넣을 수 없습니다.
도메인 클래스에 병합 하는 요소 지시어를 추가 하 고 앞으로 병합 하 여 부모 클래스를 설정 합니다.이 같은 효과가 끌기 작업을 해야 합니다.자세한 내용은 요소 만들기 및 이동 사용자 지정를 참조하십시오.-또는-
요소를 재정의 하 여 붙여 넣기 전에 다이어그램 선택 ClipboardCommandSet.ProcessOnPasteCommand().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); } } }
사용자가 선택한 대상에 붙여넣습니다 때 추가 링크를 작성 합니다. 설명 상자에 요소를 붙여넣을 때 예를 들어, 링크 간에 이루어집니다.
대상 도메인 클래스에는 요소 병합 지시문을 추가 하 고 링크를 추가 하 여 병합 프로세스를 설정 합니다.이 같은 효과가 끌기 작업을 해야 합니다.자세한 내용은 요소 만들기 및 이동 사용자 지정를 참조하십시오.-또는-
재정의 ClipboardCommandSet.ProcessOnPasteCommand() 기본 메서드를 호출한 후 추가 링크를 만들 수 있습니다.
에 요소 복사 될 수 있습니다 형식 사용자 정의 비트맵 폼에 테두리를 추가 하려면 외부 응용 프로그램-예를 들어.
재정의 MyDslClipboardCommandSet.ProcessOnMenuCopyCommand() DslPackage 프로젝트에서입니다.어떻게 요소를 클립보드로 복사 명령에 의해 있지만 끌기 작업에 복사 됩니다 사용자 지정 합니다.
재정의 MyDslClipboardCommandSet.CopyModelElementsIntoElementGroupPrototype() DslPackage 프로젝트에서입니다.셰이프 레이아웃 복사를 유지 하 고 붙여 넣습니다.
사용자가 여러 개의 셰이프를 복사할 때, 붙여 넣을 때의 상대적인 위치를 유지할 수 있습니다.이 기법에서 예제에서 확인할 수 있습니다 VMSDK: 회로 다이어그램 샘플.이 효과 얻기 위해 복사 Elementgroupprototype에 도형과 연결선을 추가 합니다.재정의 하는 가장 편리한 방법 ElementOperations.CreateElementGroupPrototype()입니다.이렇게 하려면 Dsl 프로젝트에 다음 코드를 추가 합니다.
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; }
현재 커서 위치와 같은 선택한 위치에 셰이프를 붙여 넣습니다.
사용자가 여러 개의 셰이프를 복사할 때, 붙여 넣을 때의 상대적인 위치를 유지할 수 있습니다.이 기법에서 예제에서 확인할 수 있습니다 VMSDK: 회로 다이어그램 샘플.이 효과 얻기 위해 재정의 ClipboardCommandSet.ProcessOnMenuPasteCommand() 위치에 특정 버전의 ElementOperations.Merge().이 작업을 수행 하려면 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(); } } } } }
사용자가 요소를 끌어서 놓기 수 있습니다.
자세한 내용은 방법: 끌어서 놓기 처리기 추가를 참조하십시오.
링크 복사 동작 사용자 지정
사용자가 요소를 복사할 때 포함 된 요소 또한 복사할 수 표준 동작이입니다.표준 복사 동작을 수정할 수 있습니다.DSL 정의에서 속성 창의 설정 및 관계의 한 쪽에는 역할 선택은 전파 복사 값입니다.
값이 세 개 있습니다.
복사본에 전파
복사 전용-링크 전파 그룹에 붙여 넣을 때이 링크의 새 복사본이 연결의 다른 쪽 끝에 있는 기존 요소를 참조 합니다.
연결 복사본에 전파 하 고 반대 역할 수행자-복사한 그룹 복사본을 연결의 다른 쪽 끝에 있는 요소를 포함 합니다.
변경 내용이 복사 되는 이미지와 요소에 적용 됩니다.
프로그래밍 복사 및 붙여넣기 동작
복사, 붙여넣기, 생성 및 개체 삭제와 관련 하 여 DSL의 동작의 여러 측면의 인스턴스에서 제어 되는 ElementOperations 다이어그램에 연결 됩니다.클래스에서 파생 하 여 사용자 DSL의 동작을 수정할 수 있습니다 ElementOperations 및 재정의 ElementOperations 다이어그램 클래스의 속성입니다.
팁 |
---|
프로그램 코드를 사용 하 여 모델을 사용자 지정 하는 방법에 대 한 자세한 내용은 참조 하십시오. 프로그램 코드에서 모델 탐색 및 업데이트. |
직접 Elementoperations을 정의 하려면
클래스에서 파생 된 DSL 프로젝트에서에 새 파일을 만들 DesignSurfaceElementOperations.
클래스 다이어그램에 대 한 partial 클래스 정의 추가 합니다.이 클래스의 이름에서 찾을 수 있습니다 Dsl\GeneratedCode\Diagrams.cs.
다이어그램 클래스를 재정의 하 여 ElementOperations ElementOperations 하위 클래스의 인스턴스를 반환 합니다.모든 호출에서 동일한 인스턴스를 반환 해야 합니다.
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
}
다른 모델에서 끌어 온 항목을 받기
ElementOperations 복사, 이동, 삭제, 드래그 앤 드롭 동작을 정의 하는 데도 사용할 수 있습니다.ElementOperations 사용 하는 데모 여기에 제공 된 예제 사용자 지정 드래그 앤 드롭 동작을 정의 합니다.그러나 용도에 설명 된 다른 방법을 고려할 수 있습니다 방법: 끌어서 놓기 처리기 추가, 확장할 수 있는입니다.
ElementOperations 클래스의 두 메서드를 정의 합니다.
CanMerge(ModelElement targetElement, System.Windows.Forms.IDataObject data)소스 요소의 대상 셰이프, 커넥터 또는 다이어그램으로 끌 수 있는지 여부를 결정 합니다.
MergeElementGroupPrototype(ModelElement targetElement, ElementGroupPrototype sourcePrototype)어떤 대상에 소스 요소를 결합합니다.
CanMerge()
[CanMerge()]다이어그램에서 마우스를 이동 하는 사용자에 게 부여 해야 합니다 피드백을 확인 하기 위해 호출 됩니다.메서드 매개 변수는 위에 마우스를 가져가면입니다, 요소 및 끌기 작업이 수행 된 원본에 대 한 데이터입니다.사용자가 원하는 위치 화면에서 끌 수 있습니다.따라서 원본 개체는 다양 한 종류의 수 있습니다와 다양 한 형식으로 serialize 할 수 있습니다.DSL 또는 UML 모델입니다 데이터 매개 변수 serialization의 경우는 ElementGroupPrototype.끌기, 복사 및 도구 상자 작업 ElementGroupPrototypes 모델의 일부를 나타내는 데 사용 합니다.
요소 그룹 프로토타입에 다양 한 요소에 대 한 링크를 포함할 수 있습니다.요소 유형 Guid로 식별할 수 있습니다.GUID를 내부 모델 요소 놓은 모양입니다.다음 예제에서는 CanMerge() UML 다이어그램에서 클래스 모양을이 다이어그램으로 끌 경우 true를 반환 합니다.
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()
이 메서드는 사용자 다이어그램, 도형 또는 연결선 요소 떨어질 때 호출 됩니다.이 끌어 온된 콘텐츠 대상 요소에 병합할 수 있습니다.이 예제에서는 코드 프로토타입 및 대상 형식의 조합에서 인식할 것인지 결정 합니다. 이 경우 메서드 프로토타입 모델에 추가 해야 하는 요소를 드래그 한 요소가 변환 합니다.변환 된 또는 변환 되지 않은 요소의 병합을 수행 하려면 기본 메서드가 호출 됩니다.
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);
}
UML 클래스 요소 UML 클래스 다이어그램에서 끌어 놓은 다음이 예제를 다룹니다.대신, 각 드래그 UML 클래스는 DSL 요소 만들 DSL UML 클래스에 직접 저장 하지 는지 않습니다.DSL 인스턴스 다이어그램이 있는 경우이 예를 들어, 유용 합니다.사용자 클래스가 이러한 클래스의 인스턴스를 만들 수 있는 다이어그램으로 끌어 놓을 수 있습니다.
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;
}
표준 복사 동작
이 섹션의 코드를에서 복사 동작을 변경 할 수 있습니다 하는 방법을 무시할 수 있습니다 보여 줍니다.고유의 사용자 지정을 사용 하는 방법을 볼 수 있도록이 섹션에서는 복사에 관련 된 메서드를 재정의 하는 코드를 보여 줍니다 있지만 표준 동작은 변경 되지 않습니다.
사용자가 CTRL + C을 누르거나 복사 메뉴 명령이 메서드를 사용 하 여 ProcessOnMenuCopyCommand 라고 합니다.이것의 설정 방법을 확인할 수 있습니다 DslPackage\Generated Code\CommandSet.cs.어떻게 명령을 설정 하는 방법에 대 한 자세한 내용은 참조 하십시오. 방법: 바로 가기 메뉴에 명령 추가.
Partial 클래스 정의를 추가 하 여 Processonmenucopycommand를 재정의할 수 있습니다 MyDslClipboardCommandSet 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);
}
}
각 다이어그램에는 singleton 인스턴스를 ElementOperations 있습니다.직접 파생물을 제공할 수 있습니다.DSL 프로젝트에 배치할 수 있습니다,이 파일에서이 재정의 하는 코드와 같은 동작 하는 지.
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;
}
}
}
참고 항목
개념
기타 리소스
샘플: VMSDK 회로 다이어그램 샘플