From 9b0011c354ae5865c4d3b1b1b2d20b85bb84ad77 Mon Sep 17 00:00:00 2001 From: Marcel Kloubert Date: Mon, 27 Nov 2017 06:03:35 +0100 Subject: [PATCH] switch buttons --- package.json | 43 ++++++ src/deploy.ts | 1 + src/i18.ts | 4 + src/lang/de.ts | 4 + src/lang/en.ts | 4 + src/plugins/switch.ts | 34 +++++ src/switch.ts | 316 +++++++++++++++++++++++++++++++----------- 7 files changed, 328 insertions(+), 78 deletions(-) diff --git a/package.json b/package.json index 80edc35..c5bbfbb 100644 --- a/package.json +++ b/package.json @@ -30560,6 +30560,49 @@ "type": "string", "description": "Switches between targets." }, + "button": { + "description": "Settings for a button for that switch.", + "oneOf": [ + { + "type": "boolean", + "description": "Display a button for that switch or not.", + "default": false + }, + { + "type": "object", + "description": "The settings for the button.", + "properties": { + "color": { + "type": "string", + "description": "The custom (text) color for the button.", + "default": "#ffffff" + }, + "enabled": { + "type": "boolean", + "description": "Enable button or not.", + "default": true + }, + "isRight": { + "type": "boolean", + "description": "Set button on the right side or not.", + "default": false + }, + "priority": { + "type": "number", + "description": "The custom priority." + }, + "text": { + "type": "string", + "description": "The custom text." + }, + "tooltip": { + "type": "string", + "description": "The custom tooltip." + } + } + } + ] + }, "options": { "description": "One or more options for the switch.", "oneOf": [ diff --git a/src/deploy.ts b/src/deploy.ts index 929099b..572fb71 100644 --- a/src/deploy.ts +++ b/src/deploy.ts @@ -4184,6 +4184,7 @@ export class Deployer extends Events.EventEmitter implements vscode.Disposable { .apply(ME, []); } + deploy_switch.reloadButtons.apply(ME, []); deploy_switch.printSwitchStates.apply(ME, []); } finally { diff --git a/src/i18.ts b/src/i18.ts index de046ff..8ab6904 100644 --- a/src/i18.ts +++ b/src/i18.ts @@ -297,6 +297,10 @@ export interface Translation { unknownEngine?: string; }, switch?: { + button?: { + text?: string; + tooltip?: string; + }, defaultName?: string; defaultOptionName?: string; description?: string; diff --git a/src/lang/de.ts b/src/lang/de.ts index 4da3f8b..cc32fc2 100644 --- a/src/lang/de.ts +++ b/src/lang/de.ts @@ -288,6 +288,10 @@ export const translation: Translation = { unknownEngine: 'Unbekannter Typ {0:trim,surround}!', }, switch: { + button: { + text: 'Schalter {0:trim,surround}', + tooltip: "Aktuelle Option: {0:trim}\n\nHier klicken, um die aktuelle Option zu wechseln...", + }, defaultName: 'Schalter #{0:trim}', defaultOptionName: 'Schalter-Option #{0:trim}', description: 'Schaltet zwischen anderen existierenden Zielen um', diff --git a/src/lang/en.ts b/src/lang/en.ts index a55a32c..fa6ef1e 100644 --- a/src/lang/en.ts +++ b/src/lang/en.ts @@ -290,6 +290,10 @@ export const translation: Translation = { unknownEngine: 'Unknown engine {0:trim,surround}!', }, switch: { + button: { + text: 'Switch {0:trim,surround}', + tooltip: "Current option: {0:trim}\n\nClick here to change the current option...", + }, defaultName: 'Switch #{0:trim}', defaultOptionName: 'Switch option #{0:trim}', description: 'Switches between existing targets', diff --git a/src/plugins/switch.ts b/src/plugins/switch.ts index ac16813..76fe738 100644 --- a/src/plugins/switch.ts +++ b/src/plugins/switch.ts @@ -34,10 +34,44 @@ import * as vscode from 'vscode'; import * as Workflows from 'node-workflows'; +/** + * A button for a switch target. + */ +export interface DeploySwitchButton { + /** + * The custom (text) color for the button. + */ + color?: string; + /** + * Enable button or not. + */ + enabled?: boolean; + /** + * Put button on the right side or not. + */ + isRight?: boolean; + /** + * The priority. + */ + priority?: number; + /** + * The custom text. + */ + text?: string; + /** + * The custom tooltip. + */ + tooltip?: string; +} + /** * A switch target. */ export interface DeployTargetSwitch extends deploy_contracts.DeployTarget { + /** + * A button for the switch. + */ + button?: DeploySwitchButton | boolean; /** * One or more options for the switch. */ diff --git a/src/switch.ts b/src/switch.ts index b31d056..dc63c43 100644 --- a/src/switch.ts +++ b/src/switch.ts @@ -26,6 +26,7 @@ import * as deploy_contracts from './contracts'; import * as deploy_helpers from './helpers'; import * as deploy_plugins_switch from './plugins/switch'; +import * as deploy_values from './values'; import * as Enumerable from 'node-enumerable'; import * as i18 from './i18'; import * as vs_deploy from './deploy'; @@ -34,6 +35,14 @@ import * as vscode from 'vscode'; type SavedStates = { [switchName: string]: string }; +interface Button { + button: vscode.StatusBarItem; + command: vscode.Disposable; + index: number; + settings: deploy_plugins_switch.DeploySwitchButton; + switch: deploy_plugins_switch.DeployTargetSwitch; +} + /** * Stores the new option data for a target. */ @@ -54,8 +63,10 @@ export interface NewSwitchOptionState { export type SelectedSwitchOptions = { [name: string]: deploy_plugins_switch.DeployTargetSwitchOption }; +const BUTTONS: Button[] = []; const KEY_SWITCH_STATES = 'vsdSwitchStates'; +let nextButtonId = -1; let switchStates: SelectedSwitchOptions = {}; /** @@ -71,85 +82,9 @@ export async function changeSwitch() { let selectedOption: deploy_plugins_switch.DeployTargetSwitchOption; let selectedTarget: deploy_plugins_switch.DeployTargetSwitch; - const SELECT_OPTION = async () => { - if (!selectedOption) { - return; - } - - setCurrentOptionFor(selectedTarget, selectedOption); - await saveStates.apply(ME, []); - - printSwitchStates.apply(ME, []); - }; - const SELECT_TARGET_OPTION = async (index: number) => { - if (!selectedTarget) { - return; - } - - const SWITCH_NAME = getSwitchName(selectedTarget, index); - - const OPTIONS = Enumerable.from( getTargetOptionsOf(selectedTarget) ) - .toArray() - .sort((x, y) => { - return deploy_helpers.compareValuesBy(x, y, - i => deploy_helpers.getSortValue(i, - () => ME.name)); - }); - - const OPTION_QUICK_PICKS: deploy_contracts.DeployActionQuickPick[] = OPTIONS.map((o, i) => { - const LABEL = getSwitchOptionName(o, i); - const DESCRIPTION = deploy_helpers.toStringSafe(o.description).trim(); - - let details = ''; - let isSelected = false; - - const SELECTED_OPTION_OF_TARGET = getCurrentOptionOf(selectedTarget); - if (SELECTED_OPTION_OF_TARGET) { - if (o.__id === SELECTED_OPTION_OF_TARGET.__id) { - isSelected = true; - } - } - - return { - action: async () => { - selectedOption = o; - - await SELECT_OPTION(); - }, - description: DESCRIPTION, - detail: isSelected ? `(${i18.t('selected')})` : '', - label: LABEL, - }; - }); - - if (OPTION_QUICK_PICKS.length < 1) { - vscode.window.showWarningMessage( - '[vs-deploy] ' + i18.t('plugins.switch.noOptionsDefined', - SWITCH_NAME), - ); - - return; - } - - let action: Function; - - if (1 === OPTION_QUICK_PICKS.length) { - action = OPTION_QUICK_PICKS[0].action; - } - else { - const SELECTED_ITEM = await vscode.window.showQuickPick(OPTION_QUICK_PICKS, { - placeHolder: i18.t('plugins.switch.selectOption', - SWITCH_NAME), - }); - if (SELECTED_ITEM) { - action = SELECTED_ITEM.action; - } - } - - if (action) { - await Promise.resolve(action()); - } + await selectTargetOption.apply(ME, + [ selectedTarget, index ]); }; const QUICK_PICKS: deploy_contracts.DeployActionQuickPick[] = TARGETS.map((t, i) => { @@ -382,6 +317,93 @@ export function printSwitchStates() { } } +/** + * Reloads the switch buttons. + */ +export function reloadButtons() { + const ME = this; + + while (BUTTONS.length > 0) { + const BTN = BUTTONS.shift(); + + deploy_helpers.tryDispose(BTN.button); + deploy_helpers.tryDispose(BTN.command); + } + + const SWITCHES: deploy_plugins_switch.DeployTargetSwitch[] = getSwitches.apply(ME, []); + SWITCHES.forEach((s, i) => { + let newBtn: vscode.StatusBarItem; + let newCmd: vscode.Disposable; + try { + if (deploy_helpers.isNullOrUndefined(s.button)) { + return; + } + + if ('object' !== typeof s.button) { + if (!deploy_helpers.toBooleanSafe(s.button)) { + return; + } + } + + let btn = s.button; + if ('object' !== typeof btn) { + btn = { + }; + } + + if (!deploy_helpers.toBooleanSafe(btn.enabled, true)) { + return; + } + + const ID = nextButtonId++; + + let color = deploy_helpers.normalizeString(btn.color); + const IS_RIGHT = deploy_helpers.toBooleanSafe(btn.isRight); + let prio = parseInt( + deploy_helpers.toStringSafe(btn.priority).trim() + ); + + if (deploy_helpers.isEmptyString(color)) { + color = '#ffffff'; + } + + if (isNaN(prio)) { + prio = undefined; + } + + const ALIGNMENT = IS_RIGHT ? vscode.StatusBarAlignment.Right + : vscode.StatusBarAlignment.Left; + + const COMMAND = 'extension.deploy.switches.button' + ID; + + newCmd = vscode.commands.registerCommand(COMMAND, async () => { + await selectTargetOption.apply(ME, [ s, i ]); + }); + + newBtn = vscode.window.createStatusBarItem(ALIGNMENT, prio); + newBtn.color = color; + newBtn.command = COMMAND; + newBtn.show(); + + BUTTONS.push({ + button: newBtn, + command: newCmd, + index: i, + settings: deploy_helpers.cloneObject(btn), + switch: s, + }); + } + catch (e) { + deploy_helpers.tryDispose(newBtn); + deploy_helpers.tryDispose(newCmd); + + ME.log(`[ERROR :: vs-deploy] switch.reloadButtons(): ${deploy_helpers.toStringSafe(e)}`); + } + }); + + updateButtons.apply(ME, []); +} + /** * Reloads the target states for switches. */ @@ -458,6 +480,93 @@ export async function saveStates() { } } +async function selectTargetOption(target: deploy_plugins_switch.DeployTargetSwitch, + index: number) { + const ME: vs_deploy.Deployer = this; + + if (!target) { + return; + } + + let selectedOption: deploy_plugins_switch.DeployTargetSwitchOption; + const SWITCH_NAME = getSwitchName(target, index); + + const OPTIONS = Enumerable.from( getTargetOptionsOf(target) ) + .toArray() + .sort((x, y) => { + return deploy_helpers.compareValuesBy(x, y, + i => deploy_helpers.getSortValue(i, + () => ME.name)); + }); + + const SELECT_OPTION = async () => { + if (!selectedOption) { + return; + } + + setCurrentOptionFor(target, selectedOption); + await saveStates.apply(ME, []); + + printSwitchStates.apply(ME, []); + + updateButtons.apply(ME, []); + }; + + const OPTION_QUICK_PICKS: deploy_contracts.DeployActionQuickPick[] = OPTIONS.map((o, i) => { + const LABEL = getSwitchOptionName(o, i); + const DESCRIPTION = deploy_helpers.toStringSafe(o.description).trim(); + + let details = ''; + let isSelected = false; + + const SELECTED_OPTION_OF_TARGET = getCurrentOptionOf(target); + if (SELECTED_OPTION_OF_TARGET) { + if (o.__id === SELECTED_OPTION_OF_TARGET.__id) { + isSelected = true; + } + } + + return { + action: async () => { + selectedOption = o; + + await SELECT_OPTION(); + }, + description: DESCRIPTION, + detail: isSelected ? `(${i18.t('selected')})` : '', + label: LABEL, + }; + }); + + if (OPTION_QUICK_PICKS.length < 1) { + vscode.window.showWarningMessage( + '[vs-deploy] ' + i18.t('plugins.switch.noOptionsDefined', + SWITCH_NAME), + ); + + return; + } + + let action: Function; + + if (1 === OPTION_QUICK_PICKS.length) { + action = OPTION_QUICK_PICKS[0].action; + } + else { + const SELECTED_ITEM = await vscode.window.showQuickPick(OPTION_QUICK_PICKS, { + placeHolder: i18.t('plugins.switch.selectOption', + SWITCH_NAME), + }); + if (SELECTED_ITEM) { + action = SELECTED_ITEM.action; + } + } + + if (action) { + await Promise.resolve(action()); + } +} + /** * Sets the current option for a switch target. * @@ -483,3 +592,54 @@ export function setCurrentOptionFor(target: deploy_plugins_switch.DeployTargetSw }; } } + +function updateButtons() { + const ME: vs_deploy.Deployer = this; + + BUTTONS.forEach(btn => { + const SWITCH_NAME = getSwitchName(btn.switch, btn.index); + const OPTION = getCurrentOptionOf(btn.switch); + + const VALUES: deploy_values.ValueBase[] = [ + new deploy_values.StaticValue({ + name: 'selectedSwitch', + value: SWITCH_NAME, + }), + new deploy_values.StaticValue({ + name: 'selectedSwitchOption', + value: false === OPTION ? undefined + : getSwitchOptionName(OPTION, OPTION.__index), + }), + ]; + ME.getValues().forEach(v => { + VALUES.push(v); + }); + + let text = deploy_helpers.toStringSafe( + deploy_values.replaceWithValues(VALUES, btn.settings.text) + ).trim(); + if ('' === text) { + // default text + text = i18.t('plugins.switch.button.text', + SWITCH_NAME); + } + + let tooltip = deploy_helpers.toStringSafe( + deploy_values.replaceWithValues(VALUES, btn.settings.tooltip) + ).trim(); + if ('' === tooltip) { + // default tooltip + if (false === OPTION) { + tooltip = i18.t('plugins.switch.button.tooltip', + i18.t('plugins.switch.noOptionSelected')); + } + else { + tooltip = i18.t('plugins.switch.button.tooltip', + `'${getSwitchOptionName(OPTION, OPTION.__index)}'`); + } + } + + btn.button.text = text; + btn.button.tooltip = tooltip; + }); +}