floatpropertywidget.h 12.1 KB
Newer Older
1
2
// ================================================================================================
// 
schultezub's avatar
schultezub committed
3
// This file is part of the CAMPVis Software Framework.
4
// 
5
// If not explicitly stated otherwise: Copyright (C) 2012-2015, all rights reserved,
schultezub's avatar
schultezub committed
6
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
7
//      Chair for Computer Aided Medical Procedures
8
9
//      Technische Universitaet Muenchen
//      Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
10
// 
schultezub's avatar
schultezub committed
11
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
12
// 
13
14
15
16
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 
// except in compliance with the License. You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
17
// 
18
19
20
21
// Unless required by applicable law or agreed to in writing, software distributed under the 
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
// either express or implied. See the License for the specific language governing permissions 
// and limitations under the License.
22
23
24
// 
// ================================================================================================

schultezub's avatar
schultezub committed
25
26
27
#ifndef FLOATPROPERTYWIDGET_H__
#define FLOATPROPERTYWIDGET_H__

28
#include "application/gui/adjusterwidgets/doubleadjusterwidget.h"
schultezub's avatar
schultezub committed
29
#include "application/gui/properties/abstractpropertywidget.h"
30
#include "application/gui/properties/propertywidgetfactory.h"
31
#include "core/properties/floatingpointproperty.h"
schultezub's avatar
schultezub committed
32

schultezub's avatar
schultezub committed
33
namespace campvis {
schultezub's avatar
schultezub committed
34
    /**
35
     * Widget for a FloatProperty
schultezub's avatar
schultezub committed
36
     */
37
    class CAMPVIS_APPLICATION_API FloatPropertyWidget : public AbstractPropertyWidget {
38
        Q_OBJECT
schultezub's avatar
schultezub committed
39
40
41
42
43

    public:
        /**
         * Creates a new FloatPropertyWidget for the property \a property.
         * \param   property    The property the widget shall handle
44
         * \param   dataContainer   DataContainer to use (optional), defaults to nullptr.
schultezub's avatar
schultezub committed
45
46
         * \param   parent      Parent Qt widget
         */
47
        FloatPropertyWidget(FloatProperty* property, DataContainer* dataContainer, QWidget* parent = 0);
schultezub's avatar
schultezub committed
48
49
50
51
52
53
54
55
56
57
58
59
60

        /**
         * Destructor
         */
        virtual ~FloatPropertyWidget();

    protected:
        /**
         * Gets called when the property has changed, so that widget can update its state.
         */
        virtual void updateWidgetFromProperty();

    private slots:
61
62
        /// Slot getting called when the adjuster's value changes
        void onAdjusterValueChanged(double value);
schultezub's avatar
schultezub committed
63
64
65
66
67

    private:
        /// Slot getting called when the property's min or max value has changed, so that the widget can be updated.
        virtual void onPropertyMinMaxChanged(const AbstractProperty* property);

68
69
70
        /// Slot getting called when the property's step value has changed, so that the widget can be updated.
        virtual void onPropertyStepChanged(const AbstractProperty* property);

71
72
73
74
75
76
        /**
         * Slot getting called when the number of significant decimal places of the property has
         * changed, so that the widget can be updated.
         */
        virtual void onPropertyDecimalsChanged(const AbstractProperty* property);

77
        DoubleAdjusterWidget* _adjuster;        ///< Widget allowing the user to change the property's value
schultezub's avatar
schultezub committed
78
79

    };
80

81
82
83
    // explicitly instantiate template, so that it gets registered also over DLL boundaries.
    template class PropertyWidgetRegistrar<FloatPropertyWidget, FloatProperty>;

84
85
86
87
88
89
90
91
92
// ================================================================================================

    namespace {
        template<size_t SIZE>
        struct VecPropertyWidgetTraits {};

        template<>
        struct VecPropertyWidgetTraits<2> {
            typedef Vec2Property PropertyType;
93
            typedef cgt::vec2 BaseType;
94
95
96
97
98
        };

        template<>
        struct VecPropertyWidgetTraits<3> {
            typedef Vec3Property PropertyType;
99
            typedef cgt::vec3 BaseType;
100
101
102
103
104
        };

        template<>
        struct VecPropertyWidgetTraits<4> {
            typedef Vec4Property PropertyType;
105
            typedef cgt::vec4 BaseType;
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
        };
    }

// ================================================================================================

    /**
     * Generic base class for Vec property widgets.
     * Unfortunately Q_OBJECT and templates do not fit together, so we an additional level of 
     * indirection helps as usual...
     */
    template<size_t SIZE>
    class VecPropertyWidget : public AbstractPropertyWidget {
    public:
        enum { size = SIZE };
        typedef typename VecPropertyWidgetTraits<SIZE>::PropertyType PropertyType;

        /**
         * Creates a new VecPropertyWidget for the property \a property.
         * \param   property    The property the widget shall handle
         * \param   parent      Parent Qt widget
         */
127
        VecPropertyWidget(PropertyType* property, DataContainer* dataContainer = nullptr, QWidget* parent = 0);
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

        /**
         * Destructor
         */
        virtual ~VecPropertyWidget();

    protected:
        /**
         * Gets called when the property has changed, so that widget can update its state.
         */
        virtual void updateWidgetFromProperty();

        void onValueChangedImpl();

        /// Slot getting called when the property's min or max value has changed, so that the widget can be updated.
        virtual void onPropertyMinMaxChanged(const AbstractProperty* property);

145
146
147
        /// Slot getting called when the property's step value has changed, so that the widget can be updated.
        virtual void onPropertyStepChanged(const AbstractProperty* property);

148
149
150
151
152
153
        /**
         * Slot getting called when the number of significant decimal places of the property has
         * changed, so that the widget can be updated.
         */
        virtual void onPropertyDecimalsChanged(const AbstractProperty* property);

154
        DoubleAdjusterWidget* _adjusters[size];
155
156
157
158
159
    };

// ================================================================================================

    template<size_t SIZE>
160
161
    campvis::VecPropertyWidget<SIZE>::VecPropertyWidget(PropertyType* property, DataContainer* dataContainer, QWidget* parent /*= 0*/)
        : AbstractPropertyWidget(property, true, dataContainer, parent)
162
163
    {
        for (size_t i = 0; i < size; ++i) {
164
165
166
            _adjusters[i] = new DoubleAdjusterWidget();
            _adjusters[i]->setMinimum(property->getMinValue()[i]);
            _adjusters[i]->setMaximum(property->getMaxValue()[i]);
167
            _adjusters[i]->setDecimals(property->getDecimals()[i]);
168
            _adjusters[i]->setSingleStep(property->getStepValue()[i]);
169
170
            _adjusters[i]->setValue(property->getValue()[i]);
            addWidget(_adjusters[i]);
171
172
173
        }

        property->s_minMaxChanged.connect(this, &VecPropertyWidget::onPropertyMinMaxChanged);
174
        property->s_stepChanged.connect(this, &VecPropertyWidget::onPropertyStepChanged);
175
        property->s_decimalsChanged.connect(this, &VecPropertyWidget::onPropertyDecimalsChanged);
176
177
178
    }

    template<size_t SIZE>
schultezub's avatar
schultezub committed
179
    campvis::VecPropertyWidget<SIZE>::~VecPropertyWidget() {
180
181
182
183
184
        PropertyType* property = static_cast<PropertyType*>(_property);

        property->s_minMaxChanged.disconnect(this);
        property->s_stepChanged.disconnect(this);
        property->s_decimalsChanged.disconnect(this);
185
186
187
    }

    template<size_t SIZE>
schultezub's avatar
schultezub committed
188
    void campvis::VecPropertyWidget<SIZE>::updateWidgetFromProperty() {
189
190
        PropertyType* prop = static_cast<PropertyType*>(_property);
        for (size_t i = 0; i < size; ++i) {
191
192
193
            _adjusters[i]->blockSignals(true);
            _adjusters[i]->setValue(prop->getValue()[i]);
            _adjusters[i]->blockSignals(false);
194
195
196
197
        }
    }

    template<size_t SIZE>
schultezub's avatar
schultezub committed
198
    void campvis::VecPropertyWidget<SIZE>::onValueChangedImpl() {
schultezub's avatar
schultezub committed
199
        ++_ignorePropertyUpdates;
200
201
202
        PropertyType* prop = static_cast<PropertyType*>(_property);
        typename VecPropertyWidgetTraits<SIZE>::BaseType newValue;
        for (size_t i = 0; i < size; ++i)
203
            newValue[i] = _adjusters[i]->value();
204
        prop->setValue(newValue);
schultezub's avatar
schultezub committed
205
        --_ignorePropertyUpdates;
206
207
208
    }

    template<size_t SIZE>
schultezub's avatar
schultezub committed
209
    void campvis::VecPropertyWidget<SIZE>::onPropertyMinMaxChanged(const AbstractProperty* property) {
schultezub's avatar
schultezub committed
210
        if (_ignorePropertyUpdates == 0) {
211
212
            PropertyType* prop = static_cast<PropertyType*>(_property);
            for (size_t i = 0; i < size; ++i) {
213
214
                _adjusters[i]->setMinimum(prop->getMinValue()[i]);
                _adjusters[i]->setMaximum(prop->getMaxValue()[i]);
215
216
217
218
            }
        }
    }

219
220
221
222
223
224
225
226
227
228
    template<size_t SIZE>
    void campvis::VecPropertyWidget<SIZE>::onPropertyStepChanged(const AbstractProperty* property) {
        if (_ignorePropertyUpdates == 0) {
            PropertyType* prop = static_cast<PropertyType*>(_property);
            for (size_t i = 0; i < size; ++i) {
                _adjusters[i]->setSingleStep(prop->getStepValue()[i]);
            }
        }
    }

229
230
231
232
233
234
235
236
237
238
    template<size_t SIZE>
    void campvis::VecPropertyWidget<SIZE>::onPropertyDecimalsChanged(const AbstractProperty* property) {
        if (_ignorePropertyUpdates == 0) {
            PropertyType* prop = static_cast<PropertyType*>(_property);
            for (size_t i = 0; i < size; ++i) {
                _adjusters[i]->setDecimals(prop->getDecimals()[i]);
            }
        }
    }

239
240
241
242
243
// ================================================================================================

    class Vec2PropertyWidget : public VecPropertyWidget<2> {
        Q_OBJECT
    public:
244
245
        Vec2PropertyWidget(PropertyType* property, DataContainer* dataContainer = nullptr, QWidget* parent = 0)
            : VecPropertyWidget<2>(property, dataContainer, parent)
246
247
        {
            for (size_t i = 0; i < size; ++i) {
248
                connect(_adjusters[i], SIGNAL(valueChanged(double)), this, SLOT(onValueChanged(double)));
249
250
251
252
253
254
255
256
257
258
259
260
            }
        }

    private slots:
        void onValueChanged(double value) { onValueChangedImpl(); };
    }; 

// ================================================================================================
    
    class Vec3PropertyWidget : public VecPropertyWidget<3> {
        Q_OBJECT
    public:
261
262
        Vec3PropertyWidget(PropertyType* property, DataContainer* dataContainer = nullptr, QWidget* parent = 0)
            : VecPropertyWidget<3>(property, dataContainer, parent)
263
264
        {
            for (size_t i = 0; i < size; ++i) {
265
                connect(_adjusters[i], SIGNAL(valueChanged(double)), this, SLOT(onValueChanged(double)));
266
267
268
269
270
271
272
273
274
275
276
277
            }
        }

        private slots:
            void onValueChanged(double value) { onValueChangedImpl(); };
    }; 

// ================================================================================================

    class Vec4PropertyWidget : public VecPropertyWidget<4> {
        Q_OBJECT
    public:
278
279
        Vec4PropertyWidget(PropertyType* property, DataContainer* dataContainer = nullptr, QWidget* parent = 0)
            : VecPropertyWidget<4>(property, dataContainer, parent)
280
281
        {
            for (size_t i = 0; i < size; ++i) {
282
                connect(_adjusters[i], SIGNAL(valueChanged(double)), this, SLOT(onValueChanged(double)));
283
284
285
286
287
288
289
            }
        }

        private slots:
            void onValueChanged(double value) { onValueChangedImpl(); };
    }; 

290
291
292
293
294
295
296
// ================================================================================================

    // explicitly instantiate template, so that it gets registered also over DLL boundaries.
    template class PropertyWidgetRegistrar<Vec2PropertyWidget, typename VecPropertyWidgetTraits<2>::PropertyType, 5>;
    template class PropertyWidgetRegistrar<Vec3PropertyWidget, typename VecPropertyWidgetTraits<3>::PropertyType, 5>;
    template class PropertyWidgetRegistrar<Vec4PropertyWidget, typename VecPropertyWidgetTraits<4>::PropertyType, 5>;

schultezub's avatar
schultezub committed
297
298
299
}

#endif // FLOATPROPERTYWIDGET_H__