Std/Docu/ru/TabViews.odc

StdTabViews
ENGLISH
Редакция перевода: Ф.В.Ткачев, 2010-10-31

DEFINITION StdTabViews;

	IMPORT Views, Dialog, StdCFrames;

	CONST
		noTab = -1;
		
	TYPE
		Directory = POINTER TO ABSTRACT RECORD 
			(d: Directory) New (): View, NEW, ABSTRACT
		END;

		Frame = POINTER TO ABSTRACT RECORD (StdCFrames.Frame)
			(f: Frame) GetDispSize (OUT x, y, w, h: INTEGER), NEW, ABSTRACT;
			(f: Frame) InDispArea (x, y: INTEGER): BOOLEAN, NEW, ABSTRACT;
			(f: Frame) SetIndex (i: INTEGER), NEW
		END;

		FrameDirectory = POINTER TO ABSTRACT RECORD 
			(d: FrameDirectory) GetTabSize (VAR w, h: INTEGER), NEW, ABSTRACT;
			(d: FrameDirectory) New (): Frame, NEW, ABSTRACT
		END;

		View = POINTER TO LIMITED RECORD (Views.View)
			(tv: View) GetItem (i: INTEGER; OUT label: Dialog.String; OUT v: Views.View), NEW;
			(tv: View) GetNewFrame (VAR frame: Views.Frame);
			(tv: View) GetNotifier (OUT notifier: Dialog.String), NEW;
			(tv: View) HandleCtrlMsg (f: Views.Frame; VAR msg: Views.CtrlMessage; VAR focus: Views.View);
			(tv: View) Index (): INTEGER, NEW;
			(tv: View) Neutralize;
			(tv: View) NofTabs (): INTEGER, NEW;
			(tv: View) Restore (f: Views.Frame; l, t, r, b: INTEGER);
			(tv: View) SetIndex (i: INTEGER), NEW;
			(tv: View) SetItem (i: INTEGER; label: Dialog.String; v: Views.View), NEW;
			(tv: View) SetNofTabs (nofTabs: INTEGER), NEW;
			(tv: View) SetNotifier (IN notifier: ARRAY OF CHAR), NEW
		END;
		
		NotifierProc = PROCEDURE (tv: View; from, to: INTEGER);

	VAR
		dir-: Directory;
		dlg: RECORD 
			name, notifier: Dialog.String;
			opt: INTEGER
		END;
		frameDir-: FrameDirectory;
		frameStdDir-: FrameDirectory;
		setFocus: BOOLEAN;
		stdDir-: Directory;

	PROCEDURE AddTab;
	PROCEDURE BeginChanges (tv: View);
	PROCEDURE Delete;
	PROCEDURE DeleteGuard (VAR par: Dialog.Par);
	PROCEDURE Deposit;
	PROCEDURE EndChanges (tv: View);
	PROCEDURE Focus (): View;
	PROCEDURE InitDialog;
	PROCEDURE LabelGuard (VAR par: Dialog.Par);
	PROCEDURE LayoutModeGuard (VAR par: Dialog.Par);
	PROCEDURE Left;
	PROCEDURE MaskModeGuard (VAR par: Dialog.Par);
	PROCEDURE ModeNotifier (op, from, to: INTEGER);
	PROCEDURE NewGuard (VAR par: Dialog.Par);
	PROCEDURE NotifierGuard (VAR par: Dialog.Par);
	PROCEDURE Rename;
	PROCEDURE RenameGuard (VAR par: Dialog.Par);
	PROCEDURE Right;
	PROCEDURE SetDir (d: Directory);
	PROCEDURE SetFrameDir (d: FrameDirectory);
	PROCEDURE SetGuard (VAR par: Dialog.Par);
	PROCEDURE SetNotifier;
	PROCEDURE This (v: Views.View): View;

END StdTabViews.


Объект отрисовки типа StdTabViews.View предъявляет пользователю набор закладок. Каждая закладка состоит из заголовка и некоторой вьюшки. Когда пользователь кликает по заголовку, показывается содержимое соответствующей вьюшки (ниже такая закладка будет называться передней прим. ред.). Попробуйте проделать это здесь:




В этом примере использованы вьюшки FormViews, но можно было бы использовать любой объект типа Views.View.

Есть два способа создания StdTabViews: программно или интерактивно, используя графический интерфейс. В большинстве случаев достаточно средств графического интерфейса. Для более сложных случаев предусмотрен программный интерфейс, описанный далее.

Чтобы воспользоваться графическим интерфейсом, нужно в документ или на форму вставить StdTabViews.View. Это делается командой меню Controls -> Insert Tab View (Формы -> Вставить закладки). Новый объект StdTabViews.View содержит две закладки, названные Tab1 и Tab2, и с каждой из них связана (пустая) диалоговая форма FormViews.View. Вновь созданные закладки выглядят так:




Этот пример полностью функционален, хотя и не слишком интересен. Если StdTabViews.View находится в фокусе, то каждую закладку можно редактировать как обычную диалоговую форму. Можно мышкой бросать на нее элементы управления и перемещать их, а также менять их свойства. В этом можно убедиться, экспериментируя с объектом выше.

Чтобы добавить, удалить или изменить имя закладки, нужно открыть редактор свойств для типа StdTabViews. Для этого нужно выделить объект закладок и выполнить Edit->Object Properties... (Правка->Свойства объекта...). Редактор свойств выглядит так:



Кнопки и поля имеют следующие значения:
<-
Клик по этой кнопке перемещает переднюю закладку на одну позицию влево. То есть меняется порядок закладок.

->
Клик по этой кнопке перемещает переднюю закладку на одну позицию вправо. То есть меняется порядок закладок.

Label
Показывает заголовок передней закладки.

Rename
Меняет заголовок передней закладки на текст, введенный в поле Label. Пустой заголовок не допускается.

New Tab
Добавляет новую закладку. Ее заголовком будет текст в поле Label. Если там пусто, новой закладки создано не будет.

Delete
Удаляет переднюю закладку.

Notifier
Показывает имя процедуры-уведомителя, которая связана с объектом закладок.

Set
Использует имя в поле Notifier для установки процедуры-уведомителя объекта закладок.

All tabs in Layout Mode
Переводит все закладки в режим разметки. Это один из режимов работы с контейнерами, в нем допускается редактирование. Подробнее о режимах контейнеров см. ниже раздел О режимах контейнеров.

All tabs in Mask Mode
Переводит все закладки в режим маски. Это один из режимов работы с контейнерами, в нем невозможно выделить вьюшки, содержащиеся в контейнере. 
Подробнее о режимах контейнеров см. ниже раздел О режимах контейнеров.

О процедурах-уведомителях
Уведомители для StdTabViews отличаются от уведомителей для обычных элементов управления Controls, но работают похожим образом. Отличается сигнатура (см. тип StdTabViews.NotifierProc), и посылается только один тип уведомления. 

Уведомитель вызывается, только когда другая закладка становится передней. При вызове параметр tv содержит объект закладок StdTabViews.View, который послал уведомление, from и to  старая и новая передняя закладка соответственно.

При сохранении объекта закладок сохраняется и номер передней закладки, так что когда объект закладок вновь загружается, передняя закладка устанавливается в соответствии с сохраненным значением индекса. Это позволяет проектировщику диалога управлять тем, какая из закладок окажется передней при открытии диалога. Это также дает способ найти в диалоге объект закладок StdTabViews.View. Когда при загрузке первый раз устанавливает передняя закладка, вызывается обработчик с параметром tv, равным новому StdTabViews.View, параметру from присваивается константа noTab и параметру to присваивается индекс передней закладки, сохраненный при выгрузке.

Это означает, что каждый раз при открытии документа с объектом StdTabViews.View будет вызываться уведомитель, и это позволяет приложению при необходимости связаться с StdTabViews.View. Это простой способ получить доступ к программному интерфейсу, описанному ниже.

О режимах контейнеров
Контейнеры могут иметь различные режимы. FormViews.View является контейнером и может, например, быть переведен в режим разметки или в режим маски. В режиме разметки можно выделять вьюшки, содержащиеся в контейнере, такие как элементы управления, и перемещать их. С другой стороны, в режиме маски нельзя выделять или перемещать вьюшки, содержащиеся в контейнере.

Режимы контейнера могут переключаться с помощью меню Dev (Программирование), но обычно это не нужно. Обычный способ  сохранить документ в режиме редактирования или разметки, а затем открыть его в требуемом режиме командами из StdCmds. Например, диалоги обычно сохраняются в режиме разметки и затем открываются в режиме маски командой StdCmds.OpenAuxDialog.

Проблема в том, что StdTabViews нарушает эту схему: ведь каждая закладка может содержать свой собственный контейнер в его собственном режиме. Поэтому необходимо использовать меню Dev (Программирование), чтобы перевести закладки в правильный режим перед сохранением диалога. Чтобы использовать режимы контейнера и меню Dev (Программирование), нужно кое-что знать о контейнерах. Чтобы обойти это препятствие, предусмотрены переключатели "All tabs in Layout Mode" ("Все закладки в режиме разметки") и "All tabs in Mask Mode" ("Все закладки в режиме маски"). Эти кнопки позволяют установить все закладки в режим маски перед сохранением диалога или все закладки в режим разметки для правки диалога, что избавляет от необходимости обращаться к меню Dev (Программирование).

CONST noTab
Константа используется для присваивания параметру from в при вызове процедуры-уведомителя, когда загружается StdTabViews.View.

TYPE View = POINTER TO LIMITED RECORD (Views.View)
Позволяет пользователю выбирать различные вьюшки, кликая по закладкам.

PROCEDURE (tv: View) SetItem (i: INTEGER; label: Dialog.String; v: Views.View)
NEW
Добавляет новую закладку в tv. Новая закладка получает label в качестве заголовка и v в качестве своей вьюшки. i указывает позицию закладки среди других закладок. Если i больше чем tv.NofTabs(), то количество закладок в tv увеличивается, если нет, то старая закладка в позиции i заменяется на новую. Перед добавлением в tv делается глубокая копия v.

Предусловие
i >= 0
label # ""
v # NIL

PROCEDURE (tv: View) GetItem (i: INTEGER; OUT label: Dialog.String; OUT v: Views.View)
NEW
Возвращает заголовок и вьюшку i-й закладки.

Предусловие
i >= 0
i < tv.NofTabs()

PROCEDURE (tv: View) SetNofTabs (nofTabs: INTEGER)
NEW
Обеспечивает наличие в tv в точности nofTabs закладок. Отметим, что SetItem тоже увеличивает количество закладок в View при необходимости, так что вызывать SetNofTabs реально нужно только для уменьшения числа закладок.

Предусловие
nofTabs >= 0

Постусловие
tv.NofTabs() = nofTabs

PROCEDURE (tv: View) NofTabs (): INTEGER, NEW;
NEW
Возвращает количество закладок в tv.

Постусловие
Возвращаемое значение >= 0

PROCEDURE (tv: View) SetIndex (i: INTEGER)
NEW
Делает i-ю закладку в tv передней, и отрисовывает tv. Когда закладки переключаются вызовом SetIndex, уведомитель не вызывается.

Предусловие
i >= 0
i < tv.NofTabs()

Постусловие
tv.Index() = i

PROCEDURE (tv: View) Index (): INTEGER
NEW
Возвращает номер передней закладки. Номер изменяется, когда пользователь кликает по закладке или когда вызвается SetIndex.

Постусловие
Возвращаемое значение >= 0 и < tv.NofTabs()

PROCEDURE (tv: View) SetNotifier (IN notifier: ARRAY OF CHAR)
NEW
Устанавливает уведомитель для tv в соответствии с notifier . Допускается notifier=""; это трактуется как отсутствие у tv уведомителя. См. выше Об уведомителях.

PROCEDURE (tv: View) GetNotifier (OUT notifier: Dialog.String)
NEW
Возвращает в параметре notifier уведомитель для tv. Если tv не имеет уведомителя, то возвращается пустая строка.

TYPE Directory 
ABSTRACT
Тип фабричного объекта для StdTabViews.View.

PROCEDURE (d: Directory) New (): View
NEW, ABSTRACT
Размещает и возвращает новый View.

TYPE NotifierProc = PROCEDURE (tv: View; from, to: INTEGER)
Сигнатура процедур-уведомителей для StdTabViews. Вызовы уведомителей позволяют оповестить приложение о переключении пользователем закладок StdTabViews.View.
Параметры имеют следующий смысл:
tv 	= объект StdTabViews.View, в котором была переключена закладка
from	= передняя закладка до переключения. Имеет значение noTab, если уведомитель вызван при загрузке
to 	= новая передняя закладка

VAR dir-, stdDir-: Directory	dir # NIL  &  stdDir # NIL
Фабричные объекты для создания StdTabViews.View.

PROCEDURE SetDir (d: Directory)
Установить фабричный объект.

PROCEDURE Deposit
Размещает новый View, используя dir.New, добавляет две закладки и ставит его в глобальную очередь (см. deposit).

PROCEDURE This (v: Views.View): View
Проверяет саму вьюшку v, а если это контейнер, то все внедренные в нее вьюшки (если таковые есть) и возвращает первый найденный объект типа StdTabViews.View. Если StdTabViews.View не найден, то возвращается NIL.

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

PROCEDURE Focus (): View
Ищет в фокусе объект типа StdTabViews.View. Если таковой найден, он возвращается, иначе возвращается NIL. Если в фокусе более одного такого объекта, то не определено, какой из них будет возвращен.

PROCEDURE BeginChanges (tv: View)
Приостанавливает отрисовку объекта закладок tv, пока не произойдет вызова EndChanges. Каждый вызов BeginChanges должен быть закрыт вызовом EndChanges, иначе произойдет аварийная остановка (Trap в StdTabViews.BalanceAction.Do). Вызовы могут быть вложенными. BeginChanges и EndChanges дают возможность вносить сразу несколько изменений в StdTabViews.View без немедленной отрисовки после каждого.

Предусловие
Количество вызовов BeginChanges >= количества вызовов EndChanges, 20

PROCEDURE EndChanges (tv: View)
Возобновляет отрисовку для tv после вызова BeginChanges.

Предусловие
Количество вызовов BeginChanges >= количества вызовов EndChanges, 20


Следующие типы, переменные и процедуры используются только внутри Блэкбокса для управления фреймами вьюшек типа StdTabViews:

TYPE Frame = POINTER TO ABSTRACT RECORD (StdCFrames.Frame)
TYPE FrameDirectory = POINTER TO ABSTRACT RECORD 

VAR frameDir-, frameStdDir-: FrameDirectory 

PROCEDURE SetFrameDir (d: FrameDirectory)
PROCEDURE (f: Frame) GetDispSize (OUT x, y, w, h: INTEGER), NEW, ABSTRACT
PROCEDURE (f: Frame) InDispArea (x, y: INTEGER): BOOLEAN, NEW, ABSTRACT
PROCEDURE (f: Frame) SetIndex (i: INTEGER), NEW
PROCEDURE (d: FrameDirectory) GetTabSize (VAR w, h: INTEGER), NEW, ABSTRACT
PROCEDURE (d: FrameDirectory) New (): Frame, NEW, ABSTRACT


Следующие типы, переменные и процедуры используются только редактором свойств для объектов типа StdTabViews.View:

VAR dlg: RECORD 
			name, notifier: Dialog.String;
			opt: INTEGER
		END;

PROCEDURE AddTab
PROCEDURE Delete
PROCEDURE DeleteGuard (VAR par: Dialog.Par)
PROCEDURE InitDialog
PROCEDURE LabelGuard (VAR par: Dialog.Par)
PROCEDURE LayoutModeGuard (VAR par: Dialog.Par);
PROCEDURE Left
PROCEDURE MaskModeGuard (VAR par: Dialog.Par);
PROCEDURE ModeNotifier (op, from, to: INTEGER);
PROCEDURE NewGuard (VAR par: Dialog.Par)
PROCEDURE NotifierGuard (VAR par: Dialog.Par)
PROCEDURE Rename
PROCEDURE RenameGuard (VAR par: Dialog.Par)
PROCEDURE Right
PROCEDURE SetGuard (VAR par: Dialog.Par)
PROCEDURE SetNotifier

Следующая переменная предназначена только для внутреннего использования в каркасе Блэкбокса:

VAR setFocus: BOOLEAN