]> git.sesse.net Git - kdenlive/blob - src/kis_curve_widget_p.h
Fix label
[kdenlive] / src / kis_curve_widget_p.h
1 /*
2  *  Copyright (c) 2005 Casper Boemann <cbr@boemann.dk>
3  *  Copyright (c) 2009 Dmitry Kazakov <dimula73@gmail.com>
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 #ifndef _KIS_CURVE_WIDGET_P_H_
20 #define _KIS_CURVE_WIDGET_P_H_
21 #include "kis_cubic_curve.h"
22
23 enum enumState {
24     ST_NORMAL,
25     ST_DRAG
26 };
27
28 /**
29  * Private members for KisCurveWidget class
30  */
31 class KisCurveWidget::Private
32 {
33
34     KisCurveWidget *m_curveWidget;
35
36
37 public:
38     Private(KisCurveWidget *parent);
39     virtual ~Private();
40
41     /* Dragging variables */
42     int m_grab_point_index;
43     double m_grabOffsetX;
44     double m_grabOffsetY;
45     double m_grabOriginalX;
46     double m_grabOriginalY;
47     QPointF m_draggedAwayPoint;
48     int m_draggedAwayPointIndex;
49
50     bool m_readOnlyMode;
51     bool m_guideVisible;
52     QColor m_colorGuide;
53
54
55     /* The curve itself */
56     bool    m_splineDirty;
57     KisCubicCurve m_curve;
58
59     QPixmap m_pix;
60     bool m_pixmapDirty;
61     QPixmap *m_pixmapCache;
62
63     /* In/Out controls */
64     QSpinBox *m_intIn;
65     QSpinBox *m_intOut;
66
67     /* Working range of them */
68     int m_inOutMin;
69     int m_inOutMax;
70
71     /**
72      * State functions.
73      * At the moment used only for dragging.
74      */
75     enumState m_state;
76
77     inline void setState(enumState st);
78     inline enumState state() const;
79
80     int m_maxPoints;
81
82     /*** Internal routins ***/
83
84     /**
85      * Common update routins
86      */
87     void setCurveModified();
88     void setCurveRepaint();
89
90
91     /**
92      * Convert working range of
93      * In/Out controls to normalized
94      * range of spline (and reverse)
95      */
96     double io2sp(int x);
97     int sp2io(double x);
98
99
100     /**
101      * Check whether newly created/moved point @pt doesn't overlap
102      * with any of existing ones from @m_points and adjusts its coordinates.
103      * @skipIndex is the index of the point, that shouldn't be taken
104      * into account during the search
105      * (e.g. beacuse it's @pt itself)
106      *
107      * Returns false in case the point can't be placed anywhere
108      * without overlapping
109      */
110     bool jumpOverExistingPoints(QPointF &pt, int skipIndex);
111
112
113     /**
114      * Synchronize In/Out spinboxes with the curve
115      */
116     void syncIOControls();
117
118     /**
119      * Find the nearest point to @pt from m_points
120      */
121     int nearestPointInRange(QPointF pt, int wWidth, int wHeight) const;
122
123     /**
124      * Nothing to be said! =)
125      */
126     inline
127     void drawGrid(QPainter &p, int wWidth, int wHeight);
128
129 };
130
131 KisCurveWidget::Private::Private(KisCurveWidget *parent)
132 {
133     m_curveWidget = parent;
134     m_grab_point_index = 0;
135     m_grabOffsetX = 0;
136     m_grabOffsetY = 0;
137     m_grabOriginalX = 0;
138     m_grabOriginalY = 0;
139     m_draggedAwayPointIndex = 0;
140     m_readOnlyMode = 0;
141     m_guideVisible = 0;
142     m_splineDirty = 0;
143     m_pixmapDirty = 0;
144     m_pixmapCache = NULL;
145     m_intIn = NULL;
146     m_intOut = NULL;
147     m_inOutMin = 0;
148     m_inOutMax = 0;
149     m_state = ST_NORMAL;
150     m_maxPoints = 0;
151 }
152
153 KisCurveWidget::Private::~Private()
154 {
155 }
156
157
158 double KisCurveWidget::Private::io2sp(int x)
159 {
160     int rangeLen = m_inOutMax - m_inOutMin;
161     return double(x - m_inOutMin) / rangeLen;
162 }
163
164 int KisCurveWidget::Private::sp2io(double x)
165 {
166     int rangeLen = m_inOutMax - m_inOutMin;
167     return int(x*rangeLen + 0.5) + m_inOutMin;
168 }
169
170
171 bool KisCurveWidget::Private::jumpOverExistingPoints(QPointF &pt, int skipIndex)
172 {
173     foreach(const QPointF &it, m_curve.points()) {
174         if (m_curve.points().indexOf(it) == skipIndex)
175             continue;
176         if (fabs(it.x() - pt.x()) < POINT_AREA)
177             pt.rx() = pt.x() >= it.x() ?
178                       it.x() + POINT_AREA : it.x() - POINT_AREA;
179     }
180     return (pt.x() >= 0 && pt.x() <= 1.);
181 }
182
183 int KisCurveWidget::Private::nearestPointInRange(QPointF pt, int wWidth, int wHeight) const
184 {
185     double nearestDistanceSquared = 1000;
186     int nearestIndex = -1;
187     int i = 0;
188
189     foreach(const QPointF & point, m_curve.points()) {
190         double distanceSquared = (pt.x() - point.x()) *
191                                  (pt.x() - point.x()) +
192                                  (pt.y() - point.y()) *
193                                  (pt.y() - point.y());
194
195         if (distanceSquared < nearestDistanceSquared) {
196             nearestIndex = i;
197             nearestDistanceSquared = distanceSquared;
198         }
199         ++i;
200     }
201
202     if (nearestIndex >= 0) {
203         if (fabs(pt.x() - m_curve.points()[nearestIndex].x()) *(wWidth - 1) < 5 &&
204                 fabs(pt.y() - m_curve.points()[nearestIndex].y()) *(wHeight - 1) < 5) {
205             return nearestIndex;
206         }
207     }
208
209     return -1;
210 }
211
212
213 #define div2_round(x) (((x)+1)>>1)
214 #define div4_round(x) (((x)+2)>>2)
215
216 void KisCurveWidget::Private::drawGrid(QPainter &p, int wWidth, int wHeight)
217 {
218     /**
219      * Hint: widget size should conform
220      * formula 4n+5 to draw grid correctly
221      * without curious shifts between
222      * spline and it caused by rounding
223      *
224      * That is not mandatory but desirable
225      */
226
227     p.setPen(QPen(Qt::gray, 1, Qt::SolidLine));
228     p.drawLine(div4_round(wWidth), 0, div4_round(wWidth), wHeight);
229     p.drawLine(div2_round(wWidth), 0, div2_round(wWidth), wHeight);
230     p.drawLine(div4_round(3*wWidth), 0, div4_round(3*wWidth), wHeight);
231
232     p.drawLine(0, div4_round(wHeight), wWidth, div4_round(wHeight));
233     p.drawLine(0, div2_round(wHeight), wWidth, div2_round(wHeight));
234     p.drawLine(0, div4_round(3*wHeight), wWidth, div4_round(3*wHeight));
235
236 }
237
238 void KisCurveWidget::Private::syncIOControls()
239 {
240     if (!m_intIn || !m_intOut)
241         return;
242
243     bool somethingSelected = (m_grab_point_index >= 0);
244
245     m_intIn->setEnabled(somethingSelected);
246     m_intOut->setEnabled(somethingSelected);
247
248     if (m_grab_point_index >= 0) {
249         m_intIn->blockSignals(true);
250         m_intOut->blockSignals(true);
251
252         m_intIn->setValue(sp2io(m_curve.points()[m_grab_point_index].x()));
253         m_intOut->setValue(sp2io(m_curve.points()[m_grab_point_index].y()));
254
255         m_intIn->blockSignals(false);
256         m_intOut->blockSignals(false);
257     } else {
258         /*FIXME: Ideally, these controls should hide away now */
259     }
260 }
261
262 void KisCurveWidget::Private::setCurveModified()
263 {
264     syncIOControls();
265     m_splineDirty = true;
266     m_curveWidget->update();
267     m_curveWidget->emit modified();
268 }
269
270 void KisCurveWidget::Private::setCurveRepaint()
271 {
272     m_curveWidget->update();
273 }
274
275 void KisCurveWidget::Private::setState(enumState st)
276 {
277     m_state = st;
278 }
279
280
281 enumState KisCurveWidget::Private::state() const
282 {
283     return m_state;
284 }
285
286
287 #endif /* _KIS_CURVE_WIDGET_P_H_ */