1/*
2 * Copyright (c) 2016-2021 Meltytech, LLC
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18import QtQuick 2.12
19import QtQuick.Controls 2.12
20import QtQuick.Layouts 1.12
21import Shotcut.Controls 1.0 as Shotcut
22
23Item {
24    width: 200
25    height: 50
26    property bool blockUpdate: true
27    property double startValue: 1.0
28    property double middleValue: 1.0
29    property double endValue: 1.0
30
31    Component.onCompleted: {
32        if (filter.isNew) {
33            // Set default parameter values
34            filter.set('alpha', 1.0)
35            filter.set('opacity', 1.0)
36            filter.savePreset(preset.parameters)
37        } else {
38            middleValue = filter.getDouble('opacity', filter.animateIn)
39            if (filter.animateIn > 0)
40                startValue = filter.getDouble('opacity', 0)
41            if (filter.animateOut > 0)
42                endValue = filter.getDouble('opacity', filter.duration - 1)
43        }
44        setControls()
45    }
46
47    Connections {
48        target: filter
49        onInChanged: updateFilter(null)
50        onOutChanged: updateFilter(null)
51        onAnimateInChanged: updateFilter(null)
52        onAnimateOutChanged: updateFilter(null)
53    }
54
55    Connections {
56        target: producer
57        onPositionChanged: {
58            if (filter.animateIn > 0 || filter.animateOut > 0) {
59                setControls()
60            } else {
61                blockUpdate = true
62                brightnessSlider.value = filter.getDouble('opacity', getPosition()) * 100.0
63                blockUpdate = false
64                brightnessSlider.enabled = true
65            }
66        }
67    }
68
69    function getPosition() {
70        return Math.max(producer.position - (filter.in - producer.in), 0)
71    }
72
73    function setControls() {
74        var position = getPosition()
75        blockUpdate = true
76        brightnessSlider.value = filter.getDouble('opacity', position) * 100.0
77        brightnessKeyframesButton.checked = filter.keyframeCount('opacity') > 0 && filter.animateIn <= 0 && filter.animateOut <= 0
78        blockUpdate = false
79        brightnessSlider.enabled = position <= 0 || (position >= (filter.animateIn - 1) && position <= (filter.duration - filter.animateOut)) || position >= (filter.duration - 1)
80    }
81
82    function updateFilter(position) {
83        if (blockUpdate) return
84        var value = brightnessSlider.value / 100.0
85
86        if (position !== null) {
87            if (position <= 0 && filter.animateIn > 0)
88                startValue = value
89            else if (position >= filter.duration - 1 && filter.animateOut > 0)
90                endValue = value
91            else
92                middleValue = value
93        }
94
95        if (filter.animateIn > 0 || filter.animateOut > 0) {
96            filter.resetProperty('opacity')
97            brightnessKeyframesButton.checked = false
98            if (filter.animateIn > 0) {
99                filter.set('opacity', startValue, 0)
100                filter.set('opacity', middleValue, filter.animateIn - 1)
101            }
102            if (filter.animateOut > 0) {
103                filter.set('opacity', middleValue, filter.duration - filter.animateOut)
104                filter.set('opacity', endValue, filter.duration - 1)
105            }
106        } else if (!brightnessKeyframesButton.checked) {
107            filter.resetProperty('opacity')
108            filter.set('opacity', middleValue)
109        } else if (position !== null) {
110            filter.set('opacity', value, position)
111        }
112    }
113
114    GridLayout {
115        columns: 4
116        anchors.fill: parent
117        anchors.margins: 8
118
119        Label {
120            text: qsTr('Preset')
121            Layout.alignment: Qt.AlignRight
122        }
123        Shotcut.Preset {
124            id: preset
125            Layout.columnSpan: parent.columns - 1
126            parameters: ['opacity']
127            onBeforePresetLoaded: {
128                filter.resetProperty(parameters[0])
129            }
130            onPresetSelected: {
131                setControls()
132                middleValue = filter.getDouble(parameters[0], filter.animateIn)
133                if (filter.animateIn > 0)
134                    startValue = filter.getDouble(parameters[0], 0)
135                if (filter.animateOut > 0)
136                    endValue = filter.getDouble(parameters[0], filter.duration - 1)
137            }
138        }
139
140        Label {
141            text: qsTr('Level')
142            Layout.alignment: Qt.AlignRight
143        }
144        Shotcut.SliderSpinner {
145            id: brightnessSlider
146            minimumValue: 0.0
147            maximumValue: 200.0
148            decimals: 1
149            suffix: ' %'
150            onValueChanged: updateFilter(getPosition())
151        }
152        Shotcut.UndoButton {
153            onClicked: brightnessSlider.value = 100
154        }
155        Shotcut.KeyframesButton {
156            id: brightnessKeyframesButton
157            onToggled: {
158                var value = brightnessSlider.value / 100.0
159                if (checked) {
160                    blockUpdate = true
161                    filter.clearSimpleAnimation('opacity')
162                    blockUpdate = false
163                    filter.set('opacity', value, getPosition())
164                } else {
165                    filter.resetProperty('opacity')
166                    filter.set('opacity', value)
167                }
168            }
169        }
170
171
172        Item {
173            Layout.fillHeight: true
174        }
175    }
176}
177