Implement Component Settings

This commit is contained in:
Christopher Serr
2017-07-04 23:42:43 +02:00
parent 8303d4aaf3
commit 328f2ab58b
5 changed files with 315 additions and 58 deletions
+48 -3
View File
@@ -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;
}
+186 -51
View File
@@ -91,60 +91,195 @@ export class LayoutEditor extends React.Component<Props, State> {
}
};
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 =
<input
type="checkbox"
checked={value.Bool}
onChange={(e) => {
this.props.editor.setComponentSettingsBool(valueIndex, e.target.checked);
this.update();
}}
/>;
break;
}
case "UInt": {
component =
<input
type="number"
className="number"
value={value.UInt}
min="0"
onChange={(e) => {
this.props.editor.setComponentSettingsUint(valueIndex, e.target.valueAsNumber);
this.update();
}}
/>;
break;
}
case "Int": {
component =
<input
type="number"
className="number"
value={value.Int}
onChange={(e) => {
this.props.editor.setComponentSettingsInt(valueIndex, e.target.valueAsNumber);
this.update();
}}
/>;
break;
}
case "String": {
component =
<input
value={value.String}
onChange={(e) => {
this.props.editor.setComponentSettingsString(valueIndex, e.target.value);
this.update();
}}
/>;
break;
}
case "OptionalString": {
let children = [
<input
type="checkbox"
checked={value.OptionalString != null}
onChange={(e) => {
if (e.target.checked) {
this.props.editor.setComponentSettingsOptionalString(valueIndex, "");
} else {
this.props.editor.setComponentSettingsOptionalStringToEmpty(valueIndex);
}
this.update();
}}
/>
];
if (value.OptionalString != null) {
children.push(
<input
value={value.OptionalString}
disabled={value.OptionalString == null}
onChange={(e) => {
this.props.editor.setComponentSettingsOptionalString(valueIndex, e.target.value);
this.update();
}}
/>
);
}
component =
<span>
{children}
</span>;
break;
}
case "Float": {
component =
<input
type="number"
value={value.Float}
className="number"
onChange={(e) => {
this.props.editor.setComponentSettingsFloat(valueIndex, e.target.valueAsNumber);
this.update();
}}
/>;
break;
}
case "Accuracy": {
component =
<select
value={value.Accuracy}
onChange={(e) => {
this.props.editor.setComponentSettingsAccuracy(valueIndex, e.target.value);
this.update();
}}
>
<option value="Seconds">Seconds</option>
<option value="Tenths">Tenths</option>
<option value="Hundredths">Hundredths</option>
</select>;
break;
}
}
settingsRows.push(
<tr>
<td>{field.text}</td>
<td>{component}</td>
</tr>
);
});
return (
<div className="layout-editor">
<div className="btn-group">
<ContextMenuTrigger id="add-button-context-menu" ref={c => contextTrigger = c}>
<button onClick={toggleMenu}><i className="fa fa-plus" aria-hidden="true"></i></button>
</ContextMenuTrigger>
<ContextMenu id="add-button-context-menu">
<MenuItem onClick={(e) => this.addComponent(LiveSplit.CurrentComparisonComponent)}>
Current Comparison
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.CurrentPaceComponent)}>
Current Pace
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.DeltaComponent)}>
Delta
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.DetailedTimerComponent)}>
Detailed Timer
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.GraphComponent)}>
Graph
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.PossibleTimeSaveComponent)}>
Possible Time Save
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.PreviousSegmentComponent)}>
Previous Segment
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.SplitsComponent)}>
Splits
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.SumOfBestComponent)}>
Sum of Best
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.TextComponent)}>
Text
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.TimerComponent)}>
Timer
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.TitleComponent)}>
Title
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.TotalPlaytimeComponent)}>
Total Playtime
</MenuItem>
</ContextMenu>
<button onClick={(e) => this.removeComponent()}><i className="fa fa-minus" aria-hidden="true"></i></button>
<button onClick={(e) => this.moveComponentUp()}><i className="fa fa-arrow-up" aria-hidden="true"></i></button>
<button onClick={(e) => this.moveComponentDown()}><i className="fa fa-arrow-down" aria-hidden="true"></i></button>
<div>
<div className="layout-editor">
<div className="btn-group">
<ContextMenuTrigger id="add-button-context-menu" ref={c => contextTrigger = c}>
<button onClick={toggleMenu}><i className="fa fa-plus" aria-hidden="true"></i></button>
</ContextMenuTrigger>
<ContextMenu id="add-button-context-menu">
<MenuItem onClick={(e) => this.addComponent(LiveSplit.CurrentComparisonComponent)}>
Current Comparison
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.CurrentPaceComponent)}>
Current Pace
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.DeltaComponent)}>
Delta
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.DetailedTimerComponent)}>
Detailed Timer
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.GraphComponent)}>
Graph
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.PossibleTimeSaveComponent)}>
Possible Time Save
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.PreviousSegmentComponent)}>
Previous Segment
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.SplitsComponent)}>
Splits
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.SumOfBestComponent)}>
Sum of Best
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.TextComponent)}>
Text
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.TimerComponent)}>
Timer
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.TitleComponent)}>
Title
</MenuItem>
<MenuItem onClick={(e) => this.addComponent(LiveSplit.TotalPlaytimeComponent)}>
Total Playtime
</MenuItem>
</ContextMenu>
<button onClick={(e) => this.removeComponent()}><i className="fa fa-minus" aria-hidden="true"></i></button>
<button onClick={(e) => this.moveComponentUp()}><i className="fa fa-arrow-up" aria-hidden="true"></i></button>
<button onClick={(e) => this.moveComponentDown()}><i className="fa fa-arrow-down" aria-hidden="true"></i></button>
</div>
<table className="layout-editor-component-list table">
<tbody className="table-body">
{components}
</tbody>
</table>
</div>
<table className="layout-editor-component-list table">
<table className="component-settings table">
<tbody className="table-body">
{components}
{settingsRows}
</tbody>
</table>
</div>
+3 -3
View File
@@ -276,11 +276,11 @@ export class RunEditor extends React.Component<Props, State> {
this.state.editor.segments.map((s: any, i: number) =>
<form key={i.toString()} className={(s.selected == "Selected" || s.selected == "CurrentRow") ? "selected" : ""} onClick={(e) => this.changeSegmentSelection(e, i)}>
<div><input className="name" type="text" value={s.name} onFocus={(e) => this.focusSegment(i)} onChange={(e) => this.handleSegmentNameChange(e)} /></div>
<div><input className={this.state.rowState.index != i || this.state.rowState.splitTimeIsValid ? "" : "invalid"}
<div><input className={this.state.rowState.index != i || this.state.rowState.splitTimeIsValid ? "number" : "number invalid"}
type="text" value={s.split_time} onFocus={(e) => this.focusSegment(i)} onChange={(e) => this.handleSplitTimeChange(e)} onBlur={(e) => this.handleSplitTimeBlur(e)} /></div>
<div><input className={this.state.rowState.index != i || this.state.rowState.segmentTimeIsValid ? "" : "invalid"}
<div><input className={this.state.rowState.index != i || this.state.rowState.segmentTimeIsValid ? "number" : "number invalid"}
type="text" value={s.segment_time} onFocus={(e) => this.focusSegment(i)} onChange={(e) => this.handleSegmentTimeChange(e)} onBlur={(e) => this.handleSegmentTimeBlur(e)} /></div>
<div><input className={this.state.rowState.index != i || this.state.rowState.bestSegmentTimeIsValid ? "" : "invalid"}
<div><input className={this.state.rowState.index != i || this.state.rowState.bestSegmentTimeIsValid ? "number" : "number invalid"}
type="text" value={s.best_segment_time} onFocus={(e) => this.focusSegment(i)} onChange={(e) => this.handleBestSegmentTimeChange(e)} onBlur={(e) => this.handleBestSegmentTimeBlur(e)} /></div>
</form>
)
+77
View File
@@ -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 {