System/Docu/ru/Views.odc

Views

DEFINITION Views;

	IMPORT Files, Fonts, Stores, Ports, Converters, Models;

	CONST
		undefined = 0;
		transparent = 0FF000000H;
		deep = FALSE; shallow = TRUE;
		keepFrames = FALSE; rebuildFrames = TRUE;
		dontAsk = FALSE; ask = TRUE;
		clean = 0; notUndoable = 1; invisible = 2;

	TYPE
		View = POINTER TO ABSTRACT RECORD (Stores.Store)
			context-: Models.Context;
			(v: View) InitContext (context: Models.Context), NEW, EXTENSIBLE;
			(v: View) GetBackground (VAR color: Ports.Color), NEW, EMPTY;
			(v: View) Neutralize, NEW, EMPTY;
			(v: View) ConsiderFocusRequestBy- (view: View), NEW, EMPTY;
			(v: View) GetNewFrame (VAR frame: Frame), NEW, EMPTY;
			(v: View) Restore (f: Frame; l, t, r, b: INTEGER), NEW, ABSTRACT;
			(v: View) RestoreMarks (f: Frame; l, t, r, b: INTEGER), NEW, EMPTY;
			(v: View) HandleViewMsg- (f: Frame; VAR msg: Message), NEW, EMPTY;
			(v: View) HandleCtrlMsg (f: Frame; VAR msg: CtrlMessage; VAR focus: View), NEW, EMPTY;
			(v: View) HandlePropMsg- (VAR p: PropMessage), NEW, EMPTY;
			(v: View) HandleModelMsg- (VAR msg: Models.Message), NEW, EMPTY;
			(v: View) CopyFrom- (source: View);
			(v: View) CopyFromSimpleView- (source: View), NEW, EMPTY;
			(v: View) CopyFromModelView- (source: View; model: Models.Model), NEW, EMPTY;
			(v: View) ThisModel (): Models.Model, NEW, EXTENSIBLE
		END;

		Alien = POINTER TO LIMITED RECORD (View)
			store-: Stores.Alien
		END;

		Message = ABSTRACT RECORD
			view-: View
		END;

		NotifyMsg = EXTENSIBLE RECORD (Message)
			id0, id1: INTEGER;
			opts: SET
		END;

		Frame = POINTER TO ABSTRACT RECORD (Ports.Frame)
			l-, t-, r-, b-: INTEGER;
			view-: View;
			front-, mark-: BOOLEAN;
			(f: Frame) Close, NEW, EMPTY
		END;

		RootFrame = POINTER TO RECORD (Frame)
			flags-: SET
		END;

		PropMessage = ABSTRACT RECORD END;

		CtrlMessage = ABSTRACT RECORD END;

		CtrlMsgHandler = PROCEDURE (op: INTEGER; f, g: Frame; VAR msg: CtrlMessage;
															VAR mark, front, req: BOOLEAN);

		Title = ARRAY 64 OF CHAR;

		UpdateCachesMsg = EXTENSIBLE RECORD (Message) END;

		ScrollClassMsg = RECORD (Message)
			allowBitmapScrolling: BOOLEAN
		END;

	VAR HandleCtrlMsg-: CtrlMsgHandler;

	PROCEDURE Broadcast (v: View; VAR msg: Message);
	PROCEDURE Domaincast (domain: Stores.Domain; VAR msg: Message);
	PROCEDURE Omnicast (VAR msg: ANYREC);
	PROCEDURE HandlePropMsg (v: View; VAR msg: PropMessage);
	PROCEDURE Era (v: View): INTEGER;
	PROCEDURE BeginModification (type: INTEGER; v: View);
	PROCEDURE EndModification (type: INTEGER; v: View);
	PROCEDURE BeginScript (v: View; name: Stores.OpName; OUT script: Stores.Operation);
	PROCEDURE EndScript (v: View; script: Stores.Operation);
	PROCEDURE Do (v: View; name: Stores.OpName; op: Stores.Operation);
	PROCEDURE LastOp (v: View): Stores.Operation;
	PROCEDURE Bunch (v: View);
	PROCEDURE StopBunching (v: View);
	PROCEDURE ForwardCtrlMsg (f: Frame; VAR msg: CtrlMessage);
	PROCEDURE Update (v: View; rebuild: BOOLEAN);
	PROCEDURE UpdateIn (v: View; l, t, r, b: INTEGER; rebuild: BOOLEAN);
	PROCEDURE ReadView (VAR rd: Stores.Reader; OUT v: View);
	PROCEDURE WriteView (VAR wr: Stores.Writer; v: View);
	PROCEDURE CopyOf (v: View; shallow: BOOLEAN): View;
	PROCEDURE CopyWithNewModel (v: View; m: Models.Model): View;
	PROCEDURE ReadFont (VAR rd: Stores.Reader; OUT f: Fonts.Font);
	PROCEDURE WriteFont (VAR wr: Stores.Writer; f: Fonts.Font);
	PROCEDURE IsPrinterFrame (f: Frame): BOOLEAN;
	PROCEDURE InstallFrame (host: Frame; view: View; x, y, level: INTEGER; focus: BOOLEAN);
	PROCEDURE ThisFrame (host: Frame; view: View): Frame;
	PROCEDURE FrameAt (host: Frame, x, y: INTEGER): Frame;
	PROCEDURE Old (ask: BOOLEAN; VAR loc: Files.Locator; VAR name: Files.Name;
									VAR conv: Converters.Converter): View;
	PROCEDURE OldView (loc: Files.Locator; name: Files.Name): View;
	PROCEDURE Register (view: View; ask: BOOLEAN; VAR loc: Files.Locator; VAR name: Files.Name;
										VAR conv: Converters.Converter; OUT res: INTEGER);
	PROCEDURE RegisterView (view: View; loc: Files.Locator; name: Files.Name);
	PROCEDURE Open (view: View; loc: Files.Locator; name: Files.Name; conv: Converters.Converter);
	PROCEDURE OpenView (view: View);
	PROCEDURE OpenAux (view: View; title: Title);
	PROCEDURE Deposit (view: View);
	PROCEDURE RestoreDomain (domain: Stores.Domain);
	PROCEDURE Scroll (v: View; dx, dy: INTEGER);
	PROCEDURE SetDir (d: Directory);

	PROCEDURE MarkBorders (root: RootFrame);
	PROCEDURE MarkBorder (host: Frame; v: View; l, t, r, b: INTEGER);
	PROCEDURE Fetch (OUT view: View);
	PROCEDURE Available (): INTEGER;
	PROCEDURE ClearQueue;
	PROCEDURE RemoveFrame (host, f: Frame);
	PROCEDURE RemoveFrames (host: Frame; l, t, r, b: INTEGER);
	PROCEDURE BroadcastModelMsg (f: Frame; VAR msg: Models.Message);
	PROCEDURE BroadcastViewMsg (f: Frame; VAR msg: Message);
	PROCEDURE HandleCtrlMsg (op: INTEGER; f, g: Frame; VAR msg: CtrlMessage;
													VAR target, front: BOOLEAN);
	PROCEDURE SetRoot (root: RootFrame; view: View; front: BOOLEAN; flags: SET);
	PROCEDURE AdaptRoot (root: RootFrame);
	PROCEDURE RootOf (f: Frame): RootFrame;
	PROCEDURE HostOf (f: Frame): Frame;
	PROCEDURE UpdateRoot (root: RootFrame; l, t, r, b: INTEGER; rebuild: BOOLEAN);
	PROCEDURE RestoreRoot (root: RootFrame; l, t, r, b: INTEGER);
	PROCEDURE ValidateRoot (root: RootFrame);
	PROCEDURE InitCtrl (p: CtrlMsgHandler);
	PROCEDURE IsInvalid (v: View): BOOLEAN;
	PROCEDURE RevalidateView (v: View);

END Views.




Figure 1. Model-View-Controller Separation


Отображение - это прямоугольный объект, который представляет собой визуальное представление данных. Отображения являются хранимыми и могут внедряться одно в другое рекурсивно.
Отображение связано с Models.Model - моделью, которая представляет некоторые данные, и иногда - с диспетчером Controllers.Controller, который обеспечивает взаимодействие отображения с пользователем. Могут существовать одновременно несколько отображений для каждой модели.
Если несколько отображений разделяют одну и ту же модель, каждое изменение модели должно вызывать соответствующие обновления всех отображений. Модуль Models предоставляет механизм сообщений, через который видимые отображения могут уведомляться об изменениях модели, и согласованно перерисовывать экран.
Возможно реализовать отображения, которые не связаны с моделью. Эти отображения не могут использовать механизм сообщений модуля Models. Следовательно, такие отображения обычно не разделяют между собой данные и не являются зависимыми друг от друга. Обычно эти отображения являются простыми элементами управления, которые реализуют слишком специфичную функциональность, которая обеспечивается во взаимодействии с контейнером, например, контейнерным отображением формы.
Возможно также реализовать отображения, которые не связаны с диспетчером. Это допустимо, поскольку все сообщения к диспетчеру передаются через отображение, а не напрямую к диспетчеру. Таким образом, отображение может решать, обрабатывать ли эти сообщения самостоятельно, или же передать их дальше диспетчеру. Простые отображения не связываются с диспетчером.
Поскольку отображение является расширением Stores.Store, оно может внедряться в модель, и таким образом загружаться и выгружаться вместе с моделью. Это делает возможным реализацию составных документов, которые содержат отображения, содержащие другие отображения, которые содержат еще отображения...
Когда отображению требуется рисовать на экране (или принтере), оно может делать это через кадр. Кадр - это канал доступа (проектор) к порту, на который отображение выводится. Если несколько окон показывают один и тот же документ с его иерархией отображений, одно и то же отображение может быть видно в нескольких местах в одно и то же время. В результате получаем несколько кадров для одного отображения, и следовательно, необходимость обновлять отображение в нескольких кадрах.
В общем, реакция на изменение модели происходит в два этапа. На первом шаге природа изменения модели передается всем видимым отображениям, с использованием механизма передачи моделей модуля Models. Это позволяет каждому видимому отображению обновить свое собственное состояние, если это необходимо. На втором шаге, каждое отображение, которое изменило свое состояние, использует механизм передачи отображений модуля Views, чтобы уведомить все кадры для этого отображения. Фактически, поскольку кадры обычно не расширены, отображение само выполняет обновление каждого из своих кадров. Этот второй шаг передачи обычно невидим для программиста, поскольку ему нужно всего лишь определить, какой участок отображения надо обновить. Фактически обновление участка в каждом из его кадров осуществляется средой.
Отображение может по-разному зависеть от модели, в которую оно внедрено, то есть, зависеть от своего контекста. Для этой цели в отображение вносится переменная типа Models.Context, как ссылка на его контейнер.
При каждом взаимодействии с пользователем, например, нажатии клавиши, должно быть определено, какое отображение будет обрабатывать это взаимодействие, то есть, так называемый фокус. BlackBox не знает, какое отображение является текущим фокусом. Поскольку окно может содержать иерархию отображений, отображение, которое получает сообщение о взаимодействии - диспетчерское сообщение - должно решить самостоятельно, когда оно само является фокусом, или когда фокусом является его внедренное отображение. В первом случае, оно обрабатывает сообщение самостоятельно, во втором - передает сообщение внедренному отображению.
Каждое окно содержит дерево кадров. Это дерево соответствует видимым отображениям окна. Каждое отображение может рисовать только внутри своих границ, рисование за этими границами должно пресекаться. Кадры предоставляют необходимые возможности отсечения. Управление деревом кадров и отсечением является, в основном, прозрачным для программиста отображений.

Примеры:
ObxPatternsdocu	отображения без модели
ObxCalcdocu
ObxOmosidocu
ObxButtonsdocu
ObxLinesdocu	отображения с моделью
ObxGraphsdocu
ObxBlackBoxdocu
ObxWrappersdocu	обертка
ObxTwinsdocu	специальный контейнер
Formsubsystemmap	общий контейнер


CONST undefined
Это значение указывает, когда ширина или высота отображения неопределены.

CONST transparent
Отображение может быть опрошено о цвете фона. В этом случае отображение может вернуть как значение типа Ports.Color, так и transparent. Последнее означает, что контейнер, содержащий отображение, должен найти другой источник фонового цвета, то есть, того цвета, который используется для стирания фона перед восстановлением переднего плана (используйте Update или UpdateIn для восстановления области отображения во всех его кадрах). Прозрачность полезна, когда несколько отображений наложены одно на другое, что обычно происходит в составных документах.

CONST deep, shallow
Есть два способа, которым отображение может быть копировано: глубокое (deep) и мелкое (shallow). Такое разделение происходит из факта, что отображение может обладать двумя типами данных: данными, которые принадлежат ему полностью, и данными, которые оно разделяет с другими отображениями. Наиболее важным примером последних является модель отображения, если она есть.
Когда отображение копируется, необходимо решить, следует ли оставить состояние общим с копией (мелкое копирование), или создать независимую копию этого состояния (глубокое копирование). Эти константы могут передаваться параметрами в процедуры CopyModel или CopyOf.

CONST keepFrames, rebuildFrames
Когда часть области отображения должна быть восстановлена (в каждом его кадре), есть два возможных типа восстановления: кадр может быть оставлен как есть и только его содержимое перерисовано, или он может быть перестроен, то есть, заново размещен, установлен и перерисован. Последнее менее эффективно, чем первое, и требуется только в следующих случаях: отображение должно быть контейнером, и операция, которая изменяет отображение, может изменять границу вложенного отображения (и тем самым делать негодными все подкадры). В редких случаях, когда кадры расширяются, также может потребоваться перестройка кадров к отображению.

CONST dontAsk, ask
Эти константы могут передаваться в процедуры Old и Register. Они определяют, когда эти процедуры позволяют пользователю интерактивно изменять loc, name или conv, которые используются для операции.

CONST clean
Возможное значение для параметра type процедур BeginModification/EndModification. Показывает, что операция не делает документ "грязным", несохраненным. Пример: изменение текста, которое расценивается как "неважное", такое как раскрытие и свертка текстовых складок (-> StdFolds).

CONST invisible
Возможное значение для параметра type процедур BeginModification/EndModification. Показывает, что операция складывается вместе с предыдущей операцией, то есть, не видна сама по себе в Отменить/Вернуть. Пример: установка настроек в диспетчере. При выполнении Возврата, после видимой операции, выполняются все невидимые. При выполнении операции Отмены, сначала отменяются все невидимые операции, и после - видимые.

CONST notUndoable
Возможное значение для параметра type процедур BeginModification/EndModification. Показывает, что операция необратима (не может быть отменена). Это важно для операций, отмена которых будет слишком дорогостоящей.


TYPE View (Stores.Store)
ABSTRACT
Отображение - это хранимый объект, который может содержать модель, возможно, поддерживать позицию прокрутки для этой модели, и генерировать кадры для ее показа, когда это необходимо. Отображение можно считать специальным редактором, и расширенные отображения (контейнеры) могут содержать любое количество других отображений как часть своих редактируемых данных (например, модели). Отображения размещаются особыми директориями отображений, например, TextViews.dir.
Отображения используются командами, которые управляют визуальным представлением данных.
Отображения расширяются для новых типов данных, которые нужно визуально представлять. После реализации новых команд, реализация новых расширений отображений - основная деятельность программирования BlackBox.
Restore - единственная процедура, которая должна быть реализована в расширениях View. Она вызывается средой, когда отображение должно быть перерисовано на экране или принтере.
Internalize, Externalize должны быть реализованы в отображениях, которые содержат перманентные изменяемые данные. В этом случае отображению без модели следует также реализовать процедуру CopyFromSimpleView, в то время как отображение с моделью должно реализовывать вместо этого процедуру CopyFromModelView. Internalize/Externalize вызываются средой, когда пользователь открывает / сохраняет документ. CopyFromSimpleView / CopyFromModelView следует также реализовать для отображений с изменяемым состоянием, которые должны быть печатаемыми. Причиной является то, что среда делает мелкую копию отображения, которое печатается, во избежание влияния изменений исходного отображения в процессе печати.
ThisModel должна быть реализована в отображениях, которые содержат модель. Процедура вызывается средой для обнаружения того, что это отображение должно получать сообщения для модели.
ConsiderFocusRequestBy следует реализовать для контейнерных отображений. Процедура вызывается внедренными отображениями, которые хотят получить фокус.
GetBackground должна быть реализована в отображениях, которые имеют непрозрачные цвета фона. Процедура вызывается механизмом восстановления дисплея среды.
RestoreMarks и Neutralize должны быть реализованы в отображениях, которые могут содержать метки, подобные выделению или каретке. RestoreMarks вызывается механизмом восстановления дисплея среды, после вызова соответствующего Restore.
HandleModelMsg должна быть реализована в отображениях, которые поддерживают частичное обновление после изменения модели. Процедура вызывается средой для доставки уведомлений об изменениях в модели отображения.
HandleViewMsg должна быть реализована в отображениях, которые поддерживают метки, или которые не используют механизм отложенного обновления по каким-либо другим причинам. Процедура вызывается средой для передачи сообщений отображения через все текущие видимые пути (то есть, через кадры) к этому отображению.
HandleCtrlMsg должна быть реализована в редактируемых отображениях. Процедура вызывается окружающим контейнером, если он считает получающее отображение текущим фокусом.
HandlePropMsg должна быть реализована в отображениях, которые поддерживают настройки и свойства (-> Properties). Процедура вызывается окружающим контейнером для выяснения такого, каким образом желало бы быть представленным вложенное отображение.
InitContext и GetNewFrame обычно не расширяются.
Домен отображения является общим с его контейнером и всеми внедренными отображениями и моделями. Домен индентифицирует документ, в который внедрено отображение и его контекст. Процедура отображения PropagateDomain распространяет переданный домен на его модель, если она есть.

context-: Models.Context
Контекст связывает отображение с его контейнером. Контекст принадлежит (и управляется) контейнером, но доступен отображению.

PROCEDURE (v: View) InitContext (context: Models.Context)
NEW, EXTENSIBLE
Присваивает context к v.context.
InitContext вызывается контейнером отображения v, когда v внедряется внего (что означает, что контейнер создает подходящий контекст для v).
InitContext обычно не расширяется, только отображения-обертки расширяют его для передачи оборачиваемому отображению.

Предусловие
context # NIL	21
v.context = NIL OR v.context = context	22

Постусловие
v.context = context

PROCEDURE (v: View) GetBackground (VAR color: Ports.Color)
NEW, EMPTY
Эта процедура может возвращать фоновый цвет отображения. Во время ввода color = transparent.
GetBackground вызывается внутри среда.
GetBackground реализовывается, если отображению требуется непрозрачный фон.

PROCEDURE (v: View) Neutralize
NEW, EMPTY
Эта процедура должна удалять все метки, которые нанесены на отображение.
Neutralize вызывается средой.
Neutralize реализуется отображениями, которые могут содержать метки.

PROCEDURE (v: View) ConsiderFocusRequestBy- (view: View)
NEW, EMPTY
Под-отображение, вложенное в v, может запросить на себя фокус. Контейнер может удовлетворить или отвергнуть этот запрос.
ConsiderFocusRequestBy вызывается вложенным отображением.
ConsiderFocusRequestBy реализуется в контейнерных отображениях.

PROCEDURE (v: View) GetNewFrame (VAR f: Frame)
NEW, EMPTY
Процедура может генерировать кадр для отображения. На входе f = NIL.
Эта процедура редко реализовывается (в основном в традиционных элементах управления).
GetNewFrame вызывается внутри среды.
GetNewFrame реализуется в отображениях, которые нуждаются в специализированных кадрах.

PROCEDURE (v: View) Restore (f: Frame; l, t, r, b: INTEGER)
NEW, ABSTRACT
Реализация отображения должна реализовать эту процедуру для отрисовки всего или части своего содержания. Для рисования отображению передается кадр, процедуры которого могут вызываться в процедуре Restore.
В обновлении нуждается только прямоугольник (l, t, r, b), заданный в универсальных координатах. Поскольку рисование автоматически усекается до этого прямоугольника, иногда лучшим решением будет восстановить содержимое отображения целиком. Однако часто значительно быстре восстановить только содержимое прямоугольника.
Если необходимо, размер отображения может быть определен вызовом v.context.GetSize. В соответствии с операциями рисования кадра (как они описаны в документации к модулю Ports), началом для перерисовки является верхний левый угол, с положительно значениями x направо и положительными значениями y вниз.
Для рисования в точечном разрешении экрана без ошибок округления полезно поле кадра f.dot. Значение f.unit может быть использовано для получения размера пиксела в универсальных координатах (см. документацию модуля Fonts). Например, это позволяет приспособиться к различным разрешениям экрана и принтера. Если рисование должно производиться различным образом в зависимости от того, рисуется ли отображение на экране или на принтере, можно использовать для определения этого процедуру Views.IsPrinterFrame.
Restore вызывается внутри среды всякий раз, когда какая-либо часть отображения становится вновь видимой, или после вызова кем-либо Views.Update или Views.UpdateIn для этого отображения. Restore редко вызывается напрямую. Не допустимо делать какие-либо предположения о том, когда и с какой частотой и т.п. вызывается Restore. Restore должна просто отрисовывать все, что находится в заданном прямоугольники, она не может предполагать, что что-то уцелело на экране с прошлого раза.
Поскольку отображения могут быть вложенными, контейнер должен быть отрисован прежде, чем содержащиеся отображения отрисуют себя. Среда вызывает метод Restore в правильном порядке, от "задних" к "передним". При этом внедренные отображения всегда лежат "выше", чем их контейнер. Как исключение из этого правила, BlackBox позволяет отрисовать метки (в частности, выделение) контейнера поверх внедренных отображений. Это может быть выполнено методом отображения RestoreMarks. Это необходимо только для контейнерных отображений.
Restore должна быть реализована в любом расширении отображения. Это единственная процедура, реализация которой обязательна.

Предусловие
f # NIL	20
f.view = v	21
v.context # NIL	22
0 <= f.l <= l <= r <= f.r <= width of view	23
0 <= f.t <= t <= b <= f.b <= height of view	24

PROCEDURE (v: View) RestoreMarks (f: Frame; l, t, r, b: INTEGER)
NEW, EMPTY
Отрисовывает все метки (в частности, выделение) отображения v в кадр f. Нужно восстановить только прямоугольник (l, t, r, b), который задан в универсальных координатах. Кадр содержит метод MarkRect, который предназначен специально для отрисовки меток.
RestoreMarks вызывается механизмом восстановления экрана среды, после вызова соответствующего Restore.
RestoreMarks реализовывается в отображениях, которые поддерживают какой-либо вид меток, например, выделение, каретку или метки фокуса.

Предусловие
f # NIL	20
f.view = v	21
v.context # NIL	22

PROCEDURE (v: View) HandleViewMsg- (f: Frame; VAR msg: Message)
NEW, EMPTY
Обработчик сообщений для сообщений отображению.
HandleViewMsg вызывается средой.
HandleViewMsg реализовывается в отображениях, которые поддерживают метки (например, выделение), и в отображениях, которые поддерживают различное содержимое кадров (редкий случай).

Предусловие
f # NIL	гарантировано
f.view = v	гарантировано
v.context # NIL	гарантировано
msg.view = v  OR  msg.view = NIL	гарантировано

PROCEDURE (v: View) HandleCtrlMsg (f: Frame; VAR msg: CtrlMessage; VAR focus: View)
NEW, EMPTY
Обработчик сообщений для сообщений фокусу.
HandleCtrlMsg вызывается контейнером, содержащим отображение, непосредственно через ForwardCtrlMsg. Если диспетчерское сообщение требуется передать дальше внедренному отображению, установите focus в это отображение. Среда выполнит передачу после возврата из HandleCtrlMsg. В редких случаях, когда это не является адекватным решением, следует использовать ForwardCtrlMsg; методы HandleCtrlMsg внедренных отображений никогда не следует вызывать напрямую. После вызова ForwardCtrlMsg, focus должен быть установлен в NIL, чтобы сообщение не передавалось дважды.
Во время движения мыши (например, при обработке Controllers.TrackMsg), рисование следует производить только в кадре f. Это подразумевает также, что во время движения мыши никакие сообщения об обновлении не должны посылаться. Если необходимо, сообщение обновления модели может быть послано после отпускания кнопки мыши.
HandleCtrlMsg расширяется в редактируемых отображениях.

Предусловие
f # NIL	20
f.view = v	21
v.context # NIL	22
focus = NIL	23

PROCEDURE (v: View) HandlePropMsg- (VAR p: PropMessage)
NEW, EMPTY
Сообщения свойств могут передаваться отображению через его процедуру HandlePropMsg.
HandlePropMsg вызывается контейнером, содержащим отображение. Глобальная процедура HandlePropMsg (см. ниже) используется для посылки отображению сообщений свойств.
HandlePropMsg вызывается локально средой.
HandlePropMsg реализуется в отображениях, которые поддерживают свойства (не описанные здесь).

PROCEDURE (v: View) HandleModelMsg- (VAR msg: Models.Message)
NEW, EMPTY
Обработчик сообщений для сообщений модели.
HandleModelMsg вызывается локально средой.
HandleModelMsg реализуется в отображениях с моделью, которая поддерживает обновления после модификации.

Предусловие
msg.model # NIL	20
msg.model = v.ThisModel()	21

PROCEDURE (v: View) CopyFrom- (source: Stores.Store)
Этот метод финальный. Он вызывает соответственно CopyFromSimpleView или CopyFromModelView. Он проверяет, что эти процедуры не изменяют контекст отображения.

PROCEDURE (v: View) CopyFromSimpleView- (source: View)
NEW, EMPTY
Эта процедура должна бы реализована в отображениях, которые не имеют модели. Она должна копировать специфичные для отображения данные из source. CopyFromModelView вызывается как часть операций копирования модуля Views (CopyOf, CopyWithNewModel).
Замечание: не допустимо реализовывать одновременно и CopyFromModelView, и CopyFromSimpleView!

Предусловие
source # NIL	гарантировано
TYP(source) = TYP(v)	гарантировано
CopyFromModelView не должна быть реализована	20

PROCEDURE (v: View) CopyFromModelView- (source: View; model: Models.Model)
NEW, EMPTY
Эта процедура должна бы реализована в отображениях, которые имеют модель, и только в них. Главное исключение, когда отображение без модели может также реализовывать CopyFromModelView вместо CopyFromSimpleView - это отображения-обертки: используя CopyFromModelView, они могут оборачивать любые отображения, независимо от того, имеют они модель или нет.
Процедура должна инициализировать свою модель в model. Если необходимо, она может копировать из source специфичные для отображения данные. CopyFromModelView вызывается как часть операций копирования модуля Views (CopyOf, CopyWithNewModel).
Если model = source.ThisModel(), то будет выполнено мелкое копирование.
Замечание: не допустимо реализовывать одновременно и CopyFromModelView, и CopyFromSimpleView!

Предусловие
source # NIL	гарантировано
TYP(source) = TYP(v)	гарантировано
model # NIL  =>  TYP(model) = TYP(source.ThisModel())	гарантировано
CopyFromSimpleView не должна быть реализована	20

Постусловие
v.ThisModel() = model

PROCEDURE (v: View) ThisModel (): Models.Model
NEW, EXTENSIBLE
Возвращает модель отображения, если она есть. Стандартная реализация возвращает NIL.
ThisModel вызывается внутренне.
ThisModel переопределяется для отображений, которые содержат модели. Отображение с моделью должны всегда возвращать одну модель, то есть, ту, которая была присвоена им при инициализации.


TYPE Alien (View)
LIMITED
Если загрузка отображения срывается из-за того, что реализующий модуль не может быть загружен, или из-за отмены загрузки (например, из-за конфликта версий), вместо отображения создается нелегал (это происходит в процедуре ReadView). Нелегал неизменяем и не имеет модели. Он включает хранимый объект, который можно просмотреть для определения типа нелегала и причин его возникновения.
Любой контейнер должен продолжать работать, даже если один или несколько внедренных отображений - нелегалы. Если модель отображения является нелегальным хранимым объектом, отображение может само перевести себя в нелегал.
Нелегалы размещаются в ReadView.

store-: Stores.Alien	store # NIL
Хранимый объект нелегала, который создается Stores.Reader'ом при загрузке отображения.


TYPE Message
ABSTRACT
Базовый тип всех сообщений отображений. Такие сообщения посылаются при изменении состояния отображения, в целях соответствующего обновления экрана. Может быть несколько кадров, показывающих отображение, так что каждый из них нуждается в обновлении.
Сообщения посылаются отображениями, когда их состояние изменяется, и если они не могут использовать механизм отложенного обновления BlackBox. Это верно в основном для рисования меток, например, выделения.
Сообщения расширяются, чтобы показать, какой тип обновления следует выполнить в кадре.

view-: View
Отображение, которое изменилось. Если view = NIL, все кадры в одном домене уведомляются об изменении отображения.


TYPE NotifyMsg (Message)
EXTENSIBLE
Это сообщение уведомляет все видимые отображения об изменении состояния интерактора (-> Dialog).
NotifyMsg посылается процедурами обновления интерактора Update и UpdateList модуля Dialog.
NotifyMsg никогда не расширяется.
NotifyMsg посылается только внутренне.

id0, id1: INTEGER
Идентификаторы интерактора или одного из его полей.

opts: SET
Определяют, например, когда элементы управления (здесь не описываются) должны проверить свои процедуры охраны.


TYPE Frame (Ports.Frame)
ABSTRACT
Все операции ввода-вывода для отображения проходят через кадр. Кадр полностью управляет расположением отображений на порте, включая отсечение. Сообщения модели и отображения передаются через деревья кадров. Внутренняя структура дерева кадров скрыта. Кадры являются легкими объектами, они создаются и освобождаются BlackBox всякий раз, когда это необходимо, например, когда изменяется размер окна кадра. Следовательно, их нельзя использовать для хранения специфического состояния приложения, разве что в целях буферизации.
Кадры размещаются процедурой отображения GetNewFrame.
Управление кадрами идет внутри среды, они передаются параметрами в процедуры отображений, когда это необходимо.
Стандартные кадры достаточны для большинства целей, и поэтому они редко расширяются.

l-, t-, r-, b-: INTEGER	0 <= l <= r  &  0 <= t <= b
Видимая область отображения в данном кадре. Значения задаются в универсальных координатах, относительно верхнего левого угла отображения.
Например, f.l + f.gx - это расстояние левой границы кадра от левой границы порта (экрана, принтера) в универсальных координатах; (f.l + f.gx) DIV f.unit - то же расстояние в точках растра.

view-: View	view # NIL
The frame's view.
Отображение, принадлежащее кадру.

front-: BOOLEAN
Флаг, указывающий, что кадр является частью переднего окна.

mark-: BOOLEAN
Флаг, который указывает, что кадр находится на пути фокуса своего окна, то есть, когда следует отрисовывать метки (каретку, выделение). Обычно процедуры пометки работают следующим образом:

	IF f.mark THEN
		IF f.front THEN DrawMark(f) ELSE DrawBackgroundMark(f) END
	END

PROCEDURE (f: Frame) Close
NEW, EMPTY
Выполняет завершающие действия перед тем, как кадр будет удален.
После вызова Close f.view и f.rider устанавливаются в NIL и вызвается f.ConnectTo(NIL).
Close вызывается внутренне.


TYPE RootFrame
Этот тип используется внутренне.

flags-: SET
Флаги, специфичные для окна. Зарезервировано для будущего использования.


TYPE PropMessage
ABSTRACT
Используйте свои псевдонимы Properties.Message вместо.


TYPE CtrlMessage
ABSTRACT
Базовый тип всех диспетчерских сообщений. Используйте свои псевдонимы Controllers.Message вместо.


TYPE CtrlMsgHandler
Для внутреннего использования.


TYPE Title
Тип для названий отображений, например, в окнах.


TYPE UpdateCachesMsg (Message)
EXTENSIBLE
Для внутреннего пользования.

TYPE ScrollClassMsg (Message)
EXTENSIBLE
Для внутреннего пользования.


PROCEDURE Broadcast (v: View; VAR msg: Message)
Передает msg отображению view. Перед передачей параметр v присваивается полю сообщения view. Фактическая передача имеет место только если v.domain # NIL.
Broadcast вызывается отображением всякий раз, когда его состояние изменяется и механизма отложенного обновления не достаточно, например, для обновления специфичных для кадра меток, v будет получать msg один раз для каждого своего видимого кадра.
Обработчик сообщения отображения не может рекурсивно передавать другое сообщение отображения, так как это может повлечь нарушение порядка получения сообщений относительно посылки, и привести к ошибкам, которые очень трудно обнаружить.

Предусловие
v # NIL	20
без рекурсии	21

Постусловие
msg.view = v

PROCEDURE Domaincast (domain: Stores.Domain; VAR msg: Message)
Передает msg внутрь домена. Для визуальных объектов домен соответствует документу объекта. Domaincast необходима только в исключительных случаях; обычно сообщения отображений посылаются в случаях, когда известно соответствующее отображение, а не только его домен. В этих случаях, Broadcast является более подходящей (и быстрой) процедурой.

PROCEDURE Omnicast (VAR msg: ANYREC)
Передает msg всем открытым отображениям, независимо от их доменов (то есть, от их документа). Все отображения будут получать это сообщение с msg.view = NIL. Omnicast медленнее, чем Broadcast, и необходима только в исключительных случаях, например, для отображений часов, которые должны обновляться каждую секунду.

PROCEDURE HandlePropMsg (v: View; VAR msg: PropMessage)
Используйте эту процедуру для посылки сообщения свойств отображению. Это эквивалентно:
	v.HandlePropMsg(msg)
за исключением того, что допускается значительно лучшая обработка ошибок.

PROCEDURE Era (v: View): INTEGER
Для отображений с моделью возвращает эру, в которой отображение было последний раз синхронизировано с моделью.

Предусловие
v # NIL	20

Постусловие
v.ThisModel() # NIL
	in-synch(v) iff Era(v) = Models.Era(v.ThisModel())

PROCEDURE BeginModification (type: INTEGER; v: View)
PROCEDURE EndModification (type: INTEGER; v: View)
PROCEDURE BeginScript (v: View; name: Stores.OpName; OUT script: Stores.Operation)
PROCEDURE EndScript (v: View; script: Stores.Operation)
PROCEDURE Do (v: View; name: Stores.OpName; op: Stores.Operation)
PROCEDURE LastOp (v: View): Stores.Operation
PROCEDURE Bunch (v: View)
PROCEDURE StopBunching (v: View)
Эти процедуры обрабатывают изменения отображения. Они используются таким же образом, как их аналоги в модуле Models (-> Models). Заметим, что эти процедуры предоставляются для удобства, они в основном идентичны аналогам Models. Единственное заметное отличие в том, что операции отображения затрагивают только это отображение и не влияют на другие отображения, даже если они показывают одну и ту же модель. Например, скрипт, который изменяет модель отображения, должен использовать процедуру из Models, чтобы все отображения обновлялись корректно. Скрипт, который изменяет только собственное состояние отображения, должен использовать приведенные выше процедуры.

PROCEDURE ForwardCtrlMsg (f: Frame; VAR msg: CtrlMessage)
Эту процедуру следует использовать для посылки диспетчерского сообщения через путь фокуса. Обычно она вызывается из реализации HandleCtrlMsg. Это необходимо только если не подходит установка параметра focus в HandleCtrlMsg равным внедренному отображению, к которому должна произойти передача. В свою очередь, это необходимо только если HandleCtrlMsg должна сделать что-либо после дальнейшей передачи сообщения. В этом случае она вызывает ForwardCtrlMsg и затем убеждается, что focus = NIL.

Предусловие
f # NIL	20

PROCEDURE Update (v: View; rebuild: BOOLEAN)
Вызывает восстановление отображения v, во всех кадрах, показывающих v. Обновление происходит отложенно, после завершения текущей выполняемой команды. rebuild следует устанавливать в keepFrames для не-контейнеров или для операций, которые не изменяют расположение в контейнере (то есть, места и размеры внедернных отображений). В противном случае следует передавать rebuildFrames.

Предусловие
v # NIL	20

PROCEDURE UpdateIn (v: View; l, t, r, b: INTEGER; rebuild: BOOLEAN)
Вызывает восстановление прямоугольника (l, t, r, b) отображения v во всех кадрах, показывающих v. Обновление происходит отложенно, после завершения текущей выполняемой команды. rebuild следует устанавливать в keepFrames для не-контейнеров или для операций, которые не изменяют расположение в контейнере (то есть, места и размеры внедернных отображений). В противном случае следует передавать rebuildFrames.

Предусловие
v # NIL	20

PROCEDURE ReadView (VAR rd: Stores.Reader; OUT v: View)
Считывает отображение v, используя считыватель rd. Если загрузка невозможна, возвращается нелегальное отображение.

PROCEDURE WriteView (VAR wr: Stores.Writer; v: View)
Записывает отображение v, используя записыватель wr. Нелегальное отображения обрабатываются корректно.

PROCEDURE CopyOf (v: View; shallow: BOOLEAN): View
Возвращает мелкую или глубокую копию v.

Предусловие
v # NIL	20

Постусловие
result # NIL

PROCEDURE CopyWithNewModel (v: View; m: Models.Model): View
Копирует отображение и присваивает новую модель копии.

Предусловие
v # NIL	20
v.ThisModel() # NIL	21
m # NIL	22
TYP(m) = TYP(v.ThisModel())	23

PROCEDURE ReadFont (VAR rd: Stores.Reader; OUT f: Fonts.Font)
Читает шрифт из считывателя.

Постусловие
f # NIL

PROCEDURE WriteFont (VAR wr: Stores.Writer; f: Fonts.Font)
Записывает шрифт в записыватель.

Предусловие
f # NIL	20

PROCEDURE IsPrinterFrame (f: Frame): BOOLEAN
Эта функция может быть использована для определения, когда отображение кадра f восстанавливается на принтер либо на порт предварительного просмотра.

Предусловие
f # NIL	20

PROCEDURE InstallFrame (host: Frame; view: View; x, y, level: INTEGER; focus: BOOLEAN)
Если view не имеет соответствующего внедренного кадра в host, Install размещает и устанавливает новый кадр для него, иначе сохраняется существующий кадр. Параметры x и y задают позицию верхнего левого угла относительно верхнего левого угла контейнера (то есть, host.view).  На порядок кадров можно повлиять передачей уровня отображения, на котором view находится логически. Уровни не обязаны быть уникальными (передавайте 0, если вас это не заботит, например, вы никогда не имеете перекрывающихся кадров). Кадр всегда лежит "выше" других кадров с меньшими уровнями. Параметр focusЏговорит, что кадр является частью пути фокуса.

Предусловие
host # NIL	20
host открыт в окне	21
view # NIL	22
view.context # NIL	23
view.Domain() # NIL	24

PROCEDURE ThisFrame (host: Frame; view: View): Frame
Ищет внедренный кадр в host, который содержит отображение view.

Предусловие
host # NIL	20

Постусловие
result = NIL
	view = NIL  OR  not found
result # NIL
	view # NIL  &  found
	result.view = view

PROCEDURE FrameAt (host: Frame; x, y: INTEGER): Frame
Ищет внедренный кадр в host, который содержит точку (x, y).

Предусловие
host # NIL	20

Постусловие
result = NIL
	нет внедренных кадров в (x, y)
result # NIL
	результат содержит (x, y)

PROCEDURE Old (ask: BOOLEAN; VAR loc: Files.Locator; VAR name: Files.Name;
								VAR conv: Converters.Converter): View
Эта процедура просматривает файл, считывает из него документ и затем возвращает корневое отображение этого документа. Если файл уже открыт в окне, корневое отображение документа в окне возвращается вместа чтения его из файла. Параметр ask задает, опрашивается или нет пользователь интерактивно о триаде (loc, name, conv) через стандартный файловый диалог.
loc, name, conv трактуются как входные-выходные параметры. Их входные значения используются по умолчанию. Если ask, то пользователь может изменить их.
loc, name задают файл, из которого читается документ.
conv задает конвертор, который используется для чтения документа. conv = NIL означает, что необходимости в преобразовании нет, то есть, формат файла стандартен для BlackBox.

Предусловие
ask  OR  loc # NIL	20
ask  OR  name # ""	21

Постусловие
result = NIL
	loc.res # 0
result # NIL
	loc.res = 0
	result.context # NIL
~ask
	loc = loc'  &  name = name'  &  conv = conv'

PROCEDURE OldView (loc: Files.Locator; name: Files.Name): View
OldView - аббревиатура для Old(dontAsk, loc, name, NIL).

PROCEDURE Register (view: View; ask: BOOLEAN; VAR loc: Files.Locator;
										VAR name: Files.Name; VAR conv: Converters.Converter;
										OUT res: INTEGER)
Сохраняет документ отображения view в файл. Параметр ask задает, опрашивается или нет пользователь интерактивно о триаде (loc, name, conv) через стандартный файловый диалог.
loc, name, conv трактуются как входные-выходные параметры. Их входные значения используются по умолчанию. Если ask, то пользователь может изменить их.
loc, name задают файл, в который документ записывается.
conv задает конвертор, который используется для записи документа. conv = NIL означает, что необходимости в преобразовании нет, то есть, файл получает стандартный формат BlackBox.

Предусловие
view # NIL	20
ask  OR  loc # NIL	22
ask  OR  name # ""	23

Постусловие
операция была успешной
	res = 0
операция не удалась
	res # 0

PROCEDURE RegisterView (view: View; loc: Files.Locator; name: Files.Name)
RegisterView - аббревиатура Register(view, dontAsk, loc, name, nil, res).

PROCEDURE Open (view: View; loc: Files.Locator; name: Files.Name;
									conv: Converters.Converter)
Открывает view в новом окне. (loc, name) задают файл, ассоциированный с отображением, если он есть. conv - это конвертер, который будет использован, когда пользователь сохранит документ. conv = NIL передается, когда требуется сохранение в стандартном формате BlackBox. 

Предусловие
view # NIL	20
(loc = NIL) = (name = "")	21

PROCEDURE OpenView (view: View)
OpenView is an abbreviation of Open(view, NIL, "", NIL).

PROCEDURE OpenAux (view: View; title: Title)
Opens view in an auxiliary window with title title.

Pre
view # NIL	20
title # ""	21

PROCEDURE Deposit (view: View)
Помещает отображение в буфер обмена для последующего использования, обычно для открытия в окне или вставки в фокусе.
Процедура обычно используется командами размещения, то есть, командами, которые размещают и затем помещают в буфер отображение конкретного типа.

Предусловие
view # NIL	20

PROCEDURE RestoreDomain (domain: Stores.Domain)
Эта процедура вызывает принудительное восстановление всех регионов для отображений домена domain.
Обычно экран обновляется отложенным образом, то есть, обновляемый регион строится для всех устаревших областей отображения (используя Update и UpdateIn), и экран обновляется в соотвествии с этим регионом во время простоя среды, то есть, между командами. Однако иногда необходимо принудительное обновление экрана во время команды. Для этого может быть использована данная процедура. Необходимость в принудительном обновлении возникает при прокрутке: если отображение прокручивается, эффект прокрутки должен становиться видимым немедленно.

PROCEDURE Scroll (v: View; dx, dy: INTEGER)
Прокручивает содержимое каждого кадра от v на (dx, dy).

Предусловие
v # NIL	20

PROCEDURE SetDir (d: Directory)
Устанавливает директорию.

Предусловие
d # NIL	20

Постусловие
stdDir' = NIL
	stdDir = d
stdDir' # NIL
	stdDir = stdDir'
dir = d

Следующие процедуры предназначены для внутреннего использования:

PROCEDURE MarkBorders (root: RootFrame)
PROCEDURE MarkBorder (host: Frame; view: View; l, t, r, b: INTEGER)
PROCEDURE Fetch (OUT view: View)
PROCEDURE Available (): INTEGER
PROCEDURE ClearQueue
PROCEDURE RemoveFrame (host, f: Frame)
PROCEDURE RemoveFrames (host: Frame; l, t, r, b: INTEGER)
PROCEDURE BroadcastModelMsg (f: Frame; VAR msg: Models.Message)
PROCEDURE BroadcastViewMsg (f: Frame; VAR msg: Message)
PROCEDURE HandleCtrlMsg (op: INTEGER; f, g: Frame; VAR msg: CtrlMessage;
													VAR target, front, req: BOOLEAN)
PROCEDURE SetRoot (root: RootFrame; view: View; front: BOOLEAN; flags: SET)
PROCEDURE AdaptRoot (root: RootFrame)
PROCEDURE RootOf (f: Frame): RootFrame
PROCEDURE HostOf (f: Frame): Frame
PROCEDURE UpdateRoot (root: RootFrame; l, t, r, b: INTEGER; rebuild: BOOLEAN)
PROCEDURE RestoreRoot (root: RootFrame; l, t, r, b: INTEGER)
PROCEDURE ValidateRoot (root: RootFrame)
PROCEDURE InitCtrl (p: CtrlMsgHandler)
PROCEDURE IsInvalid (v: View): BOOLEAN
PROCEDURE RevalidateView (v: View)