From 328f2ab58baba2ea5ee6b3fae14b3a9d2103bf08 Mon Sep 17 00:00:00 2001 From: Christopher Serr Date: Tue, 4 Jul 2017 23:42:43 +0200 Subject: [PATCH] Implement Component Settings --- css/livesplit.css | 51 ++++++- livesplit-core | 2 +- src/components/LayoutEditor.tsx | 237 +++++++++++++++++++++++++------- src/components/RunEditor.tsx | 6 +- src/livesplit.ts | 77 +++++++++++ 5 files changed, 315 insertions(+), 58 deletions(-) diff --git a/css/livesplit.css b/css/livesplit.css index a0e9c02..5bf0a64 100644 --- a/css/livesplit.css +++ b/css/livesplit.css @@ -78,6 +78,13 @@ button.toggle-right { text-shadow: 2px 2px 2px rgba(0, 0, 0, 0.5); margin: 10px; margin-bottom: 5px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: default; } .previous-segment, @@ -606,7 +613,7 @@ input.name { } -form > div > input { +input { font-size: 15px; border: none; border-bottom: 1px solid hsl(0, 0%, 25%); @@ -616,11 +623,16 @@ form > div > input { font-family: 'fira', sans-serif; } +input.number { + text-align: right; + font-weight: bold; + font-family: 'Roboto', sans-serif; +} + form > div > input:not(.name) { text-align: right; } - .timing-selection > button { font-size: 15px; height: 30px; @@ -656,7 +668,7 @@ svg { .layout-editor { margin: 20px; - width: 300px; + width: 445px; display: inline-flex; } @@ -700,6 +712,10 @@ svg { margin-left: 10px; } +.layout-editor-component { + cursor: pointer; +} + .react-contextmenu-item--divider { margin-bottom: 3px; padding: 2px 0; @@ -710,3 +726,32 @@ svg { .react-contextmenu-item--selected { background: rgba(0, 67, 255, 0.26); } + +.component-settings { + margin-left: 20px; + width: 500px; +} + +.component-settings > tbody > tr { + height: 30px; +} + +.component-settings > tbody > tr > td:nth-child(1) { + width: 250px; +} + +.component-settings > tbody > tr > td:nth-child(2) > input, +.component-settings > tbody > tr > td:nth-child(2) > span, +.component-settings > tbody > tr > td:nth-child(2) > select { + width: 100%; +} + +select { + background: hsla(0, 0%, 9%, 1); + font-size: 15px; + border: none; + border-bottom: 1px solid hsl(0, 0%, 25%); + color: white; + text-overflow: ellipsis; + font-family: 'fira', sans-serif; +} diff --git a/livesplit-core b/livesplit-core index 1566f24..f4b9154 160000 --- a/livesplit-core +++ b/livesplit-core @@ -1 +1 @@ -Subproject commit 1566f241a6785582b7ecbd5f590408155cd06199 +Subproject commit f4b91547a16577270405dafc1e7c743de6bfc2d1 diff --git a/src/components/LayoutEditor.tsx b/src/components/LayoutEditor.tsx index 566d212..6b3f199 100644 --- a/src/components/LayoutEditor.tsx +++ b/src/components/LayoutEditor.tsx @@ -91,60 +91,195 @@ export class LayoutEditor extends React.Component { } }; + let settingsRows: any[] = []; + + this.state.editor.settings_description.fields.forEach((field, valueIndex) => { + var component; + let value: any = field.value; + switch (Object.keys(value)[0]) { + case "Bool": { + component = + { + this.props.editor.setComponentSettingsBool(valueIndex, e.target.checked); + this.update(); + }} + />; + break; + } + case "UInt": { + component = + { + this.props.editor.setComponentSettingsUint(valueIndex, e.target.valueAsNumber); + this.update(); + }} + />; + break; + } + case "Int": { + component = + { + this.props.editor.setComponentSettingsInt(valueIndex, e.target.valueAsNumber); + this.update(); + }} + />; + break; + } + case "String": { + component = + { + this.props.editor.setComponentSettingsString(valueIndex, e.target.value); + this.update(); + }} + />; + break; + } + case "OptionalString": { + let children = [ + { + if (e.target.checked) { + this.props.editor.setComponentSettingsOptionalString(valueIndex, ""); + } else { + this.props.editor.setComponentSettingsOptionalStringToEmpty(valueIndex); + } + this.update(); + }} + /> + ]; + + if (value.OptionalString != null) { + children.push( + { + this.props.editor.setComponentSettingsOptionalString(valueIndex, e.target.value); + this.update(); + }} + /> + ); + } + + component = + + {children} + ; + break; + } + case "Float": { + component = + { + this.props.editor.setComponentSettingsFloat(valueIndex, e.target.valueAsNumber); + this.update(); + }} + />; + break; + } + case "Accuracy": { + component = + ; + break; + } + } + settingsRows.push( + + {field.text} + {component} + + ); + }); + return ( -
-
- contextTrigger = c}> - - - - this.addComponent(LiveSplit.CurrentComparisonComponent)}> - Current Comparison - - this.addComponent(LiveSplit.CurrentPaceComponent)}> - Current Pace - - this.addComponent(LiveSplit.DeltaComponent)}> - Delta - - this.addComponent(LiveSplit.DetailedTimerComponent)}> - Detailed Timer - - this.addComponent(LiveSplit.GraphComponent)}> - Graph - - this.addComponent(LiveSplit.PossibleTimeSaveComponent)}> - Possible Time Save - - this.addComponent(LiveSplit.PreviousSegmentComponent)}> - Previous Segment - - this.addComponent(LiveSplit.SplitsComponent)}> - Splits - - this.addComponent(LiveSplit.SumOfBestComponent)}> - Sum of Best - - this.addComponent(LiveSplit.TextComponent)}> - Text - - this.addComponent(LiveSplit.TimerComponent)}> - Timer - - this.addComponent(LiveSplit.TitleComponent)}> - Title - - this.addComponent(LiveSplit.TotalPlaytimeComponent)}> - Total Playtime - - - - - +
+
+
+ contextTrigger = c}> + + + + this.addComponent(LiveSplit.CurrentComparisonComponent)}> + Current Comparison + + this.addComponent(LiveSplit.CurrentPaceComponent)}> + Current Pace + + this.addComponent(LiveSplit.DeltaComponent)}> + Delta + + this.addComponent(LiveSplit.DetailedTimerComponent)}> + Detailed Timer + + this.addComponent(LiveSplit.GraphComponent)}> + Graph + + this.addComponent(LiveSplit.PossibleTimeSaveComponent)}> + Possible Time Save + + this.addComponent(LiveSplit.PreviousSegmentComponent)}> + Previous Segment + + this.addComponent(LiveSplit.SplitsComponent)}> + Splits + + this.addComponent(LiveSplit.SumOfBestComponent)}> + Sum of Best + + this.addComponent(LiveSplit.TextComponent)}> + Text + + this.addComponent(LiveSplit.TimerComponent)}> + Timer + + this.addComponent(LiveSplit.TitleComponent)}> + Title + + this.addComponent(LiveSplit.TotalPlaytimeComponent)}> + Total Playtime + + + + + +
+ + + {components} + +
- +
- {components} + {settingsRows}
diff --git a/src/components/RunEditor.tsx b/src/components/RunEditor.tsx index b06801e..24a2849 100644 --- a/src/components/RunEditor.tsx +++ b/src/components/RunEditor.tsx @@ -276,11 +276,11 @@ export class RunEditor extends React.Component { this.state.editor.segments.map((s: any, i: number) =>
this.changeSegmentSelection(e, i)}>
this.focusSegment(i)} onChange={(e) => this.handleSegmentNameChange(e)} />
-
this.focusSegment(i)} onChange={(e) => this.handleSplitTimeChange(e)} onBlur={(e) => this.handleSplitTimeBlur(e)} />
-
this.focusSegment(i)} onChange={(e) => this.handleSegmentTimeChange(e)} onBlur={(e) => this.handleSegmentTimeBlur(e)} />
-
this.focusSegment(i)} onChange={(e) => this.handleBestSegmentTimeChange(e)} onBlur={(e) => this.handleBestSegmentTimeBlur(e)} />
) diff --git a/src/livesplit.ts b/src/livesplit.ts index 3f32c62..6a5c1a9 100644 --- a/src/livesplit.ts +++ b/src/livesplit.ts @@ -121,6 +121,7 @@ export interface LayoutEditorStateJson { components: string[], buttons: LayoutEditorButtonsJson, selected_component: number, + settings_description: SettingsDescriptionJson, } export interface LayoutEditorButtonsJson { @@ -129,6 +130,26 @@ export interface LayoutEditorButtonsJson { can_move_down: boolean, } +export interface SettingsDescriptionJson { + fields: SettingsDescriptionFieldJson[], +} + +export interface SettingsDescriptionFieldJson { + text: string, + value: SettingsDescriptionValueJson, +} + +export type SettingsDescriptionValueJson = + { Bool: boolean } | + { UInt: number } | + { Int: number } | + { String: string } | + { OptionalString: string } | + { Float: number } | + { Accuracy: AccuracyJson }; + +export type AccuracyJson = "Seconds" | "Tenths" | "Hundredths"; + export interface RunEditorStateJson { icon_change?: string, game: string, @@ -256,6 +277,14 @@ liveSplitCoreNative.LayoutEditor_remove_component = emscriptenModule.cwrap('Layo liveSplitCoreNative.LayoutEditor_move_component_up = emscriptenModule.cwrap('LayoutEditor_move_component_up', null, ["number"]); liveSplitCoreNative.LayoutEditor_move_component_down = emscriptenModule.cwrap('LayoutEditor_move_component_down', null, ["number"]); liveSplitCoreNative.LayoutEditor_move_component = emscriptenModule.cwrap('LayoutEditor_move_component', null, ["number", "number"]); +liveSplitCoreNative.LayoutEditor_set_component_settings_bool = emscriptenModule.cwrap('LayoutEditor_set_component_settings_bool', null, ["number", "number", "number"]); +liveSplitCoreNative.LayoutEditor_set_component_settings_uint = emscriptenModule.cwrap('LayoutEditor_set_component_settings_uint', null, ["number", "number", "number"]); +liveSplitCoreNative.LayoutEditor_set_component_settings_int = emscriptenModule.cwrap('LayoutEditor_set_component_settings_int', null, ["number", "number", "number"]); +liveSplitCoreNative.LayoutEditor_set_component_settings_string = emscriptenModule.cwrap('LayoutEditor_set_component_settings_string', null, ["number", "number", "string"]); +liveSplitCoreNative.LayoutEditor_set_component_settings_optional_string = emscriptenModule.cwrap('LayoutEditor_set_component_settings_optional_string', null, ["number", "number", "string"]); +liveSplitCoreNative.LayoutEditor_set_component_settings_optional_string_to_empty = emscriptenModule.cwrap('LayoutEditor_set_component_settings_optional_string_to_empty', null, ["number", "number"]); +liveSplitCoreNative.LayoutEditor_set_component_settings_float = emscriptenModule.cwrap('LayoutEditor_set_component_settings_float', null, ["number", "number", "number"]); +liveSplitCoreNative.LayoutEditor_set_component_settings_accuracy = emscriptenModule.cwrap('LayoutEditor_set_component_settings_accuracy', null, ["number", "number", "string"]); liveSplitCoreNative.PossibleTimeSaveComponent_new = emscriptenModule.cwrap('PossibleTimeSaveComponent_new', "number", []); liveSplitCoreNative.PossibleTimeSaveComponent_drop = emscriptenModule.cwrap('PossibleTimeSaveComponent_drop', null, ["number"]); liveSplitCoreNative.PossibleTimeSaveComponent_into_generic = emscriptenModule.cwrap('PossibleTimeSaveComponent_into_generic', "number", ["number"]); @@ -1449,6 +1478,54 @@ export class LayoutEditorRefMut extends LayoutEditorRef { } liveSplitCoreNative.LayoutEditor_move_component(this.ptr, dstIndex); } + setComponentSettingsBool(index: number, value: boolean) { + if (this.ptr == 0) { + throw "this is disposed"; + } + liveSplitCoreNative.LayoutEditor_set_component_settings_bool(this.ptr, index, value ? 1 : 0); + } + setComponentSettingsUint(index: number, value: number) { + if (this.ptr == 0) { + throw "this is disposed"; + } + liveSplitCoreNative.LayoutEditor_set_component_settings_uint(this.ptr, index, value); + } + setComponentSettingsInt(index: number, value: number) { + if (this.ptr == 0) { + throw "this is disposed"; + } + liveSplitCoreNative.LayoutEditor_set_component_settings_int(this.ptr, index, value); + } + setComponentSettingsString(index: number, value: string) { + if (this.ptr == 0) { + throw "this is disposed"; + } + liveSplitCoreNative.LayoutEditor_set_component_settings_string(this.ptr, index, value); + } + setComponentSettingsOptionalString(index: number, value: string) { + if (this.ptr == 0) { + throw "this is disposed"; + } + liveSplitCoreNative.LayoutEditor_set_component_settings_optional_string(this.ptr, index, value); + } + setComponentSettingsOptionalStringToEmpty(index: number) { + if (this.ptr == 0) { + throw "this is disposed"; + } + liveSplitCoreNative.LayoutEditor_set_component_settings_optional_string_to_empty(this.ptr, index); + } + setComponentSettingsFloat(index: number, value: number) { + if (this.ptr == 0) { + throw "this is disposed"; + } + liveSplitCoreNative.LayoutEditor_set_component_settings_float(this.ptr, index, value); + } + setComponentSettingsAccuracy(index: number, value: string) { + if (this.ptr == 0) { + throw "this is disposed"; + } + liveSplitCoreNative.LayoutEditor_set_component_settings_accuracy(this.ptr, index, value); + } } export class LayoutEditor extends LayoutEditorRefMut {