diff --git a/README.md b/README.md index 814545b..98403a4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# Color Picker for StreamDeck +# Color Picker for StreamDeck + ## Description As a [color-blind](https://en.wikipedia.org/wiki/Color_blindness) person sometimes I struggle to recognize certain colors, so I thought it would be nice to have the functionality of [WhatColor](http://www.hikarun.com/e/) in StreamDeck. And while I was there, I decided to add the options to show their RGB or hexadecimal value. @@ -12,17 +13,19 @@ Also check my [KeePass plugin](https://github.com/VictorGrycuk/StreamDeck-KeePas It was done using BarRaider's [Stream Deck Tools](https://github.com/BarRaider/streamdeck-tools). ## Features -#### Color Picker + +### Color Picker When pressed, it will return either the color name, the RGB value, or the hexadecimal value of the color where the mouse is. It has the following configuration: -- **Value to show:** The value to show on the key: - - Color name - - RGB Value - - Hex Value -- **Copy value to clipboard:** If checked, it will copy the selected value to the clipboard. For the RGB it will copy the RGB value delimited by coma, for the hexadecimal value it will copy the hexadecimal without the hash character. +- **Value to show:** The value to show on the key: + - Color name + - RGB Value + - Hex Value + +- **Copy value to clipboard:** If checked, it will copy the selected value to the clipboard. For the RGB it will copy the RGB value delimited by coma, for the hexadecimal value it will copy the hexadecimal without the hash character. -#### Custom Color Name +### Custom Color Name I am using the [WhatColor](http://www.hikarun.com/e/) names definition for the 16 VGA color. I might expand this, not sure. @@ -32,11 +35,10 @@ However, have in mind that in its current state, the plugin has a static font si ## Future Features -I am planning to add two different behaviour for the plugin: +I am planning to add one more behaviour for the plugin: -- **Dynamic:** Follow the mouse around and update the data shown in the key every 1 second. -- **Fixed Dynamic:** Same as above, except at a fixed screen location. +- **Fixed Dynamic:** Same as above, except at a fixed screen location. ---- +* * * -The icons are modified version of *Color* and *iOS Filled* at [Icon8](https://icons8.com). \ No newline at end of file +The icons are modified version of _Color_ and _iOS Filled_ at [Icon8](https://icons8.com). diff --git a/StreamDeck.ColorPicker/StreamDeck.ColorPicker/Program.cs b/StreamDeck.ColorPicker/StreamDeck.ColorPicker/Program.cs index f65db67..aa66a34 100644 --- a/StreamDeck.ColorPicker/StreamDeck.ColorPicker/Program.cs +++ b/StreamDeck.ColorPicker/StreamDeck.ColorPicker/Program.cs @@ -1,19 +1,11 @@ using BarRaider.SdTools; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace StreamDeck.ColorPicker { - class Program + static class Program { static void Main(string[] args) { - // Uncomment this line of code to allow for debugging - //while (!System.Diagnostics.Debugger.IsAttached) { System.Threading.Thread.Sleep(100); } - SDWrapper.Run(args); } } diff --git a/StreamDeck.ColorPicker/StreamDeck.ColorPicker/PropertyInspector/ColorPickerPI.html b/StreamDeck.ColorPicker/StreamDeck.ColorPicker/PropertyInspector/ColorPickerPI.html index 5a73c12..5ce88ec 100644 --- a/StreamDeck.ColorPicker/StreamDeck.ColorPicker/PropertyInspector/ColorPickerPI.html +++ b/StreamDeck.ColorPicker/StreamDeck.ColorPicker/PropertyInspector/ColorPickerPI.html @@ -12,6 +12,13 @@
+
+
Select Type
+ +
Value to show
- - - - -
-
-
Copy value to clipboard
-
-
- - -
-
-
-
- - diff --git a/StreamDeck.ColorPicker/StreamDeck.ColorPicker/PropertyInspector/sdtools.common.js b/StreamDeck.ColorPicker/StreamDeck.ColorPicker/PropertyInspector/sdtools.common.js index 9b82b1a..5709a5c 100644 --- a/StreamDeck.ColorPicker/StreamDeck.ColorPicker/PropertyInspector/sdtools.common.js +++ b/StreamDeck.ColorPicker/StreamDeck.ColorPicker/PropertyInspector/sdtools.common.js @@ -42,16 +42,17 @@ function websocketOnMessage(evt) { // Received message from Stream Deck var jsonObj = JSON.parse(evt.data); + var payload; if (jsonObj.event === 'sendToPropertyInspector') { - var payload = jsonObj.payload; + payload = jsonObj.payload; loadConfiguration(payload); } else if (jsonObj.event === 'didReceiveSettings') { - var payload = jsonObj.payload; + payload = jsonObj.payload; loadConfiguration(payload.settings); } else { - console.log("Unhandled websocketOnMessage: " + jsonObj.event); + console.log('Unhandled websocketOnMessage: ' + jsonObj.event); } } @@ -61,20 +62,20 @@ function loadConfiguration(payload) { for (var key in payload) { try { var elem = document.getElementById(key); - if (elem.classList.contains("sdCheckbox")) { // Checkbox + if (elem.classList.contains('sdCheckbox')) { // Checkbox elem.checked = payload[key]; } - else if (elem.classList.contains("sdFile")) { // File - var elemFile = document.getElementById(elem.id + "Filename"); + else if (elem.classList.contains('sdFile')) { // File + var elemFile = document.getElementById(elem.id + 'Filename'); elemFile.innerText = payload[key]; if (!elemFile.innerText) { - elemFile.innerText = "No file..."; + elemFile.innerText = 'No file...'; } } - else if (elem.classList.contains("sdList")) { // Dynamic dropdown - var textProperty = elem.getAttribute("sdListTextProperty"); - var valueProperty = elem.getAttribute("sdListValueProperty"); - var valueField = elem.getAttribute("sdValueField"); + else if (elem.classList.contains('sdList')) { // Dynamic dropdown + var textProperty = elem.getAttribute('sdListTextProperty'); + var valueProperty = elem.getAttribute('sdListValueProperty'); + var valueField = elem.getAttribute('sdValueField'); var items = payload[key]; elem.options.length = 0; @@ -87,31 +88,32 @@ function loadConfiguration(payload) { } elem.value = payload[valueField]; } - else if (elem.classList.contains("sdHTML")) { // HTML element + else if (elem.classList.contains('sdHTML')) { // HTML element elem.innerHTML = payload[key]; } else { // Normal value elem.value = payload[key]; } - console.log("Load: " + key + "=" + payload[key]); + console.log(`Load: ${ key }=${ payload[key] }`); } catch (err) { - console.log("loadConfiguration failed for key: " + key + " - " + err); + console.log(`loadConfiguration failed for key: ${ key } - ${ err }`); } } } function setSettings() { var payload = {}; - var elements = document.getElementsByClassName("sdProperty"); + var elements = document.getElementsByClassName('sdProperty'); Array.prototype.forEach.call(elements, function (elem) { var key = elem.id; - if (elem.classList.contains("sdCheckbox")) { // Checkbox + var valueField; + if (elem.classList.contains('sdCheckbox')) { // Checkbox payload[key] = elem.checked; } - else if (elem.classList.contains("sdFile")) { // File - var elemFile = document.getElementById(elem.id + "Filename"); + else if (elem.classList.contains('sdFile')) { // File + var elemFile = document.getElementById(elem.id + 'Filename'); payload[key] = elem.value; if (!elem.value) { // Fetch innerText if file is empty (happens when we lose and regain focus to this key) @@ -122,18 +124,18 @@ function setSettings() { elemFile.innerText = elem.value; } } - else if (elem.classList.contains("sdList")) { // Dynamic dropdown - var valueField = elem.getAttribute("sdValueField"); + else if (elem.classList.contains('sdList')) { // Dynamic dropdown + valueField = elem.getAttribute('sdValueField'); payload[valueField] = elem.value; } - else if (elem.classList.contains("sdHTML")) { // HTML element - var valueField = elem.getAttribute("sdValueField"); + else if (elem.classList.contains('sdHTML')) { // HTML element + valueField = elem.getAttribute('sdValueField'); payload[valueField] = elem.innerHTML; } else { // Normal value payload[key] = elem.value; } - console.log("Save: " + key + "<=" + payload[key]); + console.log(`Save: ${ key }<=${ payload[key] }`); }); setSettingsToPlugin(payload); } @@ -155,7 +157,7 @@ function setSettingsToPlugin(payload) { function sendPayloadToPlugin(payload) { if (websocket && (websocket.readyState === 1)) { const json = { - 'action': actionInfo['action'], + 'action': actionInfo.action, 'event': 'sendToPlugin', 'context': uuid, 'payload': payload @@ -168,7 +170,7 @@ function sendPayloadToPlugin(payload) { function sendValueToPlugin(value, param) { if (websocket && (websocket.readyState === 1)) { const json = { - 'action': actionInfo['action'], + 'action': actionInfo.action, 'event': 'sendToPlugin', 'context': uuid, 'payload': { @@ -231,20 +233,20 @@ function addDynamicStyles(clrs) { input[type="radio"]:active + label span, input[type="checkbox"]:active:checked + label span, input[type="checkbox"]:active + label span { - background-color: ${clrs.mouseDownColor}; + background-color: ${clrs.mouseDownColor}; } input[type="radio"]:active + label span, input[type="checkbox"]:active + label span { - background-color: ${clrs.buttonPressedBorderColor}; + background-color: ${clrs.buttonPressedBorderColor}; } td.selected, td.selected:hover, li.selected:hover, li.selected { - color: white; - background-color: ${clrs.highlightColor}; + color: white; + background-color: ${clrs.highlightColor}; } .sdpi-file-label > label:active, @@ -253,9 +255,9 @@ function addDynamicStyles(clrs) { label.sdpi-file-info:active, input[type="file"]::-webkit-file-upload-button:active, button:active { - background-color: ${clrs.buttonPressedBackgroundColor}; - color: ${clrs.buttonPressedTextColor}; - border-color: ${clrs.buttonPressedBorderColor}; + background-color: ${clrs.buttonPressedBackgroundColor}; + color: ${clrs.buttonPressedTextColor}; + border-color: ${clrs.buttonPressedBorderColor}; } ::-webkit-progress-value, @@ -269,7 +271,7 @@ function addDynamicStyles(clrs) { } `; document.body.appendChild(node); -}; +} /** UTILITIES */ diff --git a/StreamDeck.ColorPicker/StreamDeck.ColorPicker/ScreenHelper.cs b/StreamDeck.ColorPicker/StreamDeck.ColorPicker/ScreenHelper.cs index 67db224..8416105 100644 --- a/StreamDeck.ColorPicker/StreamDeck.ColorPicker/ScreenHelper.cs +++ b/StreamDeck.ColorPicker/StreamDeck.ColorPicker/ScreenHelper.cs @@ -1,12 +1,8 @@ -using System; -using System.Collections.Generic; +using BarRaider.SdTools; +using System; using System.Drawing; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; using System.Drawing.Imaging; -using BarRaider.SdTools; +using System.Runtime.InteropServices; namespace StreamDeck.ColorPicker { @@ -50,7 +46,7 @@ public static Color GetColor(Point location) { IntPtr hSrcDC = gsrc.GetHdc(); IntPtr hDC = gdest.GetHdc(); - int retval = BitBlt(hDC, 0, 0, 1, 1, hSrcDC, location.X, location.Y, (int)CopyPixelOperation.SourceCopy); + _ = BitBlt(hDC, 0, 0, 1, 1, hSrcDC, location.X, location.Y, (int)CopyPixelOperation.SourceCopy); gdest.ReleaseHdc(); gsrc.ReleaseHdc(); } diff --git a/StreamDeck.ColorPicker/StreamDeck.ColorPicker/StaticPicker.cs b/StreamDeck.ColorPicker/StreamDeck.ColorPicker/StaticPicker.cs index 34d3d11..633de81 100644 --- a/StreamDeck.ColorPicker/StreamDeck.ColorPicker/StaticPicker.cs +++ b/StreamDeck.ColorPicker/StreamDeck.ColorPicker/StaticPicker.cs @@ -2,7 +2,6 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; -using System.Threading.Tasks; namespace StreamDeck.ColorPicker { @@ -13,20 +12,40 @@ private class PluginSettings { public static PluginSettings CreateDefaultSettings() { - var instance = new PluginSettings { ValueToShow = string.Empty }; + var instance = new PluginSettings + { + SelectValueToShow = string.Empty, + SelectFunctionType = string.Empty, + }; + return instance; } [JsonProperty(PropertyName = "valueToShow")] - public string ValueToShow { get; set; } + public string SelectValueToShow { get; set; } + + public ValueFormat.ValueType ValueToShow { get; set; } [JsonProperty(PropertyName = "copyToClipboard")] public bool CopyToClipboard { get; set; } + + [JsonProperty(PropertyName = "functionType")] + public string SelectFunctionType { get; set; } + + public FunctionType FunctionType { get; set; } + + public string ColorValue { get; set; } + } + + public enum FunctionType + { + OnKeyPress, + Dynamic } #region Private Members - private PluginSettings settings; + private static PluginSettings settings; #endregion public StaticPicker(SDConnection connection, InitialPayload payload) : base(connection, payload) @@ -45,16 +64,14 @@ public override void KeyPressed(KeyPayload payload) { try { - Enum.TryParse(settings.ValueToShow, true, out ValueFormat.ValueType valueType); - var position = ScreenHelper.GetMouseLocation(); - var color = ScreenHelper.GetColor(position); - var valueFormat = new ValueFormat(valueType, color); - var keyImage = ScreenHelper.GetKeyImage(valueFormat); - Connection.SetImageAsync(keyImage); + if (settings.FunctionType == FunctionType.OnKeyPress) + { + SetImage(); + } if (settings.CopyToClipboard) { - ClipboardHelper.SendToClipboard(valueFormat.ValueToCopy); + ClipboardHelper.SendToClipboard(settings.ColorValue); } } catch (Exception ex) @@ -63,14 +80,38 @@ public override void KeyPressed(KeyPayload payload) } } + public void SetImage() + { + var position = ScreenHelper.GetMouseLocation(); + var color = ScreenHelper.GetColor(position); + var valueFormat = new ValueFormat(settings.ValueToShow, color); + settings.ColorValue = valueFormat.ValueToCopy; + + Connection.SetImageAsync(ScreenHelper.GetKeyImage(valueFormat)); + } + public override void KeyReleased(KeyPayload payload) { } - public override void OnTick() { } + public override void OnTick() + { + try + { + if (settings.FunctionType == FunctionType.Dynamic) + { + SetImage(); + } + } + catch (Exception ex) + { + Logger.Instance.LogMessage(TracingLevel.INFO, ex.Message); + } + } public override void ReceivedSettings(ReceivedSettingsPayload payload) { - Logger.Instance.LogMessage(TracingLevel.INFO, payload.Settings.ToString()); Tools.AutoPopulateSettings(settings, payload.Settings); + UpdateSettingsEnum(); + SaveSettings(); } @@ -78,9 +119,18 @@ public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payloa #region Private Methods - private Task SaveSettings() + private void SaveSettings() { - return Connection.SetSettingsAsync(JObject.FromObject(settings)); + _ = Connection.SetSettingsAsync(JObject.FromObject(settings)); + } + + private void UpdateSettingsEnum() + { + _ = Enum.TryParse(settings.SelectFunctionType, true, out FunctionType functionType); + _ = Enum.TryParse(settings.SelectValueToShow, true, out ValueFormat.ValueType valueType); + + settings.FunctionType = functionType; + settings.ValueToShow = valueType; } #endregion diff --git a/StreamDeck.ColorPicker/StreamDeck.ColorPicker/ValueFormat.cs b/StreamDeck.ColorPicker/StreamDeck.ColorPicker/ValueFormat.cs index 34673ce..e5c56b7 100644 --- a/StreamDeck.ColorPicker/StreamDeck.ColorPicker/ValueFormat.cs +++ b/StreamDeck.ColorPicker/StreamDeck.ColorPicker/ValueFormat.cs @@ -46,6 +46,8 @@ public ValueFormat(ValueType valueType, Color color) ValueToShow = color.ToHex().Replace("#", string.Empty); ValueToCopy = ValueToShow; break; + default: + throw new NotSupportedException($"The value '{ valueType }' is not supported."); } // Set the text color to white if the color is below certain threshold diff --git a/StreamDeck.ColorPicker/StreamDeck.ColorPicker/manifest.json b/StreamDeck.ColorPicker/StreamDeck.ColorPicker/manifest.json index 50834ba..cead260 100644 --- a/StreamDeck.ColorPicker/StreamDeck.ColorPicker/manifest.json +++ b/StreamDeck.ColorPicker/StreamDeck.ColorPicker/manifest.json @@ -21,7 +21,7 @@ "Description": "Colorblind Helper & Color Picker for Stream Deck", "Icon": "Images/pluginIcon", "URL": "https://github.com/VictorGrycuk/streamdeck-color-picker", - "Version": "1.0", + "Version": "1.1", "CodePath": "StreamDeck.ColorPicker", "Category": "Color Picker", "CategoryIcon": "Images/categoryIcon",