aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/SliderBox.tsx
blob: cb2526769def36f10814eaf93ac2cc60c310a0f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import { library } from '@fortawesome/fontawesome-svg-core';
import { faEdit } from '@fortawesome/free-regular-svg-icons';
import { runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Handles, Rail, Slider, Ticks, Tracks } from 'react-compound-slider';
import { documentSchema } from '../../../new_fields/documentSchemas';
import { createSchema, makeInterface } from '../../../new_fields/Schema';
import { ScriptField } from '../../../new_fields/ScriptField';
import { Cast, NumCast, StrCast } from '../../../new_fields/Types';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { ViewBoxBaseComponent } from '../DocComponent';
import { ScriptBox } from '../ScriptBox';
import { FieldView, FieldViewProps } from './FieldView';
import { Handle, Tick, TooltipRail, Track } from './SliderBox-components';
import './SliderBox.scss';


library.add(faEdit as any);

const SliderSchema = createSchema({
    _sliderMin: "number",
    _sliderMax: "number",
    _sliderMinThumb: "number",
    _sliderMaxThumb: "number",
});

type SliderDocument = makeInterface<[typeof SliderSchema, typeof documentSchema]>;
const SliderDocument = makeInterface(SliderSchema, documentSchema);

@observer
export class SliderBox extends ViewBoxBaseComponent<FieldViewProps, SliderDocument>(SliderDocument) {
    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(SliderBox, fieldKey); }

    get minThumbKey() { return this.fieldKey + "-minThumb"; }
    get maxThumbKey() { return this.fieldKey + "-maxThumb"; }
    get minKey() { return this.fieldKey + "-min"; }
    get maxKey() { return this.fieldKey + "-max"; }
    specificContextMenu = (e: React.MouseEvent): void => {
        const funcs: ContextMenuProps[] = [];
        funcs.push({ description: "Edit Thumb Change Script", icon: "edit", event: (obj: any) => ScriptBox.EditButtonScript("On Thumb Change ...", this.props.Document, "onThumbChange", obj.x, obj.y) });
        ContextMenu.Instance.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" });
    }
    onChange = (values: readonly number[]) => runInAction(() => {
        this.dataDoc[this.minThumbKey] = values[0];
        this.dataDoc[this.maxThumbKey] = values[1];
        Cast(this.layoutDoc.onThumbChanged, ScriptField, null)?.script.run({ self: this.rootDoc, range: values, this: this.layoutDoc });
    })

    render() {
        const domain = [NumCast(this.layoutDoc[this.minKey]), NumCast(this.layoutDoc[this.maxKey])];
        const defaultValues = [NumCast(this.dataDoc[this.minThumbKey]), NumCast(this.dataDoc[this.maxThumbKey])];
        return domain[1] <= domain[0] ? (null) : (
            <div className="sliderBox-outerDiv" onContextMenu={this.specificContextMenu} onPointerDown={e => e.stopPropagation()}
                style={{ boxShadow: this.layoutDoc.opacity === 0 ? undefined : StrCast(this.layoutDoc.boxShadow, "") }}>
                <div className="sliderBox-mainButton" onContextMenu={this.specificContextMenu} style={{
                    background: StrCast(this.layoutDoc.backgroundColor), color: StrCast(this.layoutDoc.color, "black"),
                    fontSize: NumCast(this.layoutDoc._fontSize), letterSpacing: StrCast(this.layoutDoc.letterSpacing)
                }} >
                    <Slider
                        mode={2}
                        step={1}
                        domain={domain}
                        rootStyle={{ position: "relative", width: "100%" }}
                        onChange={this.onChange}
                        values={defaultValues}
                    >

                        <Rail>{railProps => <TooltipRail {...railProps} />}</Rail>
                        <Handles>
                            {({ handles, activeHandleID, getHandleProps }) => (
                                <div className="slider-handles">
                                    {handles.map((handle, i) => {
                                        const value = i === 0 ? defaultValues[0] : defaultValues[1];
                                        return (
                                            <div title={String(value)}>
                                                <Handle
                                                    key={handle.id}
                                                    handle={handle}
                                                    domain={domain}
                                                    isActive={handle.id === activeHandleID}
                                                    getHandleProps={getHandleProps}
                                                />
                                            </div>
                                        );
                                    })}
                                </div>
                            )}
                        </Handles>
                        <Tracks left={false} right={false}>
                            {({ tracks, getTrackProps }) => (
                                <div className="slider-tracks">
                                    {tracks.map(({ id, source, target }) => (
                                        <Track
                                            key={id}
                                            source={source}
                                            target={target}
                                            disabled={false}
                                            getTrackProps={getTrackProps}
                                        />
                                    ))}
                                </div>
                            )}
                        </Tracks>
                        <Ticks count={5}>
                            {({ ticks }) => (
                                <div className="slider-tracks">
                                    {ticks.map((tick) => (
                                        <Tick
                                            key={tick.id}
                                            tick={tick}
                                            count={ticks.length}
                                            format={(val: number) => val.toString()}
                                        />
                                    ))}
                                </div>
                            )}
                        </Ticks>
                    </Slider>
                </div>
            </div>
        );
    }
}