2012-09-09 24 views
8

我正在爲「模型」編寫一個圖形編輯器(例如,帶有某種語義的框和線的集合,如UML,其中的細節在這裏無關緊要) 。所以我想要有一個表示模型的數據結構,以及一個對圖表進行編輯導致模型發生相應更改的圖表。因此,例如,如果模型元素在屬性中包含一些文本,並且編輯圖中的文本,我希望模型元素得到更新。圖形模型編輯器的拉鍊數據結構

該模型可能會被表示爲一棵樹,但我想讓圖編輯器儘可能少地瞭解模型表示。 (我正在使用diagrams框架,因此將任意信息與圖形元素關聯起來很容易)。如果我能弄清楚應該是什麼,那麼可能會有一個「模型」類來對接口進行編碼。

如果我是用命令式語言來做這件事,那很簡單:我只是從圖中的圖形元素引用模型元素。理論上,我仍然可以通過從大量IORefs集合中構建模型來完成此任務,但是這將會在Haskell中編寫一個Java程序。顯然,每個圖形元素都會有一些與之關聯的cookie,這將使模型更新發生。一個簡單的答案是給每個模型元素一個唯一的標識符並將模型存儲在Data.Map查找表中。但是這需要大量的簿記來確保沒有兩個模型元素獲得相同的標識符。它也使我成爲"stringly typed"解決方案;你必須處理一個對象被刪除的情況,但在其他地方有一個懸而未決的引用,並且很難說出你的類型中模型的內部結構。

另一方面Oleg's writings關於拉鍊與多個洞和光標與清晰的事務共享聽起來像一個更好的選擇,只要我能理解它。我得到了列表和樹拉鍊的基本概念以及數據結構的差異。圖中的每個元素是否可以將光標放入模型的拉鍊中?因此,如果做出更改,則可以將其委託給所有其他遊標?包括樹操作(如將子樹從一個地方移動到另一個地方)?

如果有關於定界延續的教程,以及他們如何讓Oleg的多指針拉鍊工作,這比Oleg的貼子稍微低一點,這對我來說會特別有幫助嗎?

+1

也許Chung-chieh Shan的博客? :http://conway.rutgers.edu/~ccshan/wiki/blog/posts/WalkZip1/。請注意,Blob(wxHaskell)是一個用於編寫「網絡編輯器」的庫 - 它可能已經被破壞了,但更新它可能比重新開始使用Diagrams更不方便。 –

+0

謝謝。我已經開始瞭解它。如果它導致答案,我會通知你。 –

回答

2

我認爲你目前正在從一個設計中工作,其中模型樹中的每個節點都由一個單獨的圖形小部件表示,並且這些小部件中的每一個都可以獨立更新模型。如果是這樣,我不相信一個多孔拉鍊將是非常實用的。問題在於拉鍊的複雜性隨着您希望支持的孔的數量而迅速增長。當你獲得超過2個條件時,拉鍊的尺寸將變得相當大。從差異的角度來看,雙孔拉鍊是單孔拉鍊上的拉鍊,因此通過鏈條法則的操作增加了複雜性。

相反,你可以從MVC借鑑一個想法。每個節點仍然與一個小部件相關聯,但它們不直接通信。而是他們通過一箇中間控制器,它維護一個拉鍊。當部件更新時,他們通知控制器,該控制器將所有更新序列化並相應地修改拉鍊。

小部件仍然需要某種標識符來引用模型節點。我發現通常最容易使用節點的路徑,例如[0]爲根,[1,0]爲根的第二個孩子,等等。這有幾個優點。確定路徑引用的節點很容易,拉鍊也很容易計算從當前位置到給定節點的最短路徑。對於樹結構,它們在刪除和重新插入之前也是唯一的。即使這通常也不是問題,因爲當通知控制器應該刪除節點時,它可以刪除相應的小部件並忽略任何關聯的更新。只要小部件生命週期與每個節點的生命週期相關聯,該路徑將足夠獨特以識別任何修改。

對於樹操作,我可能會銷燬然後重新創建圖形小部件。

作爲一個例子,我有一些代碼,其中does this sort of thing。在這個模型中,每個節點都沒有單獨的窗口小部件,而是使用圖表渲染所有內容,然後根據點擊位置查詢圖表以獲取路徑進入數據模型。這遠遠沒有完成,我沒有看它一段時間,所以它可能無法建立,但代碼可能會給你一些想法。

+0

關於Oleg的拉鍊版本的事情是,它不涉及區分數據結構,而是使用延續來捕獲部分步行。 –

+0

@PaulJohnson - 即使有繼續捕捉部分漫步,仍然有相同數量的狀態來表示,這是複雜性來自的地方。它的管理方式不同,因爲Oleg在延續之間使用明確的順序,這意味着您必須通過確保延續按照正確的順序進行更新來管理複雜性。我不確定在實踐中哪種方法更簡單,但我期望任何一種方法都不是微不足道的。 –