From 597cc0ae320aea06a4b1e5015e8fa116686cd459 Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Mon, 18 Jul 2022 17:46:39 +0200 Subject: [PATCH 1/4] add typing support to steppers --- .../dialogs/settings/settings-component.tsx | 61 ++++----- .../dialogs/settings/settings-step-input.tsx | 122 ++++++++++++++++++ .../src/browser/style/index.css | 1 + .../src/browser/style/settings-step-input.css | 47 +++++++ 4 files changed, 198 insertions(+), 33 deletions(-) create mode 100644 arduino-ide-extension/src/browser/dialogs/settings/settings-step-input.tsx create mode 100644 arduino-ide-extension/src/browser/style/settings-step-input.css diff --git a/arduino-ide-extension/src/browser/dialogs/settings/settings-component.tsx b/arduino-ide-extension/src/browser/dialogs/settings/settings-component.tsx index ff70947ff..620cd1982 100644 --- a/arduino-ide-extension/src/browser/dialogs/settings/settings-component.tsx +++ b/arduino-ide-extension/src/browser/dialogs/settings/settings-component.tsx @@ -21,7 +21,15 @@ import { AsyncLocalizationProvider, LanguageInfo, } from '@theia/core/lib/common/i18n/localization'; +import SettingsStepInput from './settings-step-input'; +const maxScale = 200; +const minScale = -100; +const scaleStep = 20; + +const maxFontSize = 72; +const minFontSize = 8; +const fontSizeStep = 2; export class SettingsComponent extends React.Component< SettingsComponent.Props, SettingsComponent.State @@ -88,6 +96,8 @@ export class SettingsComponent extends React.Component< } protected renderSettings(): React.ReactNode { + const scalePercentage = 100 + this.state.interfaceScale * 20; + return (
{nls.localize( @@ -160,14 +170,13 @@ export class SettingsComponent extends React.Component<
-
@@ -179,14 +188,13 @@ export class SettingsComponent extends React.Component< /> {nls.localize('arduino/preferences/automatic', 'Automatic')} - %
@@ -516,13 +524,8 @@ export class SettingsComponent extends React.Component< } }; - protected editorFontSizeDidChange = ( - event: React.ChangeEvent - ): void => { - const { value } = event.target; - if (value) { - this.setState({ editorFontSize: parseInt(value, 10) }); - } + private setFontSize = (editorFontSize: number) => { + this.setState({ editorFontSize }); }; protected rawAdditionalUrlsValueDidChange = ( @@ -539,18 +542,10 @@ export class SettingsComponent extends React.Component< this.setState({ autoScaleInterface: event.target.checked }); }; - protected interfaceScaleDidChange = ( - event: React.ChangeEvent - ): void => { - const { value } = event.target; - const percentage = parseInt(value, 10); - if (isNaN(percentage)) { - return; - } + private setInterfaceScale = (percentage: number) => { const interfaceScale = (percentage - 100) / 20; - if (!isNaN(interfaceScale)) { - this.setState({ interfaceScale }); - } + + this.setState({ interfaceScale }); }; protected verifyAfterUploadDidChange = ( diff --git a/arduino-ide-extension/src/browser/dialogs/settings/settings-step-input.tsx b/arduino-ide-extension/src/browser/dialogs/settings/settings-step-input.tsx new file mode 100644 index 000000000..d6f54ea7b --- /dev/null +++ b/arduino-ide-extension/src/browser/dialogs/settings/settings-step-input.tsx @@ -0,0 +1,122 @@ +import * as React from '@theia/core/shared/react'; +import classnames from 'classnames'; + +interface SettingsStepInputProps { + value: number; + setSettingsStateValue: (interfaceScale: number) => void; + step: number; + maxValue: number; + minValue: number; + classNames?: { [key: string]: string }; +} + +const SettingsStepInput: React.FC = ( + props: SettingsStepInputProps +) => { + const { value, setSettingsStateValue, step, maxValue, minValue, classNames } = + props; + + const [stepUpDisabled, setStepUpDisabled] = React.useState(false); + const [stepDownDisabled, setStepDownDisabled] = React.useState(false); + + const onStepUp = (): void => { + const valueRoundedToScale = Math.ceil(value / step) * step; + const calculatedValue = + valueRoundedToScale === value ? value + step : valueRoundedToScale; + const newValue = limitValueByCondition( + calculatedValue, + calculatedValue >= maxValue, + () => setStepUpDisabled(true) + ); + + setSettingsStateValue(newValue); + }; + + const onStepDown = (): void => { + const valueRoundedToScale = Math.floor(value / step) * step; + const calculatedValue = + valueRoundedToScale === value ? value - step : valueRoundedToScale; + const newValue = limitValueByCondition( + calculatedValue, + calculatedValue <= minValue, + () => setStepDownDisabled(true) + ); + + setSettingsStateValue(newValue); + }; + + const limitValueByCondition = ( + calculatedValue: number, + condition: boolean, + onConditionTrue: () => void, + onConditionFalse = enableButtons + ): number => { + if (condition) { + onConditionTrue(); + return minValue; + } else { + onConditionFalse(); + return calculatedValue; + } + }; + + const enableButtons = (): void => { + setStepUpDisabled(false); + setStepDownDisabled(false); + }; + + const onUserInput = (event: React.ChangeEvent): void => { + const { value: eventValue } = event.target; + + if (eventValue === '') { + setSettingsStateValue(0); + } + + const number = Number(eventValue); + + if (!isNaN(number) && number !== value) { + let newValue; + if (number > value) { + newValue = limitValueByCondition(number, number >= maxValue, () => + setStepUpDisabled(true) + ); + } else { + newValue = limitValueByCondition(number, number <= minValue, () => + setStepDownDisabled(true) + ); + } + + setSettingsStateValue(newValue); + } + }; + + return ( +
+ +
+ + +
+
+ ); +}; + +export default SettingsStepInput; diff --git a/arduino-ide-extension/src/browser/style/index.css b/arduino-ide-extension/src/browser/style/index.css index fe5d9753f..1a7c98533 100644 --- a/arduino-ide-extension/src/browser/style/index.css +++ b/arduino-ide-extension/src/browser/style/index.css @@ -18,6 +18,7 @@ @import './fonts.css'; @import './custom-codicon.css'; @import './progress-bar.css'; +@import './settings-step-input.css'; .theia-input.warning:focus { outline-width: 1px; diff --git a/arduino-ide-extension/src/browser/style/settings-step-input.css b/arduino-ide-extension/src/browser/style/settings-step-input.css new file mode 100644 index 000000000..fd6d6046f --- /dev/null +++ b/arduino-ide-extension/src/browser/style/settings-step-input.css @@ -0,0 +1,47 @@ +.settings-step-input-container { + position: relative +} + +.settings-step-input-element::-webkit-inner-spin-button, +.settings-step-input-element::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; +} + +.settings-step-input-buttons-container { + display: none; + flex-direction: column; + position: absolute; + right: 0px; + top: 50%; + transform: translate(0px, -50%); + height: calc(100% - 4px); + width: 14px; + padding: 2px; + background: white; +} + +.settings-step-input-container:hover > .settings-step-input-buttons-container { + display: flex; +} + +.settings-step-input-up-button { + transform: rotate(-180deg); +} + +.settings-step-input-button { + border: none; + border-radius: 0; + height: 50%; + width: 1; + display: flex; + align-items: center; + justify-content: center; + user-select: none; + cursor: pointer; + line-height: 12px; +} + +.settings-step-input-button:hover { + background: rgba(128, 128, 128, 0.8); +} From c7971601f57bc41194c6e303b2988b6fc3a62c95 Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Mon, 18 Jul 2022 18:08:51 +0200 Subject: [PATCH 2/4] logic cleanup --- .../dialogs/settings/settings-step-input.tsx | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/arduino-ide-extension/src/browser/dialogs/settings/settings-step-input.tsx b/arduino-ide-extension/src/browser/dialogs/settings/settings-step-input.tsx index d6f54ea7b..d8de881fa 100644 --- a/arduino-ide-extension/src/browser/dialogs/settings/settings-step-input.tsx +++ b/arduino-ide-extension/src/browser/dialogs/settings/settings-step-input.tsx @@ -25,8 +25,9 @@ const SettingsStepInput: React.FC = ( valueRoundedToScale === value ? value + step : valueRoundedToScale; const newValue = limitValueByCondition( calculatedValue, + maxValue, calculatedValue >= maxValue, - () => setStepUpDisabled(true) + disableStepUp ); setSettingsStateValue(newValue); @@ -38,8 +39,9 @@ const SettingsStepInput: React.FC = ( valueRoundedToScale === value ? value - step : valueRoundedToScale; const newValue = limitValueByCondition( calculatedValue, + minValue, calculatedValue <= minValue, - () => setStepDownDisabled(true) + disableStepDown ); setSettingsStateValue(newValue); @@ -47,13 +49,14 @@ const SettingsStepInput: React.FC = ( const limitValueByCondition = ( calculatedValue: number, + limitedValue: number, condition: boolean, onConditionTrue: () => void, onConditionFalse = enableButtons ): number => { if (condition) { onConditionTrue(); - return minValue; + return limitedValue; } else { onConditionFalse(); return calculatedValue; @@ -65,6 +68,14 @@ const SettingsStepInput: React.FC = ( setStepDownDisabled(false); }; + const disableStepUp = (): void => { + setStepUpDisabled(true); + }; + + const disableStepDown = (): void => { + setStepDownDisabled(true); + }; + const onUserInput = (event: React.ChangeEvent): void => { const { value: eventValue } = event.target; @@ -77,12 +88,18 @@ const SettingsStepInput: React.FC = ( if (!isNaN(number) && number !== value) { let newValue; if (number > value) { - newValue = limitValueByCondition(number, number >= maxValue, () => - setStepUpDisabled(true) + newValue = limitValueByCondition( + number, + maxValue, + number >= maxValue, + disableStepUp ); } else { - newValue = limitValueByCondition(number, number <= minValue, () => - setStepDownDisabled(true) + newValue = limitValueByCondition( + number, + minValue, + number <= minValue, + disableStepDown ); } From c18850ba0f15cfb1db71445cdc4d257d641cb1d1 Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Mon, 18 Jul 2022 18:18:49 +0200 Subject: [PATCH 3/4] misc cleanup --- .../src/browser/dialogs/settings/settings-component.tsx | 2 +- .../src/browser/dialogs/settings/settings-step-input.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arduino-ide-extension/src/browser/dialogs/settings/settings-component.tsx b/arduino-ide-extension/src/browser/dialogs/settings/settings-component.tsx index 620cd1982..6bbc3c4c1 100644 --- a/arduino-ide-extension/src/browser/dialogs/settings/settings-component.tsx +++ b/arduino-ide-extension/src/browser/dialogs/settings/settings-component.tsx @@ -28,7 +28,7 @@ const minScale = -100; const scaleStep = 20; const maxFontSize = 72; -const minFontSize = 8; +const minFontSize = 0; const fontSizeStep = 2; export class SettingsComponent extends React.Component< SettingsComponent.Props, diff --git a/arduino-ide-extension/src/browser/dialogs/settings/settings-step-input.tsx b/arduino-ide-extension/src/browser/dialogs/settings/settings-step-input.tsx index d8de881fa..c7abfb5da 100644 --- a/arduino-ide-extension/src/browser/dialogs/settings/settings-step-input.tsx +++ b/arduino-ide-extension/src/browser/dialogs/settings/settings-step-input.tsx @@ -3,7 +3,7 @@ import classnames from 'classnames'; interface SettingsStepInputProps { value: number; - setSettingsStateValue: (interfaceScale: number) => void; + setSettingsStateValue: (value: number) => void; step: number; maxValue: number; minValue: number; From 0b2f390529dfa7bfc47f4d84d0ce522e2ebab749 Mon Sep 17 00:00:00 2001 From: David Simpson <45690499+davegarthsimpson@users.noreply.github.com> Date: Tue, 19 Jul 2022 10:21:16 +0200 Subject: [PATCH 4/4] account for lack of unmount --- .../src/browser/dialogs/settings/settings-step-input.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arduino-ide-extension/src/browser/dialogs/settings/settings-step-input.tsx b/arduino-ide-extension/src/browser/dialogs/settings/settings-step-input.tsx index c7abfb5da..458266fa9 100644 --- a/arduino-ide-extension/src/browser/dialogs/settings/settings-step-input.tsx +++ b/arduino-ide-extension/src/browser/dialogs/settings/settings-step-input.tsx @@ -107,6 +107,14 @@ const SettingsStepInput: React.FC = ( } }; + // the component does not unmount when we close the settings dialog + // in theia which necessitates the below useEffect + React.useEffect(() => { + if (value > minValue && value < maxValue) { + enableButtons(); + } + }, [value, minValue, maxValue]); + return (