numericproperty.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, all rights reserved,
schultezub's avatar
schultezub committed
6
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
7
8
9
//      Chair for Computer Aided Medical Procedures
//      Technische Universität München
//      Boltzmannstr. 3, 85748 Garching b. München, Germany
schultezub's avatar
schultezub committed
10
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
// 
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// 
// ================================================================================================

schultezub's avatar
schultezub committed
30
31
32
#ifndef NUMERICPROPERTY_H__
#define NUMERICPROPERTY_H__

33
#include "tgt/vector.h"
schultezub's avatar
schultezub committed
34
35
#include "core/properties/genericproperty.h"

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
#include <limits>

namespace {
    /**
     * Helper struct for template specialization regarding scalar/vector types.
     */
    template<typename T, bool IsScalar>
    struct NumericPropertyTraits {
    };

    /**
     * Specialized traits for scalar NumericProperties.
     */
    template<typename T>
    struct NumericPropertyTraits<T, true> {
        static T validateValue(const T& value, const T& minValue, const T& maxValue) {
            if (value >= minValue && value <= maxValue)
                return value;
            else {
                return (value < minValue) ? minValue : maxValue;
            }
        }
    };

    /**
     * Specialized traits for vector NumericProperties.
     */
    template<typename T>
    struct NumericPropertyTraits<T, false> {
        static T validateValue(const T& value, const T& minValue, const T& maxValue) {
            T toReturn(value);

            for (size_t i = 0; i < value.size; ++i) {
                if (toReturn[i] < minValue[i])
                    toReturn[i] = minValue[i];
                else if (toReturn[i] > maxValue[i])
                    toReturn[i] = maxValue[i];
            }
            return toReturn;
        }
    };

}

schultezub's avatar
schultezub committed
80
namespace campvis {
schultezub's avatar
schultezub committed
81
82
83
84
    /**
     * Interface for numeric properties.
     * Defines methods for incrementing and decrementing the property's value.
     */
85
86
    class INumericProperty {
    public:
schultezub's avatar
schultezub committed
87
        /// Increments the value of the property.
88
        virtual void increment() = 0;
schultezub's avatar
schultezub committed
89
        /// Decrements the value of the property.
90
91
92
        virtual void decrement() = 0;
    };

schultezub's avatar
schultezub committed
93
94
95
96
97
98
99
100
    /**
     * Generic class for numeric properties.
     * Numeric properties manage a minimum and maximum value and ensure, that the property's 
     * value is within these bounds.
     *
     * \tparam  T   Base type of the property's value.
     */
    template<typename T>
101
    class NumericProperty : public GenericProperty<T>, public INumericProperty {
schultezub's avatar
schultezub committed
102
103
104
105
106
107
108
109
    public:
        /**
         * Creates a new NumericProperty.
         * \param name      Property name
         * \param title     Property title (e.g. used for GUI)
         * \param value     Initial value of the property
         * \param minValue  Minimum value for this property
         * \param maxValue  Maximum value for this property
110
         * \param stepValue Step value for this property
111
         * \param invalidationLevel  Invalidation level that this property triggers
schultezub's avatar
schultezub committed
112
113
114
115
116
117
118
         */
        NumericProperty(
            const std::string& name,
            const std::string& title,
            const T& value,
            const T& minValue,
            const T& maxValue,
119
            const T& stepValue,
120
            int invalidationLevel = AbstractProcessor::INVALID_RESULT);
schultezub's avatar
schultezub committed
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148

        /**
         * Virtual Destructor
         **/
        virtual ~NumericProperty();


        /**
         * Adds the given property \a prop to the set of shared properties.
         * All shared properties will be changed when this property changes.
         * \note        Make sure not to build circular sharing or you will encounter endless loops!
         * \param prop  Property to add, must be of the same type as this property.
         */
        virtual void addSharedProperty(AbstractProperty* prop);

        /**
         * Returns the minimum value of this property.
         * \return _minValue
         */
        const T& getMinValue() const;

        /**
         * Returns the minimum value of this property.
         * \return _minValue
         */
        const T& getMaxValue() const;

        /**
149
150
151
152
153
154
155
         * Returns the step value of this property.
         * \return _stepValue
         */
        const T& getStepValue() const;

        /**
         * Sets the minimum value of this property.
schultezub's avatar
schultezub committed
156
157
158
159
160
         * \param   value   New minimum value for this property.
         */
        virtual void setMinValue(const T& value);

        /**
161
         * Sets the minimum value of this property.
schultezub's avatar
schultezub committed
162
163
164
165
         * \param   value   New minimum value for this property.
         */
        virtual void setMaxValue(const T& value);

166
167
168
169
170
171
        /**
         * Sets the step value of this property.
         * \param   value   New step value for this property.
         */
        virtual void setStepValue(const T& value);

schultezub's avatar
schultezub committed
172
173
174
        /**
         * Increments the value of this property.
         */
175
        virtual void increment();
schultezub's avatar
schultezub committed
176
177
178
179

        /**
         * Decrements the value of this property.
         */
180
        virtual void decrement();
schultezub's avatar
schultezub committed
181

schultezub's avatar
schultezub committed
182
183
        /// Signal emitted, when the property's minimum or maximum value changes.
        sigslot::signal1<const AbstractProperty*> s_minMaxChanged;
schultezub's avatar
schultezub committed
184

185
186
187
        /// Signal emitted, when the property's step value changes.
        sigslot::signal1<const AbstractProperty*> s_stepChanged;

schultezub's avatar
schultezub committed
188
189
190
191
192
193
194
195
196
197
198
199
    protected:

        /**
         * Checks, whether \a value is a valid value for this property.
         * Default implementation always returns true, subclasses can overwrite this method to fit their needs.
         * \param   value   value to validate.
         * \return  true if \a value is a valid value for this property.
         */
        virtual T validateValue(const T& value);

        T _minValue;                            ///< Minimum value for this property
        T _maxValue;                            ///< Maximum value for this property
200
        T _stepValue;                           ///< Step value for this property
schultezub's avatar
schultezub committed
201
202
203
204

        static const std::string loggerCat_;
    };

205
206
207
    template<typename T>
    const std::string campvis::NumericProperty<T>::loggerCat_ = "CAMPVis.core.properties.NumericProperty";

schultezub's avatar
schultezub committed
208
// = Typedefs =====================================================================================
schultezub's avatar
schultezub committed
209

schultezub's avatar
schultezub committed
210
211
    typedef NumericProperty<int> IntProperty;
    typedef NumericProperty<float> FloatProperty;
schultezub's avatar
schultezub committed
212

213
214
215
216
217
218
219
    typedef NumericProperty<tgt::ivec2> IVec2Property;
    typedef NumericProperty<tgt::vec2> Vec2Property;
    typedef NumericProperty<tgt::ivec3> IVec3Property;
    typedef NumericProperty<tgt::vec3> Vec3Property;
    typedef NumericProperty<tgt::ivec4> IVec4Property;
    typedef NumericProperty<tgt::vec4> Vec4Property;

schultezub's avatar
schultezub committed
220
// = Template Implementation ======================================================================
schultezub's avatar
schultezub committed
221
222

    template<typename T>
223
    campvis::NumericProperty<T>::NumericProperty(const std::string& name, const std::string& title, const T& value, const T& minValue, const T& maxValue, const T& stepValue, int invalidationLevel /*= AbstractProcessor::INVALID_RESULT*/)
224
        : GenericProperty<T>(name, title, value, invalidationLevel)
schultezub's avatar
schultezub committed
225
226
        , _minValue(minValue)
        , _maxValue(maxValue)
227
        , _stepValue(stepValue)
schultezub's avatar
schultezub committed
228
229
230
231
232
    {

    }

    template<typename T>
schultezub's avatar
schultezub committed
233
    campvis::NumericProperty<T>::~NumericProperty() {
schultezub's avatar
schultezub committed
234
235
236
    }

    template<typename T>
schultezub's avatar
schultezub committed
237
    void campvis::NumericProperty<T>::addSharedProperty(AbstractProperty* prop) {
schultezub's avatar
schultezub committed
238
239
240
241
        // make type check first, then call base method.
        tgtAssert(prop != 0, "Shared property must not be 0!");
        if (NumericProperty<T>* tmp = dynamic_cast< NumericProperty<T>* >(prop)) {
            AbstractProperty::addSharedProperty(prop);
schultezub's avatar
schultezub committed
242
            tmp->setValue(GenericProperty<T>::getValue());
schultezub's avatar
schultezub committed
243
244
245
246
247
248
            return;
        }
        tgtAssert(false, "Shared property must be of the same type as this property!");
    }

    template<typename T>
schultezub's avatar
schultezub committed
249
    T campvis::NumericProperty<T>::validateValue(const T& value) {
250
        return NumericPropertyTraits<T, std::numeric_limits<T>::is_specialized>::validateValue(value, _minValue, _maxValue);
schultezub's avatar
schultezub committed
251
252
253
    }

    template<typename T>
schultezub's avatar
schultezub committed
254
    const T& campvis::NumericProperty<T>::getMinValue() const {
schultezub's avatar
schultezub committed
255
256
257
258
        return _minValue;
    }

    template<typename T>
schultezub's avatar
schultezub committed
259
    const T& campvis::NumericProperty<T>::getMaxValue() const {
schultezub's avatar
schultezub committed
260
261
262
        return _maxValue;
    }

263
264
265
266
267
    template<typename T>
    const T& campvis::NumericProperty<T>::getStepValue() const {
        return _stepValue;
    }

schultezub's avatar
schultezub committed
268
    template<typename T>
schultezub's avatar
schultezub committed
269
    void campvis::NumericProperty<T>::setMinValue(const T& value) {
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
270
        this->_minValue = value;
schultezub's avatar
schultezub committed
271
        this->setValue(validateValue(this->_value));
schultezub's avatar
schultezub committed
272

Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
273
        for (std::set<AbstractProperty*>::iterator it = this->_sharedProperties.begin(); it != this->_sharedProperties.end(); ++it) {
schultezub's avatar
schultezub committed
274
275
276
277
278
279
            // We ensure all shared properties to be of type NumericProperty<T> in the addSharedProperty overload.
            // Hence, static_cast ist safe.
            NumericProperty<T>* child = static_cast< NumericProperty<T>* >(*it);
            child->setMinValue(value);
        }

Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
280
        this->s_minMaxChanged(this);
schultezub's avatar
schultezub committed
281
282
283
    }

    template<typename T>
schultezub's avatar
schultezub committed
284
    void campvis::NumericProperty<T>::setMaxValue(const T& value) {
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
285
        this->_maxValue = value;
schultezub's avatar
schultezub committed
286
        this->setValue(validateValue(this->_value));
schultezub's avatar
schultezub committed
287

Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
288
        for (std::set<AbstractProperty*>::iterator it = this->_sharedProperties.begin(); it != this->_sharedProperties.end(); ++it) {
schultezub's avatar
schultezub committed
289
290
291
292
293
294
            // We ensure all shared properties to be of type NumericProperty<T> in the addSharedProperty overload.
            // Hence, static_cast ist safe.
            NumericProperty<T>* child = static_cast< NumericProperty<T>* >(*it);
            child->setMaxValue(value);
        }

Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
295
        this->s_minMaxChanged(this);
schultezub's avatar
schultezub committed
296
297
    }

298
299
300
301
302
303
304
305
306
307
308
309
310
311
    template<typename T>
    void campvis::NumericProperty<T>::setStepValue(const T& value) {
        this->_stepValue = value;

        for (std::set<AbstractProperty*>::iterator it = this->_sharedProperties.begin(); it != this->_sharedProperties.end(); ++it) {
            // We ensure all shared properties to be of type NumericProperty<T> in the addSharedProperty overload.
            // Hence, static_cast ist safe.
            NumericProperty<T>* child = static_cast< NumericProperty<T>* >(*it);
            child->setStepValue(value);
        }

        this->s_stepChanged(this);
    }

schultezub's avatar
schultezub committed
312
    template<typename T>
schultezub's avatar
schultezub committed
313
    void campvis::NumericProperty<T>::increment() {
schultezub's avatar
schultezub committed
314
        this->setValue(this->_value + T(1));
schultezub's avatar
schultezub committed
315
316
317
    }

    template<typename T>
schultezub's avatar
schultezub committed
318
    void campvis::NumericProperty<T>::decrement() {
schultezub's avatar
schultezub committed
319
        this->setValue(this->_value - T(1));
schultezub's avatar
schultezub committed
320
321
322
323
    }
}

#endif // NUMERICPROPERTY_H__