Skip to content

Commit d6c7b5a

Browse files
elektronikworkshopadiazulay
authored andcommitted
New classes which will improve the device settings management and event handling. To be integrated with one of the next commits.
1 parent d712a94 commit d6c7b5a

File tree

1 file changed

+234
-0
lines changed

1 file changed

+234
-0
lines changed

src/deviceSettings.ts

+234
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
import * as fs from "fs";
2+
import * as path from "path";
3+
import * as vscode from "vscode";
4+
5+
import * as constants from "./common/constants";
6+
import * as util from "./common/util";
7+
import * as logger from "./logger/logger";
8+
9+
/**
10+
* Generic class which provides monitoring of a specific settings value.
11+
* If the value is modified a flag is set and an event is emitted.
12+
*
13+
* Usually you want to specialize the setter for any given value type
14+
* to prevent invalid or badly formatted values to enter your settings.
15+
*/
16+
class Setting<T> {
17+
/** The setting's default value. */
18+
public readonly default: T;
19+
/** The actual value of the setting. */
20+
private _value: T | undefined;
21+
/** Indicates if the value was changed since the last call to this.commit(). */
22+
private _modified: boolean;
23+
/** Event emitter which fires when the value is changed. */
24+
private _emitter: vscode.EventEmitter<T> = new vscode.EventEmitter<T>();
25+
26+
constructor(defaultValue?: T) {
27+
this.default = defaultValue;
28+
this._value = this.default;
29+
}
30+
/**
31+
* Value-setter - sets the value.
32+
* If modified, the modified flag is set and the modified event is
33+
* fired.
34+
*/
35+
public set value(value: T | undefined) {
36+
if (value !== this._value) {
37+
this._value = value;
38+
this._modified = true;
39+
this._emitter.fire(this._value);
40+
}
41+
}
42+
/** Value-getter - returns the internal value. */
43+
public get value() {
44+
return this._value;
45+
}
46+
/**
47+
* Returns true, if the internal value has been modified.
48+
* To clear the modified flag call commit().
49+
*/
50+
public get modified() {
51+
return this._modified;
52+
}
53+
/** Returns the modified-event emitter. */
54+
public get emitter() {
55+
return this._emitter;
56+
}
57+
/**
58+
* Returns the internal value to its default value.
59+
* If the default value is different from the previous value,
60+
* it triggers the modified event and the modified flag is set.
61+
*/
62+
public reset() {
63+
this.value = this.default;
64+
}
65+
/** Reset the modified flag (if you know what you're doing) */
66+
public commit() {
67+
this._modified = false;
68+
}
69+
}
70+
71+
/**
72+
* String specialization of the Setting class.
73+
*/
74+
class StrSetting extends Setting<string> {
75+
/**
76+
* When we override setter (below) we have to override getter as well
77+
* (see JS language specs).
78+
*/
79+
public get value() {
80+
return super.value;
81+
}
82+
/**
83+
* Set string value. Anything else than a string will set the value to
84+
* its default value (undefined). White spaces at the front and back are
85+
* trimmed before setting the value.
86+
* If the setting's value is changed during this operation, the base
87+
* class' event emitter will fire and the modified flag will be set.
88+
*/
89+
public set value(value: string) {
90+
if (typeof value !== "string") {
91+
value = this.default;
92+
} else {
93+
value = value.trim();
94+
}
95+
super.value = value;
96+
}
97+
}
98+
99+
/**
100+
* This class encapsulates all device/project specific settings and
101+
* provides common operations on them.
102+
*/
103+
export class DeviceSettings {
104+
public port = new StrSetting();
105+
public board = new StrSetting();
106+
public sketch = new StrSetting();
107+
public output = new StrSetting();
108+
public debugger = new StrSetting();
109+
public disableIntelliSenseAutoGen = new StrSetting();
110+
public configuration = new StrSetting();
111+
public prebuild = new StrSetting();
112+
public programmer = new StrSetting();
113+
114+
/**
115+
* @returns true if any of the settings values has its modified flag
116+
* set.
117+
*/
118+
public get modified() {
119+
return this.port.modified ||
120+
this.board.modified ||
121+
this.sketch.modified ||
122+
this.output.modified ||
123+
this.debugger.modified ||
124+
this.disableIntelliSenseAutoGen.modified ||
125+
this.configuration.modified ||
126+
this.prebuild.modified ||
127+
this.programmer.modified;
128+
}
129+
/**
130+
* Clear modified flags of all settings values.
131+
*/
132+
public commit() {
133+
this.port.commit();
134+
this.board.commit();
135+
this.sketch.commit();
136+
this.output.commit();
137+
this.debugger.commit();
138+
this.disableIntelliSenseAutoGen.commit();
139+
this.configuration.commit();
140+
this.prebuild.commit();
141+
this.programmer.commit();
142+
}
143+
/**
144+
* Resets all settings values to their default values.
145+
* @param commit If true clear the modified flags after all values are
146+
* reset.
147+
*/
148+
public reset(commit: boolean = true) {
149+
this.port.reset();
150+
this.board.reset();
151+
this.sketch.reset();
152+
this.output.reset();
153+
this.debugger.reset();
154+
this.disableIntelliSenseAutoGen.reset();
155+
this.configuration.reset();
156+
this.prebuild.reset();
157+
this.programmer.reset();
158+
if (commit) {
159+
this.commit();
160+
}
161+
}
162+
/**
163+
* Load settings values from the given file.
164+
* If a value is changed through this operation, its event emitter will
165+
* fire.
166+
* @param file Path to the file the settings should be loaded from.
167+
* @param commit If true reset the modified flags after all values are read.
168+
* @returns true if the settings are loaded successfully.
169+
*/
170+
public load(file: string, commit: boolean = true) {
171+
const settings = util.tryParseJSON(fs.readFileSync(file, "utf8"));
172+
if (settings) {
173+
this.port.value = settings.port;
174+
this.board.value = settings.board;
175+
this.sketch.value = settings.sketch;
176+
this.configuration.value = settings.configuration;
177+
this.output.value = settings.output;
178+
this.debugger.value = settings.debugger;
179+
this.disableIntelliSenseAutoGen.value = settings.disableIntelliSenseAutoGen;
180+
this.prebuild.value = settings.prebuild;
181+
this.programmer.value = settings.programmer;
182+
if (commit) {
183+
this.commit();
184+
}
185+
return true;
186+
} else {
187+
logger.notifyUserError("arduinoFileError",
188+
new Error(constants.messages.ARDUINO_FILE_ERROR));
189+
return false;
190+
}
191+
}
192+
/**
193+
* Writes the settings to the given file if there are modified
194+
* values. The modification flags are reset (commit()) on successful write.
195+
* On write failure the modification flags are left unmodified.
196+
* @param file Path to file the JSON representation of the settings should
197+
* written to. If either the folder or the file does not exist they are
198+
* created.
199+
* @returns true on succes, false on write failure.
200+
*/
201+
public save(file: string) {
202+
203+
if (!this.modified) {
204+
return true;
205+
}
206+
207+
let settings: any = {};
208+
if (util.fileExistsSync(file)) {
209+
settings = util.tryParseJSON(fs.readFileSync(file, "utf8"));
210+
}
211+
if (!settings) {
212+
logger.notifyUserError(
213+
"arduinoFileError",
214+
new Error(constants.messages.ARDUINO_FILE_ERROR));
215+
return false;
216+
}
217+
218+
settings.sketch = this.sketch.value;
219+
settings.port = this.port.value;
220+
settings.board = this.board.value;
221+
settings.output = this.output.value;
222+
settings.debugger = this.debugger.value;
223+
settings.disableIntelliSenseAutoGen = this.disableIntelliSenseAutoGen.value;
224+
settings.configuration = this.configuration.value;
225+
settings.programmer = this.programmer.value;
226+
227+
util.mkdirRecursivelySync(path.dirname(file));
228+
fs.writeFileSync(file, JSON.stringify(settings, undefined, 4));
229+
230+
this.commit();
231+
232+
return true;
233+
}
234+
}

0 commit comments

Comments
 (0)