DSL 图中未显示的隔间项目

发布于 2024-07-06 19:08:22 字数 626 浏览 5 评论 0原文

好的,自从我询问 这个问题几天前。

一旦我重构了我的代码,我就会发布我自己的答案,但现在,我遇到了另一个问题。

我从 DSL 创建的模型动态生成子图,将这些图保存为图像,然后生成嵌入这些图像的 Word 文档。 到目前为止,一切都很好。

但是,如果我的形状有隔间(例如,服务合同上的操作 - 您能猜出它是什么吗?),会显示隔间标题,但没有任何项目

如果我检查我的形状对象,它有一个嵌套的子对象 - 一个 ElementListCompartment,它又包含许多我希望显示的项目。 ElementListCompartment.IsExpanded 属性设置为 true(并且隔间标题上有一个小“折叠”图标),但是我的物品在哪里?

该形状是使用添加到图表中的,

parentShape.FixupChildShapes(modelElement);

所以,任何人都可以指导我快乐的方式吗?

OK, so things have progressed significantly with my DSL since I asked this question a few days ago.

As soon as I've refactored my code, I'll post my own answer to that one, but for now, I'm having another problem.

I'm dynamically generating sub-diagrams from a DSL-created model, saving those diagrams as images and then generating a Word document with those images embedded. So far, so good.

But where my shapes have compartments (for examples, Operations on a Service Contract - can you guess what it is, yet?), the compartment header is displayed but none of the items.

If I examine my shape object, it has a single nested child - an ElementListCompartment which in turn, has a number of items that I'm expecting to be displayed. The ElementListCompartment.IsExpanded property is set to true (and the compartment header has a little 'collapse' icon on it) but where, oh where, are my items?

The shape was added to the diagram using

parentShape.FixupChildShapes(modelElement);

So, can anyone guide me on my merry way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

最笨的告白 2024-07-13 19:08:22

我最近遇到了一个相关的问题,并设法使其发挥作用,所以这就是故事。

我正在实现的任务是加载并显示域模型以及由 ActiveWriter 的 DSL 包生成的关联图。

以下是我实现所需功能的方法(下面的所有方法都属于我创建的 Form1 类):

private Store LoadStore()
{
    var store = new Store();
    store.LoadDomainModels(typeof(CoreDesignSurfaceDomainModel), typeof(ActiveWriterDomainModel));
    return store;
}

private void LoadDiagram(Store store)
{
    using (var tx = store.TransactionManager.BeginTransaction("tx", true))
    {
        var validator = new ValidationController();
        var deserializer = ActiveWriterSerializationHelper.Instance;
        deserializer.LoadModelAndDiagram(store,
            @"..\..\ActiveWriter1.actiw", @"..\..\ActiveWriter1.actiw.diagram", null, validator);
        tx.Commit();
    }
}

private DiagramView CreateDiagramView()
{
    var store = LoadStore();
    LoadDiagram(store);

    using (var tx = store.TransactionManager.BeginTransaction("tx2", true))
    {
        var dir = store.DefaultPartition.ElementDirectory;
        var diag = dir.FindElements<ActiveRecordMapping>().SingleOrDefault();
        var view = new DiagramView(){Diagram = diag};
        diag.Associate(view);
        tx.Commit();

        view.Dock = DockStyle.Fill;
        return view;
    }
}

protected override void OnLoad(EventArgs e)
{
    var view = CreateDiagramView();
    this.Controls.Add(view);
}

这个东西大部分工作得很好:它正确地从使用 Visual Studio 创建的文件加载图表,在其中绘制图表我的自定义窗口窗体支持滚动画布,甚至允许我将形状拖动到此处。 然而,有一件事困扰着我 - 隔间是空的,并且有默认名称,即“隔间”。

谷歌根本没有帮助,所以我只能自己挖。 这并不容易,但在 Reflector 的帮助下,花了几个小时后,我成功地使这个场景按预期工作!

问题如下。 令我惊讶的是,DSL 库在将某些图表元素添加到图表后并没有立即正确地绘制它们。 有时,仅绘制某些形状的存根(如第一张图片中所示)。 因此,有时我们需要手动要求库重绘图表形状。

此功能可以通过所谓的“规则”来实现,“规则”实际上是由某些图表事件触发的事件处理程序。 基本上我们要做的是将特定处理程序附加到图表的元素添加事件并确保形状初始化。

幸运的是,我们甚至不需要编写任何代码,因为 DSL 设计器会自动生成修复规则和将这些规则附加到图表的实用程序方法(请参阅下面的 EnableDiagramRules)。 我们所要做的就是在创建商店后(在加载模型和图表之前)立即调用此方法。

private Store LoadStore()
{
    var store = new Store();
    store.LoadDomainModels(typeof(CoreDesignSurfaceDomainModel), typeof(ActiveWriterDomainModel));
    ActiveWriterDomainModel.EnableDiagramRules(store);
    return store;
}

/// <summary>
/// Enables rules in this domain model related to diagram fixup for the given store.
/// If diagram data will be loaded into the store, this method should be called first to ensure
/// that the diagram behaves properly.
/// </summary>
public static void EnableDiagramRules(DslModeling::Store store)
{
    if(store == null) throw new global::System.ArgumentNullException("store");

    DslModeling::RuleManager ruleManager = store.RuleManager;
    ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.FixUpDiagram));
    ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.ConnectorRolePlayerChanged));
    ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.CompartmentItemAddRule));
    ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.CompartmentItemDeleteRule));
    ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.CompartmentItemRolePlayerChangeRule));
    ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.CompartmentItemRolePlayerPositionChangeRule));
    ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.CompartmentItemChangeRule));
}

上面的代码的工作原理如下:

  1. 在将新元素添加到图中时(例如在图的反序列化期间),规则“FixUpDiagram”将被触发。

  2. 然后该规则调用 Diagram.FixUpDiagram(parentElement, childElement),其中 childElement 代表要添加的元素,parentElement 代表其逻辑父级(使用棘手的条件逻辑确定,因此我没有尝试自己重现它)。

  3. 沿着堆栈跟踪,FixUpDiagram 方法调用图中所有类形状的 EnsureCompartments 方法。

  4. EnsureCompartments 方法重绘类的隔间,将存根“[-] Compartment”图形转换为完整的“属性”形状,如上面链接的图片所示。

    EnsureCompartments 方法重绘

PS 史蒂夫,我注意到你确实调用了修复程序,但它仍然不起作用。 好吧,我不是 DSL SDK 的专业人士(几天前才开始使用它),所以无法解释为什么你可能会遇到麻烦。

也许,您使用错误的参数调用了修复程序。 或者,Diagram.FixupDiagram(parent, newChild) 的做法可能与 Parent.FixupChildShapes(newChild) 的做法不同。 然而,这是我的可行的变体。 希望这也有帮助。

I've recently faced a related problem, and managed to make it work, so here's the story.

The task I was implementing was to load and display a domain model and an associated diagram generated by ActiveWriter's DSL package.

Here's how I've implemented the required functionality (all the methods below belong to the Form1 class I've created to play around):

private Store LoadStore()
{
    var store = new Store();
    store.LoadDomainModels(typeof(CoreDesignSurfaceDomainModel), typeof(ActiveWriterDomainModel));
    return store;
}

private void LoadDiagram(Store store)
{
    using (var tx = store.TransactionManager.BeginTransaction("tx", true))
    {
        var validator = new ValidationController();
        var deserializer = ActiveWriterSerializationHelper.Instance;
        deserializer.LoadModelAndDiagram(store,
            @"..\..\ActiveWriter1.actiw", @"..\..\ActiveWriter1.actiw.diagram", null, validator);
        tx.Commit();
    }
}

private DiagramView CreateDiagramView()
{
    var store = LoadStore();
    LoadDiagram(store);

    using (var tx = store.TransactionManager.BeginTransaction("tx2", true))
    {
        var dir = store.DefaultPartition.ElementDirectory;
        var diag = dir.FindElements<ActiveRecordMapping>().SingleOrDefault();
        var view = new DiagramView(){Diagram = diag};
        diag.Associate(view);
        tx.Commit();

        view.Dock = DockStyle.Fill;
        return view;
    }
}

protected override void OnLoad(EventArgs e)
{
    var view = CreateDiagramView();
    this.Controls.Add(view);
}

This stuff worked mostly finely: it correctly loaded the diagram from files created with Visual Studio, drew the diagram within my custom windows form, supported scrolling the canvas and even allowed me to drag shapes here. However, one thing was bugging me - the compartments were empty and had default name, i.e. "Compartment".

Google didn't help at all, so I had to dig in by myself. It wasn't very easy but with the help of Reflector and after spending a couple of hours I've managed to make this scenario work as expected!

The problem was as follows. To my surprise DSL libraries do not correctly draw certain diagram elements immediately after they are added to the diagram. Sometimes, only stubs of certain shapes are drawn (as it's displayed in the first picture). Thus, sometimes we need to manually ask the library to redraw diagram shapes.

This functionality can be implemented with so called "rules" that in fact are event handlers that get triggered by certain diagram events. Basically what we have to do is attach certain handler to an element-added event of the diagram and ensure shape initialization.

Luckily we don't even have to write any code since DSL designer autogenerates both fixup rules and an utility method that attaches those rules to the diagram (see the EnableDiagramRules below). All we have to do is to call this method right after the store has been created (prior to loading model and diagram).

private Store LoadStore()
{
    var store = new Store();
    store.LoadDomainModels(typeof(CoreDesignSurfaceDomainModel), typeof(ActiveWriterDomainModel));
    ActiveWriterDomainModel.EnableDiagramRules(store);
    return store;
}

/// <summary>
/// Enables rules in this domain model related to diagram fixup for the given store.
/// If diagram data will be loaded into the store, this method should be called first to ensure
/// that the diagram behaves properly.
/// </summary>
public static void EnableDiagramRules(DslModeling::Store store)
{
    if(store == null) throw new global::System.ArgumentNullException("store");

    DslModeling::RuleManager ruleManager = store.RuleManager;
    ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.FixUpDiagram));
    ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.ConnectorRolePlayerChanged));
    ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.CompartmentItemAddRule));
    ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.CompartmentItemDeleteRule));
    ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.CompartmentItemRolePlayerChangeRule));
    ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.CompartmentItemRolePlayerPositionChangeRule));
    ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.CompartmentItemChangeRule));
}

The code above works as follows:

  1. Upon new element being added to the diagram (e.g. during deserialization of diagram) the rule "FixUpDiagram" gets triggered.

  2. The rule then calls Diagram.FixUpDiagram(parentElement, childElement), where childElement stands for an element being added and parentElement stands for its logical parent (determined using tricky conditional logic, so I didn't try to reproduce it by myself).

  3. Down the stack trace FixUpDiagram method calls EnsureCompartments methods of all class shapes in the diagram.

  4. The EnsureCompartments method redraws class' compartments turning the stub "[-] Compartment" graphic into full-blown "Properties" shape as displayed in the picture linked above.

P.S. Steve, I've noticed that you did call the fixup but it still didn't work. Well, I'm not a pro in DSL SDK (just started using it a couple of days ago), so cannot explain why you might have troubles.

Maybe, you've called the fixup with wrong arguments. Or maybe Diagram.FixupDiagram(parent, newChild) does something differently from what parent.FixupChildShapes(newChild) does. However here's my variant that just works. Hope this also helps.

静待花开 2024-07-13 19:08:22

也许我的回答有点晚了,但是您是否使用 DSL Explorer 确认您的隔间有物品?

Maybe my answer is a little bit too late, but did you confirm using DSL Explorer that your compartments have items?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文