Идея заметки возникла в ходе обсуждения вопроса «возможно ли скопировать отображение из документа в документ, сохранив при этом общую модель?». Ответ на этот вопрос «нельзя», и ниже дается попытка дать детальное объяснение почему это запрещено в каркасе Блэкбокс.
Скопировать отображение без модели возможно только в одном документе, так как хранилище модели и хранилище отображения объединены, и также объединены в единый домен с хранилищем документа, куда отображение уже было вставлено единожды.
При открытии нового документа, у него происходит инициализация домена, и два домена уже невозможно объединить. Поэтому невозможно ни при каких условиях вставить отображение в режиме SHALLOW из другого домена. Возникает нарушение предусловия… Это сделано для того, чтобы можно было обеспечить целостность данных при сохранении документов.
Внутри документа копировать можно такими двумя процедурами:
MODULE MyCopy; IMPORT Containers, Views, TextControllers, TextModels; VAR view: Views.View; w, h: INTEGER; PROCEDURE ShallowCopy*; VAR v: Views.View; BEGIN v := Containers.FocusSingleton(); IF v # NIL THEN view := v; view.context.GetSize(w, h); END END ShallowCopy; PROCEDURE ShallowPaste*; VAR c: TextControllers.Controller; writer: TextModels.Writer; beg, end: INTEGER; BEGIN c := TextControllers.Focus(); IF (c # NIL) & (view # NIL) THEN (* Stores.Join(c.view, view); *) writer := c.text.NewWriter(NIL); c.GetSelection(beg, end); IF end > 0 THEN writer.SetPos(end) ELSE writer.SetPos(c.CaretPos()) END; writer.WriteView( Views.CopyOf(view, Views.shallow), w, h) END END ShallowPaste; END MyCopy.
При этом никто не мешает создавать много окон для отображений связанных с одной моделью, так как при этом все новые документы будут объединятся в единый домен при открытии!
VAR m: Model; ... PROCEDURE NewModel*; BEGIN NEW(m); END NewModel; PROCEDURE Open*; VAR v: View; BEGIN NEW(v); v.model := m; Stores.Join(v, m); Views.OpenView(v) END Open;
Что это дает?
1. При сохранении любого из документов на диск, в него запишется модель и отображение.
2. При закрытии одного из документов, они все закроются.
т.е. отображения одного домена ведут себя как целое.
Используем для изучения вопроса пример ObxLines. Сначала скопируем отображение в отдельное окно через Ctrl+Space, уменьшим. Дальше смотрите видео.
Модель одна, а отображения разные. При этом цвет - является параметром отображения, а линии являются параметрами модели.
При попытке вставить это отображение в другой документ «мягким» копированием, с сохранением указателя на модель, мы получаем аварийную остановку (TRAP), которая предупреждает такое действие, нарушающее изоляцию доменов. Домены обеих документов уже были инициализированы, так что не выходит их объединить. Надо делать полную копию в таком случае без «shallow». Ctrl+C Ctrl+V так и делает обычно полную копию (deep) отображения.
Авторы заметки: Иван Денисов