Std/Docu/ru/Folds.odc

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

DEFINITION StdFolds;

	IMPORT TextModels, Views, Dialog;

	CONST expanded = FALSE; collapsed = TRUE;

	TYPE
		Label = ARRAY 32 OF CHAR;

		Fold = POINTER TO RECORD (Views.View)
			leftSide-, collapsed-: BOOLEAN;
			label-: Label;
			(fold: Fold) Flip, NEW;
			(fold: Fold) FlipNested, NEW;
			(fold: Fold) HiddenText (): TextModels.Model, NEW;
			(fold: Fold) MatchingFold (): Fold, NEW
		END;

		Directory = POINTER TO ABSTRACT RECORD 
			(d: Directory) New (collapsed: BOOLEAN; label: Label;
          										hiddenText: TextModels.Model): Fold, NEW, ABSTRACT
		END;

	VAR
		foldData: RECORD 
			nested, all: BOOLEAN;
			findLabel, newLabel: Label
		END;
		dir-, stdDir-: Directory;

	PROCEDURE CollapseFolds (text: TextModels.Model; nested: BOOLEAN; IN label: ARRAY OF CHAR);
	PROCEDURE ExpandFolds (text: TextModels.Model; nested: BOOLEAN; IN label: ARRAY OF CHAR);
	PROCEDURE Collapse;
	PROCEDURE Expand;
	PROCEDURE ZoomOut;
	PROCEDURE ZoomIn;
	PROCEDURE Overlaps (text: TextModels.Model; beg, end: INTEGER): BOOLEAN;
	PROCEDURE Insert (text: TextModels.Model; label: Label; beg, end: INTEGER; collapsed: BOOLEAN);
	PROCEDURE CreateGuard (VAR par: Dialog.Par);
	PROCEDURE Create (state: INTEGER);
	PROCEDURE SetDir (d: Directory);
	PROCEDURE FindFirstFold;
	PROCEDURE FindNextFold;
	PROCEDURE CollapseLabel;
	PROCEDURE ExpandLabel;
	PROCEDURE SetLabel;
	PROCEDURE SetLabelGuard (VAR p: Dialog.Par);
	PROCEDURE FindLabelGuard (VAR par: Dialog.Par);

END StdFolds.


Складка  это пара специальных объектов отрисовки (вьюшек; будем называть их левой и правой вьюшками складки; в оригинале сами эти вьюшки тоже называются складками/fold, что иногда неудобно прим. ред.). Такие вьюшки имеют смысл только при вставке парой в текст. Пара ограничивает один (видимый) фрагмент текста, скрывая в себе другой (скрытый). Клик по фрагменту текста между правой и левой вьюшкой складки делает видимый фрагмент скрытым и наоборот. При повторном клике складка возвращается в исходное состояние. Поскольку изначальное назначение складок  скрывать длинные фрагменты текста, заменяя их более короткими заголовками, говорят, что складки развернуты или свернуты. Попробуйте!

	Это фрагмент текста, спрятанный в складкетекст между вьюшками свёрнутой складки

Складки могут быть вложенными, но фрагменты разных складок не должны перекрываться частично. Иерархически вложенные складки часто используются в текстах программ. Если скрывать последовательности операторов в складках, оставляя видимыми короткие комментарии, то получающийся программный текст может исследоваться интерактивно по принципу сверху-вниз. Попробуйте этот пример!

	PROCEDURE Enter (id: INTEGER; name: TextMappers.String; value: REAL);
	VAR n, h, p: Node;
	BEGIN
		NEW(n); n.id := id; n.name := name; n.value := value;создание нового узла n
		h := list; p := NIL;
		WHILE (h # NIL) & (h.id <= id) DO p := h; h := h.next END;поиск позиции в списке
		IF p # NIL THEN
			p.next := nвставка между p и h
		ELSE
			list := nвставка в начало
		END;
		n.next := hвставка в список
	END Enter;ввод нового значения в список

Избежать многократных кликов при исследовании глубокой иерархии складок можно, прижимая при клике клавишу Ctrl(Windows)/Option(Mac). Тогда разворачиваются или сворачиваются все вложенные складки.

К работе со складками имеют отношение следующие пункты меню. Create Fold (Создать складку) в меню Tools (Инструменты) вставляет новую пару вьюшек складки вокруг выделенного текста. Развернуть все (Expand All) в том же меню разворачивает все складки в тексте, находящемся в фокусе. Аналогично, Свернуть все (Collapse All) сворачивает все складки в тексте, находящемся в фокусе.

Команда Fold... (Складка...) в меню Tools (Инструменты) открывает диалог-инспектор, позволяющий управлять складками в тексте, находящемся в фокусе. Инспектор выглядит так:


Find First ищет в тексте первое вхождение складок. Если отмечена опция All, то будет найдена и выделена самая первая складка в тексте. Иначе ищется складка с меткой, равной цепочке литер в поле Find. Find Next ищет следующую складку по тем же критериям, что и Find First.

Collapse сворачивает все складки в тексте, находящемся в фокусе, которые отвечают критериям поиска, заданным элементами All и Find. Если отмечена опция Nested, то ищутся и вложенные складки, и они тоже сворачиваются.

Expand разворачивает складки, ипользуя опции All, Find, Nested аналогично команде Collapse.

Когда складка найдена или выделена пользователем, ее метка показывается в поле около кнопки SetLabel. Можно изменить метку, введя в поле новую и нажав SetLabel.

Для описания пред- и постусловий процедур, экпортируемых из StdFolds, ниже используются следующие псевдопроцедуры:

Pos(f)	позиция вьюшки складки f в содержащем ее тексте.
0 <= Pos(f) < text.Length().

Stretch(p1, p2)	фрагмент текста [p1,p2), если p1<p2, 
иначе фрагмент текста [p2, p1).

Flipped(f) 	обозначает складку в состоянии, противоположном текущему:
f.state = collapsed <=> Flipped(f).state = expanded.

Типичные команды меню (в стандартной конфигурации Блэкбокса от поставщика в меню Tools (Инструменты) некоторые команды могут быть опущены):

MENU
	"Create Fold"	""	"StdFolds.Create(1)"	"StdFolds.CreateGuard"
	"Expand All"	""	"StdFolds.Expand"	""
	"Collapse All"	""	"StdFolds.Collapse"	""
	"Fold..."	""	"StdCmds.OpenToolDialog('Std/Rsrc/Folds', 'Zoom')"	""
END


CONST collapsed, expanded
Возможные значения поля Fold.collapsed.


TYPE Label
Тип литерных цепочек для значений метки.


TYPE Fold (Views.View)
Тип вьюшек складки.

leftSide-: BOOLEAN
Сообщает, является ли вьюшка левой в своей паре или правой.

collapsed-: BOOLEAN
Сообщает, свернута складка или нет.

label-: Label
Литерная цепочка, показывающая метку складки. Если у складки метки нет, то label = "".

PROCEDURE (fold: Fold) Flip
NEW
Изменяет состояние складки. Фрагмент текста S между вьюшкой fold и fold.MatchingFold() заменяется скрытым текстом fold.HiddenText(). Фрагмент S становится новым скрытым текстом.

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

Постусловие
(fold.MatchingFold() # NIL) & fold.collapsed'
	~fold.collapsed
(fold.MatchingFold() # NIL) & ~fold.collapsed'
	fold.collapsed
fold.MatchingFold() = NIL
	no effect

PROCEDURE (fold: Fold) FlipNested
NEW
Изменяет состояние этой складки и всех таких складок f между fold и fold.MatchingFold(), для которых f.state=fold.state.

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

Постусловие
(fold.MatchingFold() # NIL) & fold.collapsed'
	~fold.collapsed
	For all folds f between fold and fold.MatchingFold(): ~f.collapsed
(fold.MatchingFold() # NIL) & ~fold.collapsed'
	fold.collapsed
	For all folds f between fold and fold.MatchingFold(): f.collapsed
fold.MatchingFold() = NIL
	no effect

PROCEDURE (fold: Fold) HiddenText (): TextModels.Model
NEW
Возвращает фрагмент текста, скрытый в данный момент скрыт парой (fold, fold.MatchingFold()). Текст нельзя изменять. Если скрытый текст имеет нулевую длину, возвращается NIL.

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

Постусловие
fold.MatchingFold() # NIL
	[ let p1 := Pos(Flipped(fold)), p2 := Pos(Flipped(fold).MatchingFold() ]
	ABS(p2 - p1) = 1  =>  result = NIL
	ABS(p2 - p1) > 1  =>  result = Stretch(p1, p2)
fold.MatchingFold() = NIL
	result = NIL

PROCEDURE (fold: Fold) MatchingFold (): Fold
NEW
Возвращает вьюшку, парную для fold,  или NIL, если таковой не найдено.

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

Постусловие
~(fold.context IS TextModels.Context)
	result = NIL
fold.context IS TextModels.Context
	(fold.kind = left) & (result.kind = right) & Pos(fold) < Pos(result)
			& (For all folds f with Pos(fold) < Pos(f) < Pos(result):
					(f.MatchingFold() # NIL) & (Pos(fold) < Pos(f.MatchingFold() < Pos(result))
	OR (fold.kind = right) & (result.kind = left) & (Pos(fold) > Pos(result)
			& (For all folds f with Pos(result) < Pos(f) < Pos(fold): 
					(f.Matching # NIL) & (Pos(result) < Pos(f.MatchingFold() < Pos(fold))
	OR result = NIL


TYPE Directory
ABSTRACT
Фабричныйобъект для складочных вьюшек.

PROCEDURE (d: Directory) New (collapsed: BOOLEAN; IN label: Label;
													hiddenText: TextModels.Model): Fold
NEW, ABSTRACT
Создает новую складочную вьюшку в состоянии collapsed, c меткой label, и со скрытым текстом hiddenText. Если hiddenText = NIL, создается правая вьюшка, иначе  левая.

Постусловие
result.leftSide = (hiddenText # NIL)
result.collapsed = collapsed
result.label = label
result.HiddenText() = hiddenText


PROCEDURE CollapseFolds (text: TextModels.Model; nested: BOOLEAN;
													IN label: ARRAY OF CHAR)
Если nested истинно и label="", то все развернутые складки в тексте text будут свернуты. Если ~nested, то свернуты будут только самые внешние складки в иерархиях вложеннных складок. Если label#"", то будут свернуты только складки с меткой label.

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

PROCEDURE ExpandFolds (text: TextModels.Model; nested: BOOLEAN;
												IN label: ARRAY OF CHAR)
Если nested истинно и label="", то все свернутые складки в тексте text будут развернуты. Если ~nested, то развернуты будут только самые внешние складки в иерархиях вложеннных складок. Если label#"", то будут развернуты только складки с меткой label.

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

PROCEDURE Collapse
Охрана: TextCmds.FocusGuard
Сворачивает все вьюшки складок в тексте, находящемся в фокусе.

PROCEDURE Expand
Охрана: TextCmds.FocusGuard
Разворачивает все вьюшки складок в тексте, находящемся в фокусе.

PROCEDURE ZoomOut
Охрана: TextCmds.FocusGuard
Сворачивает все самые внешние развернутые складки в тексте, находящемся в фокусе.

PROCEDURE ZoomIn
Охрана: TextCmds.FocusGuard
Разворачивает все самые внешние свернутые складки в тексте, находящемся в фокусе.

PROCEDURE Overlaps (text: TextModels.Model; beg, end: INTEGER): BOOLEAN
Возвращает TRUE, если фрагмент [beg,end) текста text частично перекрывает пару вьюшек некоторой складки.

Предусловие
text # NIL	20
(beg >= 0) & (end <= text.Length()) & (beg <= end)	21

PROCEDURE Insert (text: TextModels.Model; IN label: Label; beg, end: INTEGER; collapsed: BOOLEAN)
Вставляет в текст text вокруг фрагмент [beg,end) новую пару (f1, f2) вьюшек, образующих складку. Флаг collapsed определяет, будет ли складка создана в свернутом или развернутом состоянии.

Предусловие
text # NIL	20
(beg >= 0) & (end <= text.Length()) & (beg <= end)	21

Постусловие
фрагмент текста [beg,end) не перекрывает частично пару складок
	Pos(f1) = beg
	Pos(f2) = end+1
	f1.MatchingFold() = f2
	f1.collapsed = f2.collapsed
	f1.HiddenText() = NIL
фрагмент текста [beg,end) частично перекрывает пару складок
	ничего не происходит

PROCEDURE CreateGuard (VAR par: Dialog.Par)
Устанавливает par.disabled в TRUE , когда выделенный фрагмент в тексте, находящемся в фокусе, частично перекрывает пару (f, Matching(f)) вьюшек складки. Кроме того, par.disabled устанавливается в TRUE, если текст, находящийся в фокусе, открыт в режимах просмотра или маски, то есть если текст нельзя править.

PROCEDURE Create (state: INTEGER)
Если охрана CreateGuard допускает, то создает новую пару вьюшек складки и вставляет их в текст, находящийся в фокусе, вокруг выделенного фрагмента или вокрут текстового курсора. Вызывает Insert(FocusText,selBeg,selEnd,state). 
При state = 0 создается свернутая складка, при state = 1  развернутая.

Предусловие
state IN {0, 1)

Постусловие
state = 0
	result.collapsed
state = 1
	~result.collapsed

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

Следующие переменные и процедуры используются только диалогом-инспектором для вьюшек типа StdFolds.View:

VAR 
	foldData: RECORD 
		nested, all: BOOLEAN;
		findLabel, newLabel: Label
	END;

PROCEDURE FindFirstFold;
PROCEDURE FindNextFold;
PROCEDURE CollapseLabel;
PROCEDURE ExpandLabel;
PROCEDURE SetLabel;
PROCEDURE SetLabelGuard (VAR p: Dialog.Par);
PROCEDURE FindLabelGuard (VAR par: Dialog.Par);