System/Docu/ru/Models.odc

Models

DEFINITION Models;

	IMPORT Stores;

	CONST clean = 0; notUndoable = 1; invisible = 2; notRecorded = 3;

	TYPE
		Model = POINTER TO ABSTRACT RECORD (Stores.Store)
			PROCEDURE (m: Model) Domain (): Stores.Domain, NEW
		END;

		Context = POINTER TO ABSTRACT RECORD
			(c: Context) ThisModel (): Model, NEW, ABSTRACT;
			(c: Context) GetSize (OUT w, h: INTEGER), NEW, ABSTRACT;
			(c: Context) SetSize (w, h: INTEGER), NEW, EMPTY;
			(c: Context) Normalize (): BOOLEAN, NEW, ABSTRACT;
			(c: Context) Consider (VAR p: Proposal), NEW, EMPTY;
			(c: Context) MakeVisible (l, t, r, b: INTEGER), NEW, EMPTY
		END;

		Proposal = ABSTRACT RECORD END;

		Message = ABSTRACT RECORD
			model-: Model;
			era-: INTEGER
		END;

		UpdateMsg = EXTENSIBLE RECORD (Message) END;
		NeutralizeMsg = RECORD (Message) END;

	PROCEDURE CopyOf (m: Model): Model;
	PROCEDURE Broadcast (model: Model; VAR msg: Message);
	PROCEDURE Domaincast (d: Stores.Domain; VAR msg: Message);
	PROCEDURE BeginModification (type: INTEGER; m: Model);
	PROCEDURE EndModification (type: INTEGER; m: Model);
	PROCEDURE BeginScript (m: Model; name: Stores.OpName; OUT script: Stores.Operation);
	PROCEDURE EndScript (m: Model; script: Stores.Operation);
	PROCEDURE Do (m: Model; name: Stores.OpName; op: Stores.Operation);
	PROCEDURE LastOp (m: Model): Stores.Operation;
	PROCEDURE Bunch (m: Model);
	PROCEDURE StopBunching (m: Model);
	PROCEDURE Era (m: Model): INTEGER;

END Models.




Рис. 1. Разделение "модель-отображение-диспетчер"


Модель - это первая составляющая триады Модель-Отображение-Контроллер. Модель предоставляет некоторые данные, не зная о том, как эти данные могут быть представлены. Представление выполняется отображением. Одну и ту же модель могут одновременно показывать несколько отображений, и возможно, различным образом.

Когда модель изменяется, отправляется сообщение модели, которое передается домену, которому эта модель принадлежит (например, домену документа, частью которого модель является). Сообщения модели принимаются соответствующими отображениями, так что они могут обновить свой вид в соответствии с изменением модели, которое было сделано.

Изменение модели может быть постоянным или обратимым. Чтобы получить постоянное изменение, следует вызвать BeginModification/EndModification перед/после изменений. Обратимые изменения ("отменяемые операции") реализованы в виде объектов Stores.Operation. Несколько операций на одной модели могут объединяться в одной (то есть, в целиком отменяемой/повторяемой) операции парой процедур BeginScript/EndScript.

Модель может быть контейнером, то есть, содержать внедренные отображения. Внедренное отображение может сообщаться с моделью, в которую оно внедрено, через Context. Модель контейнера предоставляет контекст для каждого внедренного отображения. Используя этот контекст, отображение может запросить свой текущий размер или попытаться его изменить.

Все модели в документе разделяют один домен, то есть, их поля области или равны NIL (когда документ не показан ни в одном окне), или ссылаются на одну и ту же область. Различные отображаемые документы имеют различные домены.

Примеры:
ObxLinesdocu
ObxGraphsdocu
ObxCapsdocu/sources	составные команды (отменяемые скрипты)


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

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

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

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


TYPE Model (Stores.Store)
ABSTRACT
Модель предоставляет некоторые данные, которые могут быть представлены отображением.
Модели размещаются специальными директориями моделей, например, Text.dir.
Модели используются командами, которые могут оперировать данными, представляемыми моделью.
Модели расширяются, когда необходимо представлять новый тип отображаемых данных.
Домен модели описывает границы документа, в который она внедрена.
Процедура модели InitDomain должна быть реализована, если модель может (прямо или косвенно) содержать другие объекты Stores.Store, например, если модель может содержать отображения.
Процедуры модели Internalize, Externalize, CopyFrom должны быть реализованы, если требуется хранить состояние перманентно.

PROCEDURE (m: Model) Domain (): Stores.Domain
NEW
Возвращает домен модели, обычно представляющий некоторый документ. Если домен равен NIL, то модель не отображается. Домен устанавливается процедурой Stores.InitDomain.


TYPE Context
ABSTRACT
Объект контекста является частью рекурсивной схемы модель-отображение, принятой в BlackBox. Контекст создается и поддерживается отображением, так что отображение может сообщаться со своим контекстом (то есть, с моделью, в которую оно внедрено).
Context позволяет внедренному отображению сообщаться со своим контейнером.
Context расширяется для каждой модели контейнера.

PROCEDURE (c: Context) ThisModel (): Model
NEW, ABSTRACT
Возвращает модель контекста. NIL может быть возвращен, если контекст не хочет открывать свою принадлежность. ThisModel может быть сужена в расширении.

PROCEDURE (c: Context) GetSize (OUT w, h: INTEGER)
NEW, ABSTRACT
Возвращает ширину и высоты внедренного отображения в его контейнере, в универсальных единицах.

Постусловие
w >= 0  &  h >= 0

PROCEDURE (c: Context) SetSize (w, h: INTEGER)
NEW, EMPTY
Просит контейнер адаптировать размер отображения c к заданным ширине и высоте. Контейнер может выполнять или не выполнять этот запрос.

PROCEDURE (c: Context) Normalize (): BOOLEAN
NEW, ABSTRACT
Определяет, следует ли внедренному отображению нормализовать свое перманентное состояние перед выгрузкой, и что не следует делать изменение его состояния отменяемым.
Как пример, рассмотрим позицию прокрутки текстового отображения: если отображение находится в корневом контексте, то есть, на верхнем уровне отображений, оно должно при выгрузке записать позицию 0 (то есть, "нормализовано") как текущую позицию прокрутки, и оно не должно делать операции прокрутки отменяемыми. Однако, если оно внедрено не в корневой контекст, оно должно записать свою текущую позицию прокрутки и сделать операции прокрутки отменяемыми.
Normalize вызывается в процедуре Externalize отображения и тогда, когда необходимо определить, должна ли операция быть отменяемой или нет.

PROCEDURE (c: Context) Consider (VAR p: Proposal)
NEW, EMPTY
Если внедренное отображение хочет, чтобы контейнер что-либо сделал, оно должно запросить такое изменение, посылая контейнеру Proposal через процедуру Consider. Контейнер может, но не обязан, сотрудничать подходящим образом. BlackBox в настоящий момент не предопределяет свои собственные предложения.

PROCEDURE (c: Context) MakeVisible (l, t, r, b: INTEGER)
NEW, EMPTY
Прокручивает контейнер отображения c так, что прямоугольник (l, t, r, b) становится по крайней мере частично видимым.


TYPE Proposal
ABSTRACT
Базовй тип для всех предложение. Предложение - это сообщение, которое отображение может посылать контейнеру, в который оно внедрено (через его объект контекста).


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

model: Model	model # NIL
Модель, которая была изменена.

era-: INTEGER
Для внутреннего пользования.


TYPE UpdateMsg (Message)
EXTENSIBLE
Все сообщения модели, которые уведомляют об изменении модели, должны быть расширениями UpdateMsg. Базовое (нерасширенное) UpdateMsg показывает, что модель, пославшая его, была изменена некоторым неопределенным образом.
UpdateMsgs используется для уведомления всех отображений, показывающих данную модель, о ее изменении.
UpdateMsgs расширяется в целях обновления отображений более специфичным образом, чем полной перерисовкой (то есть, быстрее и с меньшим мерцанием экрана), например, чтобы позволить частичное обновление.


TYPE NeutralizeMsg (Message)
Расширение
Это сообщение посылается средой, чтобы показать, что метки (выделения и тому подобные) должны быть убраны.


PROCEDURE CopyOf (m: Model): Model
Возвращает копию (глубокую) модели. Внутри себя метод клонирует m и вызывает его метод CopyFrom.

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

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

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

Предусловие
model # NIL	20
нет рекурсии	21

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

PROCEDURE Domaincast (d: Stores.Domain; VAR msg: Message)
Эта процедура посылает сообщение конкретному домену, или не делает ничего, если домен равен NIL. Каждое отображение в домене получит сообщение. Обычно вы будете использовать Broadcast для уведомления отображений только конкретной модели. Domaincast необходим только, если содержимое некоторого отображения (например, текстовой линейки) влияет на что-либо вне самого отображения (например, форматирует текст после линейки). Domaincast фактически выполняется, только если d # NIL.

Domaincast может не выполниться, если другая передача происходит в данный момент для этого домена (не должно быть рекурсии).

Предусловие
нет рекурсии	20

Постусловие
msg.model = NIL

PROCEDURE BeginModification (type: INTEGER; m: Model)
Если модель m изменяется таким образом, что это не может быть отменено, изменения должны быть "взяты в скобки" вызовами BeginModification и EndModification с параметров type, установленным в notUndoable. Параметр type может принимать значения из следующего набора: {clean, notUndoable, invisible, notRecorded}.

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

PROCEDURE EndModification (type: INTEGER; m: Model)
Если модель m изменяется таким образом, что это не может быть отменено, изменения должны быть "взяты в скобки" вызовами BeginModification и EndModification с параметров type, установленным в notUndoable. Параметр type может принимать значения из следующего набора: {clean, notUndoable, invisible, notRecorded}.

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

PROCEDURE BeginScript (m: Model; name: Stores.OpName; OUT script: Stores.Operation)
Чтобы сделать последовательность отменяемых операций отменяемыми как единое целое, эту последовательность следует "взять в скобки" BeginScript и EndScript.

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

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

PROCEDURE EndScript (m: Model; script: Stores.Operation)
Чтобы сделать последовательность отменяемых операций отменяемыми как единое целое, эту последовательность следует "взять в скобки" BeginScript и EndScript. В EndScript должен быть передан тот же script, который был возвращен BeginScript.

Предусловие
m # NIL	20
script # NIL	21

PROCEDURE Do (m: Model; name: Stores.OpName; op: Stores.Operation)
Эта процедура вызывается для выполнения операции на модели. Вызывается процедура Do операции, и операция записывается для последующей отмены.

Предусловие
m # NIL	20
op # NIL	21

Постусловие
op.inUse

PROCEDURE LastOp (m: Model): Stores.Operation
Эта процедура возвращает самую последнюю операцию, выполненную на данной модели. Это может использоваться для принятия решения о том, когда следует связать несколько успешных операций в одну единственную атомарную операцию, например, если в текст вводится символ, он может быть связан с предыдущим введенным символом; так что отмена будет применена сразу ко всему введенному тексту, а не к каждому символу отдельно.

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

PROCEDURE Bunch (m: Model)
Уведомляет модель, что другое действие было связано с самой последней выполненной операцией. После того, как будет установлено, что новая операция может быть слита с самой последней операцией (для теста используется LastOp), предыдущая операция может быть изменена (например, к ее строке добавлен символ, который был введен), и это изменение делается известным среде через вызов Bunch.

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

PROCEDURE StopBunching (m: Model)
Предупреждает любое дальнейшее связывание с текущей операцией модели.

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

PROCEDURE Era (m: Model): INTEGER
Вызывается внутри системы.

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