我正在为“模型”编写一个图形编辑器(即具有某种语义的框和行的集合,例如UML,其详细信息在这里无关紧要)。所以我希望有一个表示模型的数据结构,以及一个图表,其中对图表的编辑会导致模型中的相应更改。因此,例如,如果模型元素在属性中有一些文本,并且我编辑图中的文本,我希望更新模型元素。
该模型可能会表示为树,但我希望图表编辑器尽可能少地了解模型表示。 (我正在使用diagrams框架,因此将任意信息与图形元素相关联很容易。如果我能弄明白应该是什么,可能会有一个“模型”类来编码接口。
如果我用命令式语言执行此操作,那将很简单:我只需要将图表中的图形元素引用回模型元素。从理论上讲,我仍然可以通过从大量IORef集合中构建模型来实现这一目标,但这将是在Haskell中编写Java程序。
显然,每个图形元素都会有一些与之关联的cookie,这样就可以实现模型更新。一个简单的答案是为每个模型元素提供唯一标识符,并将模型存储在Data.Map查找表中。但这需要大量的簿记才能确保没有两个模型元素获得相同的标识符。它也让我感到"stringly typed"解决方案;你必须处理一个对象被删除的情况,但在其他地方有一个悬挂的引用,很难说你的类型中模型的内部结构。
另一方面Oleg's writings关于具有多个孔的拉链和具有明确事务共享的光标听起来像是更好的选择,只要我能理解它。我得到了列表和树拉链的基本概念以及数据结构的区别。图表中的每个元素都可以将光标保存到模型的拉链中吗?那么如果进行了更改,则可以将其提交给所有其他游标?包括树操作(例如将子树从一个地方移动到另一个地方)?
在这一点上,如果有一些关于分隔延续的教程,以及它们如何使Oleg的多光标拉链工作,这比Oleg的帖子稍微陡峭一点,这对我特别有帮助吗?
答案 0 :(得分:2)
我认为您目前正在使用一种设计,其中模型树中的每个节点都由一个单独的图形窗口小部件表示,并且每个窗口小部件都可以独立更新模型。如果是这样,我不相信多孔拉链会非常实用。问题是拉链的复杂性随着你想要支持的孔的数量而迅速增长。当你超过2个术语时,拉链的尺寸会变得非常大。从差异化的角度来看,2孔拉链是单孔拉链上的拉链,因此通过链条规则的操作增加了复杂性。
相反,你可以从MVC借用一个想法。每个节点仍与一个小部件相关联,但它们不直接通信。而是通过中间控制器来维护单个拉链。更新窗口小部件时,它们会通知控制器,控制器会序列化所有更新并相应地修改拉链。
小部件仍然需要某种标识符来引用模型节点。我发现使用节点的路径通常最简单,例如[0]
为根,[1,0]
为根的第二个孩子等。这有一些优点。确定路径引用的节点很容易,拉链也很容易计算从当前位置到给定节点的最短路径。对于树结构,它们在删除和重新插入时也是唯一的。即使这通常也不是问题,因为当通知控制器应该删除节点时,它可以删除相应的小部件并忽略任何相关的更新。只要窗口小部件的生命周期与每个节点的生命周期相关联,该路径就足以识别任何修改。
对于树操作,我可能会破坏然后重新创建图形小部件。
例如,我有一些代码does this sort of thing。在这个模型中,每个节点都没有单独的小部件,而是我使用图表渲染所有内容,然后根据点击位置查询图表以获取进入数据模型的路径。它还远未完成,我暂时没有看过它,所以它可能无法构建,但代码可能会给你一些想法。