====== Настройка внешнего вида и поведения UniLines ======
Для **UniLines**-а уже разработаны и предусмотрены различные варианты кастомизации его работы.
В целом, их можно разделить на следующие группы:
* Работа с выборными элементами (представление элементов как чекбоксов);
* Управление выбранными элементами;
* Кастомизация управляющих кнопок
* Текстовые опции.
===== Работа с выборными элементами (представление элементов как чекбоксов)=====
**UniLines** позволяет отобразить элементы в виде галочек. Например, как это сделано в модуле **DiscExt.pas** (внешняя дисконтная схема), для отображения таблицы со скидками на каждую группу слуг.
{{:pasted:20220905-101535.png}}
Включение галочного представления осуществляется за счёт опции **ShowCheckBoxes** (по умолчанию **False**).
Включение этой опции, по сути, для каждой ноды **VST** выставляет свойство **CheckType := ctCheckBox**.
Опция **IsTriStateCheckBoxes** отвечает за возможность отображать "смешанное" состояние чекбокса (когда у дочерних элементов как стоят галочки, так и не стоят):
{{:pasted:20220905-101950.png}}
В коде обработка происходит следующим образом:
procedure TUniLinesFrame.SetShowCheckBoxes(const Value: boolean);
var Node: PVirtualNode;
begin
FShowCheckBoxes := Value; //присвоение опции
Node:=VST.GetFirst; //получаем указатель на первую ноду
while Node<>nil do //в цикле по всем нодам
begin
if FShowCheckBoxes then //для каждой выставляем CheckType либо ctNone (без чекбокса), либо ctCheckBox (два состояния), либо ctTriStateCheckBox (три состояния).
if FIsTriStateCheckBoxes then
VST.CheckType[Node]:=ctTriStateCheckBox
else
VST.CheckType[Node] := ctCheckBox
else
VST.CheckType[Node]:=ctNone;
Node:=VST.GetNext(Node);
end;
end;
//для новых нод тоже анализируется эта опция, чтобы сразу им выставить CheckType.
function TUniLinesFrame.AddData(ANode: PVirtualNode = nil): PLinesData;
var Node: PVirtualNode;
i: integer;
begin
if ANode=nil then
begin
Node:=VST.AddChild(nil);
if FIsMultiline then
Node.States:=Node.States+[vsMultiline];
end
else
Node:=ANode;
if FShowCheckBoxes then
if FIsTriStateCheckBoxes then
VST.CheckType[Node]:=ctTriStateCheckBox
else
VST.CheckType[Node] := ctCheckBox;
//... и т.д.
end;
Опция **ShowCustomCheckBoxes** позволяет подгрузить специальные иконки для чекбоксов. У нас они берутся из **ImgDMForm.ilChecksTree32**:
begin
FShowCustomCheckBoxes := Value;
if FShowCustomCheckBoxes then
begin
vst.CustomCheckImages:=ImgDMForm.ilChecksTree32;
vst.CheckImageKind:=ckCustom;
vst.DefaultNodeHeight:=Max(vst.DefaultNodeHeight, ScaleMeasure(40));
end
else
begin
vst.CheckImageKind:=ckXP;
vst.CustomCheckImages:=nil;
end;
end;
Для работы с чекбоксами в рамках **UniLines** реализованы на текущий момент следующие функции/процедуры:
* function GetCheckedValues(const ValueName: string; GetSQLStr: boolean = True; Delimiter: string = ','): string; - через указанный разделитель собирает все значения ValueName, у которых отмечены галочки;
* procedure SetCheckedValues(ValueName, Checked: string; Delimiter: string = ','); - всем значениям, которые соответствуют указанным через Delimiter ValueName, выставить значение Checked;
* procedure CheckAll; - проставить галочки у всех нод;
* procedure UnCheckAll; - убрать галочки у всех нод;
* procedure Inversion; - инвертировать галочки у всех нод.
Изменение галочек осуществляется через свойство ноды **CheckState**, например:
procedure TUniLinesFrame.CheckAll;
var Node: PVirtualNode;
begin
if not FShowCheckBoxes then
Exit;
Node:=VST.GetFirst;
while Node<>nil do
begin
if Node.CheckState<>csCheckedNormal then
Node.CheckState:=csCheckedNormal;
Node:=VST.GetNext(Node);
end;
end;
===== Управление выбранными элементами =====
Выбранной нодой, если по-простому, можно считать ту ноду, по которой случился клик. Через **ctrl** выбранных нод может оказаться несколько:
{{:pasted:20220905-105127.png}}
Основное управление выбранными нодами осуществляется через **VST**, например
VST.Selected[LastNode] := True;
У нас реализованы функции и процедуры:
* function SelectedCount: int64; - возвращает количество выбранных нод;
* function TUniLinesFrame.GetIDsFromSel: string; - получает список значений PrimaryValue выбранных нод через запятую;
* procedure TUniLinesFrame.SelectAll; - выбрать все ноды;
* procedure TUniLinesFrame.SelectLastNode; - выбрать последнюю ноду;
* procedure LastLine(FirstVisible: boolean = True); - выбрать последнюю строку;
* procedure PrevLine(PrevVisible: boolean = True); - выбрать предыдущую строку.
===== Кастомизация управляющих кнопок =====
Для **UniLines**-а предусмотрено несколько методов, позволяющих добавить кастомные кнопки и элементы меню, чтобы можно было сделать уникальное поведение этого фрейма на разных формах, без необходимости изменения в дизайн-тайме.
==== Добавление элементов выпадающего меню в заголовок ====
Имеется в виду меню, возникающее по правому клику на заголовке:
{{:pasted:20220905-123441.png}}
Реализовано с помощью функции
function AddHeaderMenuItem(const ACaption: string; AAutoCheck, AChecked: boolean;
AOnClick: TNotifyEvent; InMenu: TMenuItem; DoHookPopup: boolean = True): TMenuItem;
* ACaption - Название меню;
* AAutoCheck - позволяет автоматически менять свойство Checked при клике;
* AChecked - позволяет работать с меню, как с чекбоксом;
* AOnClick - событие, которое должно сработать при нажатии на кнопку;
* InMenu - ссылка на объект меню, внутри которого должен создаться новый объект;
* DoHookPopup - позволяет отрисовывать меню в скине.
Пример:
it:=UDL.ULF.AddHeaderMenuItem('Показывать только с остатками', True, False,
OnShowOnlyRestClick, nil);
procedure TTovarsModalForm.OnShowOnlyRestClick(Sender: TObject);
var st: TSetting;
begin
//st := DMForm.SettingList.GetSetting(dkObject,MetaObject_Tag,'SHOW_ONLY_AT_CUR_SCLAD',dtBoolean);
st := DMForm.SettingList.GetSetting(dkObject,MetaObject_Tag,'SHOW_ONLY_REST',dtBoolean);
if st<>nil then
begin
if Sender<>nil then
begin
st.AsBoolean := TMenuItem(Sender).Checked;
st.Save(RdTr, UpTr);
end;
ShowOnlyRest := st.AsBoolean;
end;
RefreshAll;
end;
==== Добавление меню в выпадающий список дерева ====
Имеется в виду окно, возникающее при правом клике на элементе **UniLines**
{{:pasted:20220905-130209.png}}
Реализация выполнена с помощью
function AddPopupMenuItem(const ACaption: string; AOnClick: TNotifyEvent; AImageIndex: integer; AVisible: boolean = True;
DoHookPopup: boolean = True): TMenuItem;
* **ACaption** - Название пункта меню;
* **AOnClick** - событие при клике;
* **AImageIndex** - номер иконки (берётся из **ImgDMForm.ilAll**);
* **AVisible** - видимость пункта меню;
* **DoHookPopup** - позволяет отрисовывать меню в скине.
Из интересного тут появляется возможность рулить видимостью пункта меню.
Пример:
ULF.AddPopupMenuItem('Переотправить сообщение', ResendSMS, -1);
//процедура срабатывает при получении состояний дерева, находит нужный элемент меню и меняет его видимостью
procedure TSMSLogForm.ULFVSTStateChange(Sender: TBaseVirtualTree; Enter,
Leave: TVirtualTreeStates);
var it: TMenuItem;
i: integer;
begin
if ULF.Value['ID'] <> Null then
begin
for i := ULF.VST.PopupMenu.Items.Count - 1 downto 0 do
begin
it := TMenuItem(ULF.VST.PopupMenu.Items[i]);
if it.Caption = Translat('Переотправить сообщение') then
begin
it.Visible := ((ULF.Value['oper_status'] = 'СМС заблокировано химчисткой') or
(ULF.Value['oper_status'] = 'Не доставлено'));
break;
end;
end;
end;
end;
==== Добавление кнопки в тулбар ====
Имеется в виду вот эта область:
{{:pasted:20220905-131422.png}}
Реализовано с помощью
function AddToolbarButton(const ACaption: string; AAfterPosition: integer; AImageIndex: integer; AOnClick: TNotifyEvent;
AIsCheck: boolean = False): TsSpeedButton;
* **ACaption** - название кнопки;
* **AAfterPosition** - позиция кнопки (есть значения tpsEndButtons = 0 - после всех основных кнопок и tpsEndCheckbox = 1 - после всех чекбоксов);
* **AImageIndex** - индекс картинки, берётся из ImgDMForm.ilAll;
* **AOnClick** - событие нажатия;
* **AIsCheck** - должна ли кнопка быть чекбоксом.
Пример:
AddToolbarButton('Отправка документов', tpsEndCheckbox, 47, btEmailClick);
procedure TInvoicesForm.btEmailClick(Sender: TObject);
var frm: TInvoicesSendEmailForm;
begin
Application.CreateForm(TInvoicesSendEmailForm, frm);
try
if frm.ShowModal in [mrOK, mrCancel] then
begin
if frm.IsSendMail then
acRefreshExecute(self);
end;
finally
frm.Free;
end;
end;
==== Видимость стандартных пунктов меню ====
Под стандартными подразумеваются кнопки "Создать", "Изменить", "Редактировать", "Печать" и прочие подобные, а также соответствующие им элементы выпадающего меню.
В **UniLines**-е предусмотрено множество вариаций по их отображению, также как и отображение целых панелей. Подробно рассматривать не будем, названия должны понятно отражать их суть.
property ShowPopupMenu: boolean read FShowPopupMenu write SetShowPopupMenu;
property ShowToolbar: boolean read FShowToolbar write SetShowToolbar;
property ShowToolbarAndPopup: boolean read FShowToolbarAndPopup write SetShowToolbarAndPopup;
property ShowToolbarOnlyLoadSave: boolean read FShowToolbarOnlyLoadSave write SetShowToolbarOnlyLoadSave;
property ShowToolbarHorizontalSelectUnselect: boolean read FShowToolbarHorizontalSelectUnselect write SetShowToolbarHorizontalSelectUnselect;
property ShowOnlyAddButtons: Boolean read GetShowAddButton write SetShowAddButton;
property ShowOnlyParentButtons: Boolean read GetShowParentButton write SetShowParentButton;
property ShowOnlyEditButtons: Boolean read GetShowCorrButton write SetShowCorrButton;
property ShowOnlyDelButton: Boolean read GetShowDelButton write SetShowDelButton;
property ShowAddEditButtons: Boolean read GetShowAddCorrButtons write SetShowAddCorrButtons;
property ShowAddDelButtons: Boolean read GetShowAddDelButtons write SetShowAddDelButtons;
property ShowEditButtons: Boolean read GetShowAllEditButtons write SetShowAllEditButtons;
===== Текстовые опции=====
Также, в **UniLines**-е возможно настраивать ячейки с информацией, правила её отображения и возможность изменения.
==== Настройка отображения ====
property IsMultiline: boolean - добавляет всем нодам настройку vsMultiline (Node.States:=Node.States+[vsMultiline]), поддерживающую многострочность текста в соответствии с шириной колонки;
property IsHtml: boolean - при True позволяет обрабатывать html-теги, а также позволяет подключить ряд опций по обработке текста;
property FullText: boolean - при True предотвращает обрезание текста, в противном случае весь невлезший текст будет заменён многоточием (только для IsHtml = True);
property FullTextIsCenter: boolean - при True центрирует текст по высоте (только для IsHtml = True);
property SmallNodeHeight: boolean - нода имеет фиксированную высоту (25 пикселей), иначе 37; её включение блокирует опцию AutoCalcHodeHeight;
property AutoCalcHodeHeight: boolean - автоматический расчёт требуемой высоты ноды (только для IsHtml = True);
property MinNodeHeight: integer - если не равен 0, то выступает в качестве значения высоты ноды при включённой SmallNodeHeight (только для IsHtml = True);
Таким образом, в стандартном **ULF** разрешается только многострочность и ручная регулировка высоты ноды. Но при включении **IsHtml** становится возможным серьёзно управлять отображением текста.
==== Настройка редактирования ====
property AutoEdit: boolean - включает возможность редактирования колонок (при клике на ней можно вписать своё значение). Вызывает процедуру VST.EditNode
При редактировании появляется возможность использовать несколько полезных обработчиков:
procedure VSTEditing(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; var Allowed: Boolean); - перед редактированием колонки Column можно изменить её Allowed, чтобы запретить/разрешить редактирование;
procedure VSTNewText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; NewText: String); - срабатывает, когда в колонке Column появляется NewText, который можно получить для какой-либо обработки. В этой процедуре у ноды можно изменить её текст.
[[https://agbis.getcourse.ru/pl/teach/control/lesson/view?id=254286906|Пройти тест]]
[[https://doc.agb.is/develop/unilines|Назад]]