numericproperty.h 11.2 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-2014, 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 NUMERICPROPERTY_H__
#define NUMERICPROPERTY_H__

28
#include "tgt/vector.h"
29
30

#include "core/coreapi.h"
schultezub's avatar
schultezub committed
31
32
#include "core/properties/genericproperty.h"

33
34
35
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
#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
77
namespace campvis {
schultezub's avatar
schultezub committed
78
79
80
81
    /**
     * Interface for numeric properties.
     * Defines methods for incrementing and decrementing the property's value.
     */
82
    class CAMPVIS_CORE_API INumericProperty {
83
    public:
schultezub's avatar
schultezub committed
84
        /// Increments the value of the property.
85
        virtual void increment() = 0;
schultezub's avatar
schultezub committed
86
        /// Decrements the value of the property.
87
88
89
        virtual void decrement() = 0;
    };

schultezub's avatar
schultezub committed
90
91
92
93
94
95
96
97
    /**
     * 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>
98
    class NumericProperty : public GenericProperty<T>, public INumericProperty {
schultezub's avatar
schultezub committed
99
100
101
102
103
104
105
106
    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
107
         * \param stepValue Step value for this property
schultezub's avatar
schultezub committed
108
109
110
111
112
113
114
         */
        NumericProperty(
            const std::string& name,
            const std::string& title,
            const T& value,
            const T& minValue,
            const T& maxValue,
115
            const T& stepValue = T(1));
schultezub's avatar
schultezub committed
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

        /**
         * 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;

        /**
144
145
146
147
148
149
150
         * 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
151
152
153
154
155
         * \param   value   New minimum value for this property.
         */
        virtual void setMinValue(const T& value);

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

161
162
163
164
165
166
        /**
         * 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
167
168
169
        /**
         * Increments the value of this property.
         */
170
        virtual void increment();
schultezub's avatar
schultezub committed
171
172
173
174

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

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

180
181
182
        /// Signal emitted, when the property's step value changes.
        sigslot::signal1<const AbstractProperty*> s_stepChanged;

schultezub's avatar
schultezub committed
183
184
185
186
187
188
189
190
191
192
193
194
    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
195
        T _stepValue;                           ///< Step value for this property
schultezub's avatar
schultezub committed
196
197
198
199

        static const std::string loggerCat_;
    };

200
201
202
    template<typename T>
    const std::string campvis::NumericProperty<T>::loggerCat_ = "CAMPVis.core.properties.NumericProperty";

schultezub's avatar
schultezub committed
203
// = Typedefs =====================================================================================
schultezub's avatar
schultezub committed
204

schultezub's avatar
schultezub committed
205
    typedef NumericProperty<int> IntProperty;
schultezub's avatar
schultezub committed
206

207
208
209
210
    typedef NumericProperty<tgt::ivec2> IVec2Property;
    typedef NumericProperty<tgt::ivec3> IVec3Property;
    typedef NumericProperty<tgt::ivec4> IVec4Property;

schultezub's avatar
schultezub committed
211
// = Template Implementation ======================================================================
schultezub's avatar
schultezub committed
212
213

    template<typename T>
214
    campvis::NumericProperty<T>::NumericProperty(const std::string& name, const std::string& title, const T& value,
215
216
                                                 const T& minValue, const T& maxValue, const T& stepValue /*= T(1)*/)
        : GenericProperty<T>(name, title, value)
schultezub's avatar
schultezub committed
217
218
        , _minValue(minValue)
        , _maxValue(maxValue)
219
        , _stepValue(stepValue)
schultezub's avatar
schultezub committed
220
221
222
223
224
    {

    }

    template<typename T>
schultezub's avatar
schultezub committed
225
    campvis::NumericProperty<T>::~NumericProperty() {
schultezub's avatar
schultezub committed
226
227
228
    }

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

    template<typename T>
schultezub's avatar
schultezub committed
241
    T campvis::NumericProperty<T>::validateValue(const T& value) {
242
        return NumericPropertyTraits<T, std::numeric_limits<T>::is_specialized>::validateValue(value, _minValue, _maxValue);
schultezub's avatar
schultezub committed
243
244
245
    }

    template<typename T>
schultezub's avatar
schultezub committed
246
    const T& campvis::NumericProperty<T>::getMinValue() const {
schultezub's avatar
schultezub committed
247
248
249
250
        return _minValue;
    }

    template<typename T>
schultezub's avatar
schultezub committed
251
    const T& campvis::NumericProperty<T>::getMaxValue() const {
schultezub's avatar
schultezub committed
252
253
254
        return _maxValue;
    }

255
256
257
258
259
    template<typename T>
    const T& campvis::NumericProperty<T>::getStepValue() const {
        return _stepValue;
    }

schultezub's avatar
schultezub committed
260
    template<typename T>
schultezub's avatar
schultezub committed
261
    void campvis::NumericProperty<T>::setMinValue(const T& value) {
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
262
        this->_minValue = value;
schultezub's avatar
schultezub committed
263
        this->setValue(validateValue(this->_value));
schultezub's avatar
schultezub committed
264

Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
265
        for (std::set<AbstractProperty*>::iterator it = this->_sharedProperties.begin(); it != this->_sharedProperties.end(); ++it) {
schultezub's avatar
schultezub committed
266
267
268
269
270
271
            // 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
272
        this->s_minMaxChanged(this);
schultezub's avatar
schultezub committed
273
274
275
    }

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

Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
280
        for (std::set<AbstractProperty*>::iterator it = this->_sharedProperties.begin(); it != this->_sharedProperties.end(); ++it) {
schultezub's avatar
schultezub committed
281
282
283
284
285
286
            // 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
287
        this->s_minMaxChanged(this);
schultezub's avatar
schultezub committed
288
289
    }

290
291
292
293
294
295
296
297
298
299
300
301
302
303
    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
304
    template<typename T>
schultezub's avatar
schultezub committed
305
    void campvis::NumericProperty<T>::increment() {
306
        this->setValue(this->_value + this->_stepValue);
schultezub's avatar
schultezub committed
307
308
309
    }

    template<typename T>
schultezub's avatar
schultezub committed
310
    void campvis::NumericProperty<T>::decrement() {
311
        this->setValue(this->_value - this->_stepValue);
schultezub's avatar
schultezub committed
312
313
314
315
    }
}

#endif // NUMERICPROPERTY_H__