-
-
Notifications
You must be signed in to change notification settings - Fork 611
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #387 from cezarsa:grayscale
Add config for grayscale icons
- Loading branch information
Showing
13 changed files
with
310 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import * as vscode from 'vscode'; | ||
import * as helpers from './../helpers'; | ||
import * as i18n from './../i18n'; | ||
|
||
/** Command to toggle grayscale. */ | ||
export const toggleGrayscale = () => { | ||
return checkGrayscaleStatus() | ||
.then(showQuickPickItems) | ||
.then(handleQuickPickActions) | ||
.catch(err => console.log(err)); | ||
}; | ||
|
||
/** Show QuickPick items to select preferred configuration for grayscale icons. */ | ||
const showQuickPickItems = (status: boolean) => { | ||
const on: vscode.QuickPickItem = { | ||
description: i18n.translate('toggleSwitch.on'), | ||
detail: i18n.translate(`grayscale.enableGrayscale`), | ||
label: status ? '\u2714' : '\u25FB' | ||
}; | ||
const off: vscode.QuickPickItem = { | ||
description: i18n.translate('toggleSwitch.off'), | ||
detail: i18n.translate(`grayscale.disableGrayscale`), | ||
label: !status ? '\u2714' : '\u25FB' | ||
}; | ||
return vscode.window.showQuickPick( | ||
[on, off], { | ||
placeHolder: i18n.translate('grayscale.toggleGrayscale'), | ||
ignoreFocusOut: false, | ||
matchOnDescription: true | ||
}); | ||
}; | ||
|
||
/** Handle the actions from the QuickPick. */ | ||
const handleQuickPickActions = (value: vscode.QuickPickItem) => { | ||
if (!value || !value.description) return; | ||
switch (value.description) { | ||
case i18n.translate('toggleSwitch.on'): { | ||
helpers.setThemeConfig('saturation', 0, true); | ||
break; | ||
} | ||
case i18n.translate('toggleSwitch.off'): { | ||
helpers.setThemeConfig('saturation', 1, true); | ||
break; | ||
} | ||
default: | ||
break; | ||
} | ||
}; | ||
|
||
/** Is grayscale icons enabled? */ | ||
export const checkGrayscaleStatus = (): Promise<boolean> => { | ||
return helpers.getMaterialIconsJSON().then((config) => config.options.saturation === 0); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import * as vscode from 'vscode'; | ||
import { getDefaultIconOptions, validateSaturationValue } from '../icons'; | ||
import * as helpers from './../helpers'; | ||
import * as i18n from './../i18n'; | ||
|
||
/** Command to toggle the folder icons. */ | ||
export const changeSaturation = () => { | ||
return getCurrentSaturationValue() | ||
.then(showInput) | ||
.catch(err => console.log(err)); | ||
}; | ||
|
||
/** Show input to enter the saturation value. */ | ||
const showInput = (saturation: number) => { | ||
vscode.window.showInputBox({ | ||
placeHolder: i18n.translate('saturation.inputPlaceholder'), | ||
ignoreFocusOut: true, | ||
value: String(saturation), | ||
validateInput: validateSaturationInput | ||
}).then(value => setSaturationConfig(+value)); | ||
}; | ||
|
||
/** Validate the saturation value which was inserted by the user. */ | ||
const validateSaturationInput = (saturationInput: string) => { | ||
if (!validateSaturationValue(+saturationInput)) { | ||
return i18n.translate('saturation.wrongValue'); | ||
} | ||
return undefined; | ||
}; | ||
|
||
/** Get the current value of the saturation of the icons. */ | ||
export const getCurrentSaturationValue = (): Promise<number> => { | ||
const defaultOptions = getDefaultIconOptions(); | ||
return helpers.getMaterialIconsJSON().then((config) => | ||
config.options.saturation === undefined ? | ||
defaultOptions.saturation : config.options.saturation); | ||
}; | ||
|
||
const setSaturationConfig = (saturation: number) => { | ||
if (saturation !== undefined) { | ||
helpers.setThemeConfig('saturation', saturation, true); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
|
||
/** | ||
* Changes saturation of all icons in the set. | ||
* @param saturation Saturation value. | ||
* @param fileNames Only change the saturation of certain file names. | ||
*/ | ||
export const setIconSaturation = (saturation: number, fileNames?: string[]) => { | ||
if (!validateSaturationValue(saturation)) { | ||
return console.error('Invalid saturation value! Saturation must be a decimal number between 0 and 1!'); | ||
} | ||
|
||
return new Promise((resolve, reject) => { | ||
let iconsPath = path.join(__dirname, '..', '..', '..'); | ||
const parentFolder = iconsPath.split(path.sep).pop(); | ||
if (parentFolder === 'out') { | ||
iconsPath = path.join(iconsPath, '..'); | ||
} | ||
iconsPath = path.join(iconsPath, 'icons'); | ||
|
||
// read all icon files from the icons folder | ||
try { | ||
(fileNames || fs.readdirSync(iconsPath)).forEach(iconFileName => { | ||
const svgFilePath = path.join(iconsPath, iconFileName); | ||
|
||
// Read SVG file | ||
const svg = fs.readFileSync(svgFilePath, 'utf-8'); | ||
|
||
// Get the root element of the SVG file | ||
const svgRootElement = getSVGRootElement(svg); | ||
if (!svgRootElement) return; | ||
|
||
let updatedRootElement: string; | ||
if (saturation < 1) { | ||
updatedRootElement = addFilterAttribute(svgRootElement); | ||
} else { | ||
updatedRootElement = removeFilterAttribute(svgRootElement); | ||
} | ||
let updatedSVG = svg.replace(/<svg[^>]*>/, updatedRootElement); | ||
if (saturation < 1) { | ||
updatedSVG = addFilterElement(updatedSVG, saturation); | ||
} else { | ||
updatedSVG = removeFilterElement(updatedSVG); | ||
} | ||
|
||
fs.writeFileSync(svgFilePath, updatedSVG); | ||
resolve(); | ||
}); | ||
} | ||
catch (e) { | ||
console.log(e); | ||
reject(e); | ||
} | ||
resolve(); | ||
}); | ||
}; | ||
|
||
/** | ||
* Get the SVG root element. | ||
* @param svg SVG file as string. | ||
*/ | ||
const getSVGRootElement = (svg: string) => { | ||
const result = new RegExp(/<svg[^>]*>/).exec(svg); | ||
if (result.length > 0) { | ||
return result[0]; | ||
} else { | ||
return undefined; | ||
} | ||
}; | ||
|
||
/** | ||
* Add an filter attribute to the SVG icon. | ||
* @param svgRoot Root element of the SVG icon. | ||
*/ | ||
const addFilterAttribute = (svgRoot: string) => { | ||
const pattern = new RegExp(/\sfilter="[^"]+?"/); | ||
// if the filter attribute already exists | ||
if (pattern.test(svgRoot)) { | ||
return svgRoot.replace(pattern, ` filter="url(#saturation)"`); | ||
} else { | ||
return svgRoot.replace(/^<svg/, `<svg filter="url(#saturation)"`); | ||
} | ||
}; | ||
|
||
/** | ||
* Remove the filter attribute of the SVG icon. | ||
* @param svgRoot Root element of the SVG icon. | ||
*/ | ||
const removeFilterAttribute = (svgRoot: string) => { | ||
const pattern = new RegExp(/\sfilter="[^"]+?"/); | ||
// check if the filter attribute exists | ||
if (pattern.test(svgRoot)) { | ||
return svgRoot.replace(pattern, ''); | ||
} | ||
return svgRoot; | ||
}; | ||
|
||
/** | ||
* Add filter element to the SVG icon. | ||
* @param svg SVG file as string. | ||
*/ | ||
const addFilterElement = (svg: string, value: number) => { | ||
const pattern = new RegExp(/<filter id="saturation".+<\/filter>(.*<\/svg>)/); | ||
const filterElement = `<filter id="saturation"><feColorMatrix type="saturate" values="${value}"/></filter>`; | ||
if (pattern.test(svg)) { | ||
return svg.replace(pattern, `${filterElement}$1`); | ||
} else { | ||
return svg.replace(/<\/svg>/, `${filterElement}</svg>`); | ||
} | ||
return svg; | ||
}; | ||
|
||
/** | ||
* Remove filter element from the SVG icon. | ||
* @param svg SVG file as string. | ||
*/ | ||
const removeFilterElement = (svg: string) => { | ||
const pattern = new RegExp(/<filter id="saturation".+<\/filter>(.*<\/svg>)/); | ||
if (pattern.test(svg)) { | ||
return svg.replace(pattern, `$1`); | ||
} | ||
return svg; | ||
}; | ||
|
||
/** | ||
* Validate the saturation value. | ||
* @param saturation Saturation value | ||
*/ | ||
export const validateSaturationValue = (saturation: number) => { | ||
return saturation !== null && saturation <= 1 && saturation >= 0; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.