1 /**************************************************************************\
2 * Copyright (c) Kongsberg Oil & Gas Technologies AS
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * Neither the name of the copyright holder nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32
33 /*!
34 \class SoFieldSensor SoFieldSensor.h Inventor/sensors/SoFieldSensor.h
35 \brief The SoFieldSensor class detects changes to a field.
36
37 \ingroup sensors
38
39 Attach a field to a sensor of this type to put it under
40 surveillance, so you can act upon changes to the field.
41
42 An SoFieldSensor can also act for delete-callback purposes alone and
43 does not need a regular notification-based callback.
44 */
45
46 #include <Inventor/sensors/SoFieldSensor.h>
47 #include <Inventor/fields/SoField.h>
48
49
50 /*!
51 Constructor.
52 */
SoFieldSensor(void)53 SoFieldSensor::SoFieldSensor(void)
54 {
55 this->convict = NULL;
56 }
57
58 /*!
59 Constructor taking as parameters the sensor callback function and
60 the userdata which will be passed the callback.
61
62 \sa setFunction(), setData()
63 */
SoFieldSensor(SoSensorCB * func,void * data)64 SoFieldSensor::SoFieldSensor(SoSensorCB * func, void * data)
65 : inherited(func, data)
66 {
67 this->convict = NULL;
68 }
69
70 /*!
71 Destructor.
72 */
~SoFieldSensor(void)73 SoFieldSensor::~SoFieldSensor(void)
74 {
75 if (this->convict) this->detach();
76 }
77
78 /*!
79 Attach sensor to a field. Whenever the field's value changes, the
80 sensor will be triggered and call the callback function.
81
82 A field sensor can be attached to only a single field at a
83 time. When this method is invoked multiple times, each subsequent
84 call will replace the field the sensor is monitoring with the new \a
85 field.
86
87 When the given field is deleted, the sensor will automatically be
88 detached.
89
90 \sa detach()
91 */
92 void
attach(SoField * field)93 SoFieldSensor::attach(SoField * field)
94 {
95 if (this->convict) this->detach();
96 this->convict = field;
97 field->addAuditor(this, SoNotRec::SENSOR);
98 field->evaluate();
99 }
100
101 /*!
102 Detach sensor from field. As long as an SoFieldSensor is detached,
103 it will never call its callback function.
104
105 \sa attach()
106 */
107 void
detach(void)108 SoFieldSensor::detach(void)
109 {
110 if (this->convict) {
111 this->convict->removeAuditor(this, SoNotRec::SENSOR);
112 this->convict = NULL;
113 if (this->isScheduled()) this->unschedule();
114 }
115 }
116
117 /*!
118 Returns a pointer to the field connected to the sensor.
119
120 \sa attach(), detach()
121 */
122 SoField *
getAttachedField(void) const123 SoFieldSensor::getAttachedField(void) const
124 {
125 return this->convict;
126 }
127
128 // Doc from superclass.
129 void
trigger(void)130 SoFieldSensor::trigger(void)
131 {
132 this->convict->evaluate();
133 inherited::trigger();
134 }
135
136 // Doc from superclass.
137 void
notify(SoNotList * l)138 SoFieldSensor::notify(SoNotList * l)
139 {
140 // Overridden to only propagate if the field that caused the
141 // notification is the one this sensor is attached to.
142 if (l->getLastField() == this->convict) {
143 inherited::notify(l);
144 }
145 }
146
147 // Doc from superclass.
148 void
dyingReference(void)149 SoFieldSensor::dyingReference(void)
150 {
151 SoFieldContainer * dyingcontainer = this->getAttachedField()->getContainer();
152
153 this->invokeDeleteCallback();
154
155 if (this->getAttachedField() != NULL &&
156 this->getAttachedField()->getContainer() == dyingcontainer) {
157 // sensor is attached, and to the same field-container
158 this->detach();
159 // FIXME: we could maybe do an exception for the globalfield-container,
160 // and for loose fields I assume have NULL for getContainer() - those cases
161 // should be checked at the field-pointer level instead.
162 }
163 }
164