Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1f7c2eb

Browse files
Add typing support to steppers (#1209)
* add typing support to steppers * logic cleanup * misc cleanup * account for lack of unmount
1 parent 119dfa7 commit 1f7c2eb

File tree

4 files changed

+223
-33
lines changed

4 files changed

+223
-33
lines changed

‎arduino-ide-extension/src/browser/dialogs/settings/settings-component.tsx‎

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,15 @@ import {
2121
AsyncLocalizationProvider,
2222
LanguageInfo,
2323
} from '@theia/core/lib/common/i18n/localization';
24+
import SettingsStepInput from './settings-step-input';
2425

26+
const maxScale = 200;
27+
const minScale = -100;
28+
const scaleStep = 20;
29+
30+
const maxFontSize = 72;
31+
const minFontSize = 0;
32+
const fontSizeStep = 2;
2533
export class SettingsComponent extends React.Component<
2634
SettingsComponent.Props,
2735
SettingsComponent.State
@@ -88,6 +96,8 @@ export class SettingsComponent extends React.Component<
8896
}
8997

9098
protected renderSettings(): React.ReactNode {
99+
const scalePercentage = 100 + this.state.interfaceScale * 20;
100+
91101
return (
92102
<div className="content noselect">
93103
{nls.localize(
@@ -160,14 +170,13 @@ export class SettingsComponent extends React.Component<
160170
</div>
161171
<div className="column">
162172
<div className="flex-line">
163-
<input
164-
className="theia-input small"
165-
type="number"
166-
step={1}
167-
pattern="[0-9]+"
168-
onKeyDown={this.numbersOnlyKeyDown}
173+
<SettingsStepInput
169174
value={this.state.editorFontSize}
170-
onChange={this.editorFontSizeDidChange}
175+
setSettingsStateValue={this.setFontSize}
176+
step={fontSizeStep}
177+
maxValue={maxFontSize}
178+
minValue={minFontSize}
179+
classNames={{ input: 'theia-input small' }}
171180
/>
172181
</div>
173182
<div className="flex-line">
@@ -179,14 +188,13 @@ export class SettingsComponent extends React.Component<
179188
/>
180189
{nls.localize('arduino/preferences/automatic', 'Automatic')}
181190
</label>
182-
<input
183-
className="theia-input small with-margin"
184-
type="number"
185-
step={20}
186-
pattern="[0-9]+"
187-
onKeyDown={this.noopKeyDown}
188-
value={100 + this.state.interfaceScale * 20}
189-
onChange={this.interfaceScaleDidChange}
191+
<SettingsStepInput
192+
value={scalePercentage}
193+
setSettingsStateValue={this.setInterfaceScale}
194+
step={scaleStep}
195+
maxValue={maxScale}
196+
minValue={minScale}
197+
classNames={{ input: 'theia-input small with-margin' }}
190198
/>
191199
%
192200
</div>
@@ -516,13 +524,8 @@ export class SettingsComponent extends React.Component<
516524
}
517525
};
518526

519-
protected editorFontSizeDidChange = (
520-
event: React.ChangeEvent<HTMLInputElement>
521-
): void => {
522-
const { value } = event.target;
523-
if (value) {
524-
this.setState({ editorFontSize: parseInt(value, 10) });
525-
}
527+
private setFontSize = (editorFontSize: number) => {
528+
this.setState({ editorFontSize });
526529
};
527530

528531
protected rawAdditionalUrlsValueDidChange = (
@@ -539,18 +542,10 @@ export class SettingsComponent extends React.Component<
539542
this.setState({ autoScaleInterface: event.target.checked });
540543
};
541544

542-
protected interfaceScaleDidChange = (
543-
event: React.ChangeEvent<HTMLInputElement>
544-
): void => {
545-
const { value } = event.target;
546-
const percentage = parseInt(value, 10);
547-
if (isNaN(percentage)) {
548-
return;
549-
}
545+
private setInterfaceScale = (percentage: number) => {
550546
const interfaceScale = (percentage - 100) / 20;
551-
if (!isNaN(interfaceScale)) {
552-
this.setState({ interfaceScale });
553-
}
547+
548+
this.setState({ interfaceScale });
554549
};
555550

556551
protected verifyAfterUploadDidChange = (
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import * as React from '@theia/core/shared/react';
2+
import classnames from 'classnames';
3+
4+
interface SettingsStepInputProps {
5+
value: number;
6+
setSettingsStateValue: (value: number) => void;
7+
step: number;
8+
maxValue: number;
9+
minValue: number;
10+
classNames?: { [key: string]: string };
11+
}
12+
13+
const SettingsStepInput: React.FC<SettingsStepInputProps> = (
14+
props: SettingsStepInputProps
15+
) => {
16+
const { value, setSettingsStateValue, step, maxValue, minValue, classNames } =
17+
props;
18+
19+
const [stepUpDisabled, setStepUpDisabled] = React.useState(false);
20+
const [stepDownDisabled, setStepDownDisabled] = React.useState(false);
21+
22+
const onStepUp = (): void => {
23+
const valueRoundedToScale = Math.ceil(value / step) * step;
24+
const calculatedValue =
25+
valueRoundedToScale === value ? value + step : valueRoundedToScale;
26+
const newValue = limitValueByCondition(
27+
calculatedValue,
28+
maxValue,
29+
calculatedValue >= maxValue,
30+
disableStepUp
31+
);
32+
33+
setSettingsStateValue(newValue);
34+
};
35+
36+
const onStepDown = (): void => {
37+
const valueRoundedToScale = Math.floor(value / step) * step;
38+
const calculatedValue =
39+
valueRoundedToScale === value ? value - step : valueRoundedToScale;
40+
const newValue = limitValueByCondition(
41+
calculatedValue,
42+
minValue,
43+
calculatedValue <= minValue,
44+
disableStepDown
45+
);
46+
47+
setSettingsStateValue(newValue);
48+
};
49+
50+
const limitValueByCondition = (
51+
calculatedValue: number,
52+
limitedValue: number,
53+
condition: boolean,
54+
onConditionTrue: () => void,
55+
onConditionFalse = enableButtons
56+
): number => {
57+
if (condition) {
58+
onConditionTrue();
59+
return limitedValue;
60+
} else {
61+
onConditionFalse();
62+
return calculatedValue;
63+
}
64+
};
65+
66+
const enableButtons = (): void => {
67+
setStepUpDisabled(false);
68+
setStepDownDisabled(false);
69+
};
70+
71+
const disableStepUp = (): void => {
72+
setStepUpDisabled(true);
73+
};
74+
75+
const disableStepDown = (): void => {
76+
setStepDownDisabled(true);
77+
};
78+
79+
const onUserInput = (event: React.ChangeEvent<HTMLInputElement>): void => {
80+
const { value: eventValue } = event.target;
81+
82+
if (eventValue === '') {
83+
setSettingsStateValue(0);
84+
}
85+
86+
const number = Number(eventValue);
87+
88+
if (!isNaN(number) && number !== value) {
89+
let newValue;
90+
if (number > value) {
91+
newValue = limitValueByCondition(
92+
number,
93+
maxValue,
94+
number >= maxValue,
95+
disableStepUp
96+
);
97+
} else {
98+
newValue = limitValueByCondition(
99+
number,
100+
minValue,
101+
number <= minValue,
102+
disableStepDown
103+
);
104+
}
105+
106+
setSettingsStateValue(newValue);
107+
}
108+
};
109+
110+
// the component does not unmount when we close the settings dialog
111+
// in theia which necessitates the below useEffect
112+
React.useEffect(() => {
113+
if (value > minValue && value < maxValue) {
114+
enableButtons();
115+
}
116+
}, [value, minValue, maxValue]);
117+
118+
return (
119+
<div className="settings-step-input-container">
120+
<input
121+
className={classnames('settings-step-input-element', classNames?.input)}
122+
value={value.toString()}
123+
onChange={onUserInput}
124+
type="number"
125+
pattern="[0-9]+"
126+
/>
127+
<div className="settings-step-input-buttons-container">
128+
<button
129+
className="settings-step-input-button settings-step-input-up-button"
130+
disabled={stepUpDisabled}
131+
onClick={onStepUp}
132+
>
133+
&#9662;
134+
</button>
135+
<button
136+
className="settings-step-input-button"
137+
disabled={stepDownDisabled}
138+
onClick={onStepDown}
139+
>
140+
&#9662;
141+
</button>
142+
</div>
143+
</div>
144+
);
145+
};
146+
147+
export default SettingsStepInput;

‎arduino-ide-extension/src/browser/style/index.css‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
@import './fonts.css';
1919
@import './custom-codicon.css';
2020
@import './progress-bar.css';
21+
@import './settings-step-input.css';
2122

2223
.theia-input.warning:focus {
2324
outline-width: 1px;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
.settings-step-input-container {
2+
position: relative
3+
}
4+
5+
.settings-step-input-element::-webkit-inner-spin-button,
6+
.settings-step-input-element::-webkit-outer-spin-button {
7+
-webkit-appearance: none;
8+
margin: 0;
9+
}
10+
11+
.settings-step-input-buttons-container {
12+
display: none;
13+
flex-direction: column;
14+
position: absolute;
15+
right: 0px;
16+
top: 50%;
17+
transform: translate(0px, -50%);
18+
height: calc(100% - 4px);
19+
width: 14px;
20+
padding: 2px;
21+
background: white;
22+
}
23+
24+
.settings-step-input-container:hover > .settings-step-input-buttons-container {
25+
display: flex;
26+
}
27+
28+
.settings-step-input-up-button {
29+
transform: rotate(-180deg);
30+
}
31+
32+
.settings-step-input-button {
33+
border: none;
34+
border-radius: 0;
35+
height: 50%;
36+
width: 1;
37+
display: flex;
38+
align-items: center;
39+
justify-content: center;
40+
user-select: none;
41+
cursor: pointer;
42+
line-height: 12px;
43+
}
44+
45+
.settings-step-input-button:hover {
46+
background: rgba(128, 128, 128, 0.8);
47+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /