numericproperty.h 12 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
//      Chair for Computer Aided Medical Procedures
8
9
//      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 = T(1),
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
    typedef NumericProperty<int> IntProperty;
schultezub's avatar
schultezub committed
211

212
213
214
215
    typedef NumericProperty<tgt::ivec2> IVec2Property;
    typedef NumericProperty<tgt::ivec3> IVec3Property;
    typedef NumericProperty<tgt::ivec4> IVec4Property;

schultezub's avatar
schultezub committed
216
// = Template Implementation ======================================================================
schultezub's avatar
schultezub committed
217
218

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

    }

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

    template<typename T>
schultezub's avatar
schultezub committed
235
    void campvis::NumericProperty<T>::addSharedProperty(AbstractProperty* prop) {
schultezub's avatar
schultezub committed
236
237
238
239
        // 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
240
            tmp->setValue(GenericProperty<T>::getValue());
schultezub's avatar
schultezub committed
241
242
243
244
245
246
            return;
        }
        tgtAssert(false, "Shared property must be of the same type as this property!");
    }

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

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

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

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

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

Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
271
        for (std::set<AbstractProperty*>::iterator it = this->_sharedProperties.begin(); it != this->_sharedProperties.end(); ++it) {
schultezub's avatar
schultezub committed
272
273
274
275
276
277
            // 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
278
        this->s_minMaxChanged(this);
schultezub's avatar
schultezub committed
279
280
281
    }

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

Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
286
        for (std::set<AbstractProperty*>::iterator it = this->_sharedProperties.begin(); it != this->_sharedProperties.end(); ++it) {
schultezub's avatar
schultezub committed
287
288
289
290
291
292
            // 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
293
        this->s_minMaxChanged(this);
schultezub's avatar
schultezub committed
294
295
    }

296
297
298
299
300
301
302
303
304
305
306
307
308
309
    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
310
    template<typename T>
schultezub's avatar
schultezub committed
311
    void campvis::NumericProperty<T>::increment() {
312
        this->setValue(this->_value + this->_stepValue);
schultezub's avatar
schultezub committed
313
314
315
    }

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

#endif // NUMERICPROPERTY_H__