Для того, чтобы пользователь "увидел" дерево и смог управлять им необходимо решить следующие задачи:
1. Определить структуру хранения дерева в оперативной памяти.
2. Обеспечить механизм программного формирования дерева.
3. Реализовать алгоритм визуализации дерева.
4. Предоставить пользователю возмодность управлять деревом.
Начнем по порядку.
Структура хранения дерева в оперативной памяти и его программное формирование.
Вообще, дерево это структурированная совокупность узлов, взаимосвязанных друг с другом. Узел может быть корневым (не имеет родителя), промежуточным (подчинен другому узлу и является родителем для других), листовым (не имеет подчиненных узлов). Таким образом, структура дерева носит иерархический характер.
Задачу хранения дерева предлагается решить с помощью хорошо известного объекта платформы СписокЗначений.
Узел - это элемент списка значений, обладающий следующими атрибутами:
1. Идентификатор. Предназначен для именованного доступа к данным узла.
2. Представление. Видимое пользователю строковое представление узла.
3. Значение. Любое значение, хранимое в узле.
4. Знак. Определяет развернута или свернута ветка, определяемая данным узлом.
5. СписокУзлов. Список подчиненных узлов.
6. Родитель. Родительский узел.
Таким образом можно определить следующую функцию позволяющую максимально упростить процесс программного формирования дерева.
Функция ДобавитьУзел(Родитель,Идентификатор,Представление,Значение,Знак = "") Узел = СоздатьОбъект("СписокЗначений"); Узел.ДобавитьЗначение(Родитель,"Родитель"); Узел.ДобавитьЗначение(Идентификатор,"Идентификатор"); Узел.ДобавитьЗначение(Представление,"Представление"); Узел.ДобавитьЗначение(Значение,"Значение"); Узел.ДобавитьЗначение(Знак,"Знак"); Узел.ДобавитьЗначение(СоздатьОбъект("СписокЗначений"),"СписокУзлов"); Если ПустоеЗначение(Родитель) = 0 Тогда СписокУзловРодителя = Родитель.Получить("СписокУзлов"); СписокУзловРодителя.ДобавитьЗначение(Узел,Идентификатор); КонецЕсли; Возврат Узел; КонецФункции
Функция возвращает вновь созданный узел.
Визуализация дерева.
Наибольшими изобразительными способностями среди доступных на платформе 1С:Предприятие 7.7 обладает объект Таблица. Вот с помощью данного объекта и будем визуализировать Наше дерево.
Приведем текст процедур визуализации дерева.
//Рекурсивная процедура визуализации дерева Процедура ВывестиДерево(Знач Дерево, Уровень) Если Уровень > 0 Тогда Таблица.ВывестиСекцию("Пустая|Знак"); Для СчУровней = 1 По Уровень - 1 Цикл Таблица.ПрисоединитьСекцию("Пустая|Знак"); КонецЦикла; КонецЕсли; СписокУзлов = Дерево.Получить("СписокУзлов"); КолУзлов = СписокУзлов.РазмерСписка(); ID_Узла = ID_Узла + 1; СписокID.ДобавитьЗначение(Дерево,Строка(ID_Узла)); ПредставлениеУзла = Дерево.Получить("Представление"); Знак = Дерево.Получить("Знак"); Если ПустоеЗначение(Знак) = 0 Тогда Если Уровень = 0 Тогда Таблица.ВывестиСекцию("Элемент|Знак"); Иначе Таблица.ПрисоединитьСекцию("Элемент|Знак"); КонецЕсли; Иначе Таблица.ПрисоединитьСекцию("Пустая|Знак"); КонецЕсли; Таблица.ПрисоединитьСекцию("Элемент|Представление"); Если Знак = "-" Тогда Уровень = Уровень + 1; Для Сч = 1 По КолУзлов Цикл Дерево = СписокУзлов.ПолучитьЗначение(Сч); ВывестиДерево(Дерево,Уровень); КонецЦикла; Уровень = Уровень - 1; КонецЕсли; КонецПроцедуры Процедура СформироватьТаблицу(Номер) Таблица.Очистить(); СписокID.УдалитьВсе(); ID_Узла = 0; ВывестиДерево(Дерево,0); Таблица.Показать(); КонецПроцедуры
Стоит особо отметить переменные СписокID и ID_Узла. Эти переменные должны быть глобальными по отношению к модулю обработки.
СписокID - список уникальных сквозных номеров узлов для данного состояния дерева, то есть для данной комбинации свернутых и развернутых узлов. Список номеров очищается и заполняется каждый раз при вызуализации дерева.
ID_Узла используется в качестве расшифровки ячейки, содержащей представление данного узла. Данный прием был избран потому, что использовать в качестве расшифровки непосредственно ссылку на узел невозможно - это приводит к ошибке.
ID_Узла используется для доступа к данным узла в процедуре управления деревом.
Управление деревом.
Процедура ПолучитьКомпонентыАдресаЯчейки(Адрес, НомерСтроки, НомерКолонки) НомерСтроки = Число(Сред(Адрес, Найти(Адрес, "R") + 1)); НомерКолонки = Число(Сред(Адрес, Найти(Адрес, "C") + 1)); КонецПроцедуры Процедура ОбработкаЯчейкиТаблицы(Значение,ФлагСтандОбраб,Таблица,Адрес) НомерСтроки = 0; НомерКолонки = 0; ПолучитьКомпонентыАдресаЯчейки(Адрес, НомерСтроки, НомерКолонки); Если (Значение = "+") ИЛИ (Значение = "-") Тогда ID = Строка(Таблица.Область(НомерСтроки,НомерКолонки + 2).Расшифровка()); Узел = СписокID.Получить(ID); НовыйЗнак = ?(Значение = "+", "-","+"); Узел.Установить("Знак",НовыйЗнак); СформироватьТаблицу(Дерево); КонецЕсли; КонецПроцедуры
Следует отметить, что переменная Дерево является глобальной в контексте данной обработки и представляет собой список значений, являющийся корневым узлом дерева.
В качестве примера можно посмотреть мою разработку
//infostart.ru/profile/1999/projects/442
Пользуйтесь...