Перейти к содержанию

Горячие клавиши

Горячие клавиши

Команду плитки также можно вызвать по хоткею. Хоткей добавляется в коллекцию IUIContext.InputBindings и работает, пока активен контекст, т.е. выделена вкладка, связанная с контекстом. Добавить хоткей можно также в любой момент, когда уже есть контекст, но лучше это делать в расширении на открытие вкладки InitializingLocal:

ITile saveCard = context.Workspace.LeftPanel.TryGet("SaveCard"); if (saveCard != null) { saveCard.Context.AddKeyBinding(saveCard, Key.S, ModifierKeys.Control); }

Или так:

public static readonly KeyGesture SaveCardKey = new KeyGesture(Key.S, ModifierKeys.Control, "Ctrl+S");

...

ITile saveCard = context.Workspace.LeftPanel.TryGet("SaveCard"); if (saveCard != null) { saveCard.Context.AddInputBinding(saveCard, SaveCardKey); }

Плитка создаётся в расширениях InitializingGlobal или InitializingLocal, причём для неё можно добавить ToolTip с указанием горячей клавиши.

ITile tile = new Tile("SaveCard" , "Сохранить", ..., toolTip: TileHelper.GetToolTip("Сохраняет карточку", SaveCardKey));

Нужно сделать так, чтобы в состоянии плитки IsEnabled = false хоткей перестал работать. Поэтому управлять состоянием IsEnabled напрямую в расширении открытия панели OpeningLocal не рекомендуется. Вместо этого используется специальное событие Evaluating.

Событие Evaluating

Смысл Evaluating – вычислить текущие значения IsEnabled, IsCollapsed и IsHidden, и опционально их применить. Дизейбл и скрытие имеют более высокий приоритет, чем обратные значения, поэтому если хотя бы один обработчик установит SetIsEnabled(false) или SetIsEnabledWithCollapsing(false), то плитка будет дизейблена. Если состояние IsEnabled плитки определяется исключительно через Evaluating и не задаётся явно через свойство, то в любой момент (без расширений на открытие панели) можно сказать, будет ли плитка дизейблена, и, соответственно, будет ли отключён хоткей.

Событие рекомендуется добавлять в расширениях InitializingGlobal или InitializingLocal.

tile1.Evaluating += (s, e) => e.SetIsEnabledWithCollapsing(this.session.User.IsAdministrator); // скрываем и дизейблим плитку для не-админов tile2.Evaluating += (s, e) => e.SetIsEnabled(this.session.User.IsAdministrator); // дизейблим плитку для не-админов, но не скрываем её в панели tile3.Evaluating += TileHelper.DisableTileWithCollapsingHandler; // навсегда скрываем и дизейблим плитку (для текущей вкладки) tile3.Evaluating += TileHelper.DisableTileHandler; // навсегда дизейблим плитку без скрытия (для текущей вкладки)

Также это можно делать в конструкторе плитки, а позднее, в другом расширении, можно добавить ещё несколько обработчиков.

ITile saveCard = new Tile("SaveCard", "Сохранить", ..., evaluating: (s, e) => ...);

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

TileEvaluationResult result = context.Panel.Evaluate(); result.Apply();

Можно вычислить актуальные значения для конкретной плитки tile, не изменяя сами свойства:

ITile tile = ... ; TileEvaluationResult result = tile.EvaluateSelf(); bool shouldBeEnabled = result.EventArgs.GetIsEnabledEffective(tile);

Пример расширения на плитку “создание резолюции”

using System.Collections.Generic; using System.Windows.Input; using Tessa.Cards; using Tessa.UI; using Tessa.UI.Cards; using Tessa.UI.Tiles; using Tessa.UI.Tiles.Extensions;

namespace Tessa.Extensions.Client.Tiles { public sealed class SendTaskTileExtension : TileExtension { private static void EnableOnUpdateAndAllowTasks(object sender, TileEvaluationEventArgs e) { // плитка будет доступна, если карточка хотя бы раз была сохранена (Update) // и для типа карточки разрешены задания (AllowTasks)

ICardEditorModel editor = e.CurrentTile.Context.CardEditor; ICardModel model;

e.SetIsEnabledWithCollapsing( e.CurrentTile, editor != null && (model = editor.CardModel) != null && model.CardType.Flags.Has(CardTypeFlags.AllowTasks) && model.Card.StoreMode == CardStoreMode.Update); }

private static async void SendTaskAction(object parameter) { // действие по созданию резолюции, выполняется асинхронно

IUIContext context = UIContext.Current;

ICardEditorModel editor; ICardModel model; if ((editor = context.CardEditor) != null && !editor.OperationInProgress && (model = editor.CardModel) != null) { if (model.HasChanges()) { await editor.SaveCardAsync(context); }

await editor.OpenCardAsync( model.Card.ID, model.CardType.ID, model.CardType.Name, context, new Dictionary<string, object> {{ "need_starting", true }}); } }

// горячая клавиша на создание резолюции private static readonly KeyGesture sendTaskKey = new KeyGesture(Key.R, ModifierKeys.Control | ModifierKeys.Shift, "Ctrl+Shift+R");

public override void InitializingGlobal(ITileGlobalExtensionContext context) { // плитка добавляется с обработчиком Evaluating, указанном в конструкторе

// в расширениях InitializingLocal для специальных видов вкладок, таких как просмотр удалённой карточки, // плитку можно будет принудительно скрыть, добавив обработчик tile.Evaluating += TileHelper.DisableTileWithCollapsingHandler

context.Workspace.LeftPanel.Tiles.Add( new Tile( "SendTask", "Создать резолюцию", context.Icons.Get("Thin91"), context.Workspace.LeftPanel, new DelegateCommand(SendTaskAction), TileGroups.Cards, order: 100, toolTip: TileHelper.GetToolTip("Создаёт задание с параметрами резолюции", sendTaskKey.DisplayString), evaluating: EnableOnUpdateAndAllowTasks)); }

public override void InitializingLocal(ITileLocalExtensionContext context) { // добавляем горячую клавишу, которая будет работать только тогда, когда плитка не дизейблена

ITile sendTask = context.Workspace.LeftPanel.Tiles["SendTask"]; sendTask.Context.AddInputBinding(sendTask, sendTaskKey); } } }

Регистрация расширения:

extensionContainer .RegisterExtension<ITileGlobalExtension, SendTaskTileExtension>(x => x .WithOrder(ExtensionStage.AfterPlatform) .WithSingleton<SendTaskTileExtension>());

Скрытие системных плиток

Все плитки, которые автоматически создаются платформой, могут быть скрыты пользовательскими расширениями по определённым условиям (или скрыты всегда), причём они могут быть найдены по именам в классе Tessa.UI.Tiles.TileNames. Для них точно так же надо написать расширение, запрещающее их отображать, добавив соответствующую подписку на событие Evaluating на уровне расширения CardUIExtension/InitializingLocal.

Приведём пример расширения, скрывающего плитку “Договор”, создающую одноимённый тип карточки. Однако, отметим, что если речь про конкретно типы карточек, то в системе для них имеются готовые настройки (в TessaAdmin при редактировании типа). Флажок Hidden скрывает тип карточки ото всех пользователей, при этом он по-прежнему может быть создан, но только системными средствами. Флажок Administrative запрещает создание и работу с типом карточки любым пользователям, кроме администраторов, при этом плитка создания типа тоже скрывается. Если нужно учесть некоторое более сложное условие (например, какая именно вкладка открыта в настоящий момент), то подходит решение, предложенное в примере ниже.

public sealed class HideContractTileExtension : TileExtension { public override void InitializingLocal(ITileLocalExtensionContext context) { ITilePanel panel = context.Workspace.RightPanel;

// при необходимости здесь можно проверить текущий контекст IUIContext context = panel.Context;

// получаем плитку "Создать карточку" ITile createCard = panel.Tiles.TryGet(TileNames.CreateCard); if (createCard != null) { // на этом уровне плитки можно получить по имени группы Group, указанной в TessaAdmin для типа карточки

// получаем плитку "Документы" ITile documents = createCard.Tiles.TryGet(TileNames.DocumentTypes); if (documents != null) { // на этом уровне плитки можно получить по имени типа карточки (поле Name для типа карточки в TessaAdmin)

// получаем плитку "Договор" ITile contract = documents.Tiles.TryGet("Contract"); if (contract != null) { // скрываем этот тип и выполняем Disable // т.е. даже если с плиткой ассоциирован хоткей, он прекратит работать contract.Evaluating += TileHelper.DisableTileWithCollapsingHandler; } } } } }

Back to top