Редактор иерархических структур Назад В начало Вперед

Иерархические структуры (деревья) отображаются в специальной панели (treeBrowse) аналогично дереву каталогов в Windows Explorer.

<дерево> = tree [<номер-колонки>] <имя> [<контексты>] ;
  [<координаты>] [<атрибуты-дерева>] [<лист>] [<маркер>]
  { <колонка-табличного-редактора> }
  end;

<номер-колонки> - номер колонки табличного редактора, в которой будет отображаться структура дерева. Нумерация колонок начинается с 0. Если <номер-колонки> не указан, структура дерева отображается в 0-й колонке.

<имя> - идентификатор области ввода (данный идентификатор может передаваться в функцию SetFormat как параметр).

<контексты> - контексты справочника, линии статуса и строка подсказки. Синтаксическая конструкция служит для связывания с интерфейсом отдельных тем файла подсказки, статус-строки и строки подсказки. См. "Контексты. ".

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

<атрибуты-дерева> - атрибуты дерева (см. пример 3):

<атрибуты-дерева> = wideOffset | linesAtRoot | noBitmap |  <стиль-линии>

wideOffset - добавляет иконку открытого /закрытого узла с одинарным кликом.

linesAtRoot - все корневые узлы дерева связываются линией.

noBitmap - не рисовать иконки.

<стиль-линии> - стили линий в дереве:

<стиль-линии> = noLines | solidLines | dottedLines

noLines - не рисовать линии.

solidLines - сплошная линия.

dottedLines - пунктир.

<лист> - идентификатор корневой таблицы для данной области ввода. Лист это имя физической таблицы, которая является корневой для данного видимого элемента. См. "Лист. ".

<маркер> - автоматизированная пометка записей (см. "Пометка записей. ").

Описание пометки в однотабличном дереве ничем не отличается от описания пометки в браузере.

В многотабличном дереве описываются маркеры для каждого узла логической таблицы, который участвует в построении иерархии дерева: через смену корневой таблицы, через вычисляемое поле или другим образом.

Узел задается посредством конструкции <поле-маркера>, содержащей табличное поле. Для многотабличного дерева <поле-маркера> необходимо всегда задавать явно.

Компилятор контролирует единственность указания узла автоматической пометки внутри дерева.

Конструкции переопределения иконки пометки и атрибуты noColumn, noColour, noSave должны быть описаны в первом описании маркера. Будучи описанными в следующих маркерах, они считаются за ошибку.

Пары переключаемых реляционных отношений tbRM<имя>1 и tbRM<имя>2 генерируются для каждого описания автоматической пометки.

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

За добавление к заголовку окна отвечает первый описаный маркер. Другие маркеры при формировании заголовка окна не учитываются.

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

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

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

Операции пометить всё и инвертировать пометку выполняются по схожему алгоритму с корневого уровня дерева.

Операция снять пометку снимает пометку во всех описанных маркерах.

Методы Mark,Unmark,MarkUnmark будут работать только если узел, связанный с объектом, в момент вызова является текущим в дереве.

Методы SelectAll,UnselectAll,InvertSel описанных объектов работают идентично, так что для выполнения операции неважно, метод какого объекта вызывать. При собственной реализации объекта пометки это надо учитывать (т.е. собственная реализация должна это поддерживать).

Загрузка и сохранение объектов происходит независимо, и ею можно раздельно управлять.

<колонка-табличного-редактора> - описание табличного редактора.

Колонка табличного редактора служит для просмотра значений одного из полей таблицы в нескольких последовательных записях.

Начиная с Атлантис 5.3.10 колонка иерархического редактора может содержать иконку. Для этого полю надо назначить атрибут image. Все остальные атрибуты для поля устанавливаются автоматически.

Колонка с иконкой не должна быть полем иерархии дерева. Например, если номер колонки иерархии не указан явно, то колонка с иконкой не может быть самой первой.

Поле с иконкой должно возвращать значение типа string - имя иконки в ресурсе. Иконка должна быть 16 Х 16. Если значение пробел или несуществующая иконка, то ничего не рисуется (закрашвается фоном).

Т.к. полю с иконкой автоматически присваивается атрибут skip, указывать контексты нет смысла. Колонка имеет фиксированную ширину в одно знакоместо, поэтому указывать в заголовоке более 1 символа также не имеет смысла.

См. также пример "Иерархический редактор с иконкой" в конце раздела.

<колонка-табличного-редактора> = <поле>
  [<заголовок-поля>] [<контексты>] [: <атрибуты-поля>];

<поле> - любое выражение над полями таблиц, переменными и константами.

<заголовок-поля> - заголовок соответствующей колонки таблицы. Заголовок колонки табличного редактора может состоять из нескольких строк, которые указываются через запятую.

<заголовок-поля> = { <строка> [, <строка>] }

<контексты> - см. "Контексты. ".

<атрибуты-поля> - см. "Атрибуты поля. ".

Текущей таблицей в данной панели должна быть таблица, содержащая связи между узлами дерева.

Ограничения на таблицу связей: при помощи текущих ограничений должны быть видны записи, отображающие вхождения в текущей узел. Имеется ввиду вхождение как терминальных, так и нетерминальных узлов. При переходах по дереву вверх /вниз для смены текущего узла возникает необходимость в смене ограничений. Для этого вводятся события cmTreeTop, cmTreeDown, cmTreeUp. cmTreeOpenNode (смотри пример 2).

Различия между терминальным и нетерминальным узлом - существует или нет у конечного пользователя возможность открыть /закрыть узел (отображается или нет: "+" /"-") и возможностью добавлять узлы (записи) в данный узел. Любой нетерминальный узел может содержать как терминальные так и не терминальные узлы (если этого не запретит прикладной программист). Терминальный или нетерминальный узел определяется прикладным программистом и указывается при обработке события cmTreeNodeType.

Возможен вход в дерево начиная с любого узла. Дерево отображается ниже этого узла, выход выше него запрещен (при данном отображении).

Дерево не может содержать циклов.

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

Нетерминальные узлы при отображении могут иметь два состояния: закрытый (по умолчанию) и открытый. Состояния узлов ведутся системой автоматически и сохраняются от сеанса к сеансу в конфигурационном файле.

Если дерево строится по нескольким таблицам, то при обработке команд cmTreeTop, cmTreeUp и cmTreeDown необходимо изменять текущую корневую таблицу функциями TreeSetNodeTable и TreeGetNodeTable.

Т.к. навигация по дереву связана с изменением текущего ограничения, для проведения ее из прикладного кода созданы функции TreeGetFirst, TreeGetLast, TreeGetPrev и TreeGetNext. Они осуществляют навигацию по дереву с переключением ограничений (посылаются соответствующие команды), и учетом открытости узлов. Для навигации без учета открытости узлов можно использовать функции TreeGetFirstEx, TreeGetLastEx, TreeGetPrevEx и TreeGetNextEx.

Для прямого перехода на запись с заданным NRec'ом можно применять функции TreeJumpToRecord для перехода на запись в однотабличном дереве, и TreeJumpToRecordEx для перехода на запись в многотабличном дереве.

Для сохранения /восстановления текущей позиции служат функции TreePushPos, TreePopPos и TreeDropPos соответственно.

Дополнительные функции:

Примеры

Пример 1.

tree trCat (, hcStaffViewCatalogs, sci147EnEscTree)
  show at (,4,,);
  table Catalogs;
fields
  Catalogs.name  'Наименование' ('Наименование'): [35], protect;
  Catalogs.code  'Код' ('Код'): [20], protect;
end;

Пример 2.

Структура таблицы связей А:

create table A
(
  cOwner : comp "Ссылка наверх",
  NRec   : comp "Код текущей записи"
)
with index
(
  bySelf = NRec (Surrogate), byOwner = cOwner
);

Логическая таблица:

create view

var
  curOwner : comp; 
  top	: comp;

as select
  A.cOwner, A.NRec

from
  A

where
((
  curOwner == A.cOwner
))
;

В данном примере curOwner является текущим корнем дерева (при обходе), и в начале обхода он равен top - точке входа в дерево.

Обработка событий:

cmTreeTop:
{
  curOwner := top; // текущий корень - вершина
}

cmTreeDown:
{
  curOwner := A.NRec; // текущий корень - текущая запись
}

cmTreeUp:
{
  curOwner := A.cOwner; // текущий корень - ссылка вверх
}

cmTreeNodeType:
{
  TreeSetNodeType(treebrowse, ntfText);
}

Пример 3. Атрибуты дерева.

tree tr_tblMyTree ('',,sci178EscExTree_InsLevel);
  show at (,,,);
  wideOffset, linesAtRoot, noBitmap, DoubleLines;
  table tblMyTree;
fields
  tblMyTree.Name   'Наименование' : [35], noprotect;
  tblMyTree.TipPos 'Тип' : [5], noprotect;
end;

Пример 4. Автоматизированная пометка в многотабличном дереве.

Дерево двухуровневое, верхний уровень - подразделения, нижний - сотрудники по подразделениям.

interface TreeTest 'Тест Дерева по 2м таблицам';
  show at (6,6,65,20);

//---------------------------------------------------------

create view

as select
  *

from
  Persons, Deps

where

((
  Deps.NRec == Persons.Department
))
;

//---------------------------------------------------------

function GetFldName: string; forward;

//---------------------------------------------------------

tree trSelPers (,,scAtlTreeMark);
  table Deps;
  recmarker {Persons.NRec};
  recmarker {Deps.NRec};

fields
  [Name1] GetFldName 'Имя': [40];
end;

//---------------------------------------------------------

function GetFldName: string;
{
  case TreeGetNodeTable(trSelPers) of

	#Deps:
	GetFldName := Deps.Name;

	#Persons:
	GetFldName := Persons.FIO;

  else
	GetFldName := '';
  end;
}

//---------------------------------------------------------

handleEvent

cmInit:
{
  TreeGetFirst(trSelPers);
  TreeCloseAllOpenedNode(trSelPers);
}

cmTreeTop:
{
  TreeSetNodeTable(trSelPers,#Deps);
}

cmTreeDown:
{
   TreeSetNodeTable(trSelPers, #Persons);
}

cmTreeUp:
{
  TreeSetNodeTable(trSelPers, #Deps);
}

cmTreeNeedOwner:
{
  case TreeGetNodeTable(trSelPers) of

	#Deps:
	TreeJumpToRecord(trSelPers, 0);

	#Persons:
	TreeJumpToRecordEx(trSelPers, #Deps, Persons.Department);
  end;
}

cmTreeNodeType:
{
 case TreeGetNodeTable(trSelPers) of

   #Deps:
	 TreeSetNodeType(trSelPers, ntfCurrent,'bmpGroup');

   #Persons:
	 TreeSetNodeType(trSelPers, ntfText,'bmpUser');
 end;
}

cmUpdateRecord:
{
 case TreeGetNodeTable(trSelPers) of

   #Deps:
	 update current Deps;

   #Persons:
	 update current Persons;
 end;
}

cmDeleteRecord:
{
 case TreeGetNodeTable(trSelPers) of

   #Deps:
	 delete current Deps;

   #Persons:
	 delete current Persons;
 end;
}

cmInsertRecord:
{
  case TreeGetNodeTable(trSelPers) of

	#Deps:
	insert current Deps;

	#Persons:
	insert current Persons;
  end;
}
end;

end.

Пример 5. Иерархический редактор с иконкой

userBmp  bitMap "user.bmp
groupBmp bitMap "group_2.bmp
...................

//---------------------------------------------
function Img: string;
{
  if ((x$files.xf$code mod 2 ) = 0)
	Img := 'userBmp'
  else
	Img := 'groupBmp';
}

//---------------------------------------------
tree 1 trTest1 'Tree Test';
table x$Files;
fields
  Img 'И' : Image;
  x$files.xf$name 'Test1' : [15] ,Protect;
  x$files.xf$code 'x$files.xf$code' : [6], protect, skip;
end;  // tree

Смотрите также

Функции работы с иерархической табличной панелью.

Версия

Возможность вставить иконку в табличный редактор доступна начиная с Атлантис 5.3.10.

Конструкция <маркер> доступна начиная с Атлантис 5.1.38.