我正在尝试设计一个桌面UI,用于原理图、布局和绘画等方面。只是想从实际的软件设计师那里获得高级别的建议。
假设存在一个内存中的 "数据库"(包含所有用户数据的Clojure映射,以及可能包含应用程序首选项等的另一个映射),我正在研究如何在这些上执行模型-视图-控制器的操作,其中数据可以由以下任何一个或多个进行渲染 并由 修改:
- 显示单个参数(例如盒子宽度)的独立文本字段。
- 显示所选对象的多个参数(例如盒子宽度、高度、颜色、复选框等)的 "检查员" 类型视图。
- 显示多个对象的多个参数的表格/电子表格类型视图,可能是整个数据库。
- 整个东西的图形渲染,例如原理图和布局视图。
修改这些任何一个应立即出现在每个其他活动视图中,无论是文本还是图形,而不是在单击 "确定" 后...因此,不允许使用模态框。如果由于某种原因,表格视图、检查员视图和图形渲染都在视图中,那么在图形上拖动框的角应立即显示在文本等中。
所讨论的平台是JavaFX,但我想要UI和其他所有内容之间的清晰分离,因此我希望避免按照JFX意义上的绑定,因为那会将我的设计数据与JFX属性紧密地联系起来,增加了模型的粒度,并强制我在处理数据时不得不使用标准的Clojure函数,或者大量涉及整个 getValue
/setValue
世界。
我仍然假设至少存在一些状态性/可变性,并使用内置的Clojure功能,例如在原子/变量/引用上添加监视器并让运行时信号依赖函数。
特定于平台的交互将与实际的UI紧密结合,例如具体化 ActionListener
, 处理ObservableValue
等,并尝试最小化依赖诸如JavaFX Property
这样的实际应用程序数据. 我不考虑使用FRP来实现这一点.
我不介意扩展JFX界面或创建自己的协议来使用应用程序特定的defrecord
s,但我希望应用程序数据保持为纯Clojure数据,不受平台污染。
问题是如何设置所有内容,以最大程度地遵守不可变模型。我看到几个选项:
- 细粒度:每个参数值/原语(例如Long、Double、Boolean或String)都是一个atom,每个可以修改值的视图“达到”数据库中需要的范围以更改值。这可能会很糟糕,因为可能会有数千个单独的值(例如手绘曲线上的点),并且需要大量的
(deref...)
垃圾。我认为这是JFX想要做的方式,使用巨大的属性数组作为叶节点等,这感觉很臃肿。采用这种方法似乎与只在Java/C++中编码不相上下。 - 中等粒度:数据库中的每个对象/记录都是Clojure映射的一个atom。当其中任何一个值更改时,整个映射会被替换。要处理的原子总数较少,例如各种东西的长数组可以直接使用数字表示。但是,当数据库中某些对象需要比其他对象更深层嵌套时,这会变得复杂。
- 粗粒度:只有一个原子:数据库。任何时候更改任何内容,整个数据库都会被替换,每个视图都需要重新呈现其特定部分。这有点像用锤子去敲苍蝇,而且一个天真的实现将要求所有内容始终重新呈现。但我仍然认为这是最好的折衷方案,因为任何基元都有清晰的从根节点到访问路径,无论是在基元级别还是在记录级别上访问。
我还需要一个数据模板可以被多次实例化的能力。例如,如果用户更改了在多个地方使用的符号或形状,则单个编辑将应用于所有位置。我认为这也需要某种“指针”行为。我认为我可以将原子存储到模型中,然后根据需要进行实例化,并且它可以在上述任何颗粒模型中工作。
还有其他方法吗?在函数语言中尝试像GUI编辑器一样的工具只是愚蠢的吗? 谢谢