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 SoEnabledElementsList SoEnabledElementsList.h Inventor/lists/SoEnabledElementsList.h
35 \brief The SoEnabledElementsList class is a container for type info for element types that are enabled in actions.
36
37 \ingroup actions
38
39 This class is probably not interesting for the application
40 programmer.
41 */
42
43 // FIXME: doesn't handle post-initialization changes very well (fixing
44 // this also needs some tempering to be done with SoAction, I think.)
45 // 20000305 mortene.
46
47 #include <Inventor/lists/SoEnabledElementsList.h>
48 #include <cassert>
49
50 #ifdef HAVE_CONFIG_H
51 #include <config.h>
52 #endif // HAVE_CONFIG_H
53
54 #ifdef COIN_THREADSAFE
55 #include <Inventor/threads/SbMutex.h>
56 #endif // COIN_THREADSAFE
57
58 #ifndef DOXYGEN_SKIP_THIS
59
60 class SoEnabledElementsListP {
61 public:
62 int prevmerge;
63 SoTypeList elements;
64 SoEnabledElementsList * parent;
65 #ifdef COIN_THREADSAFE
66 SbMutex mutex;
67 #endif // COIN_THREADSAFE
lock(void)68 void lock(void) {
69 #ifdef COIN_THREADSAFE
70 this->mutex.lock();
71 #endif
72 }
unlock(void)73 void unlock(void) {
74 #ifdef COIN_THREADSAFE
75 this->mutex.unlock();
76 #endif
77 }
78 };
79
80 static int enable_counter = 0;
81
82 #endif // DOXYGEN_SKIP_THIS
83
84 #define PRIVATE(obj) ((obj)->pimpl)
85
86 /*!
87 Constructor.
88 */
SoEnabledElementsList(SoEnabledElementsList * const parentlist)89 SoEnabledElementsList::SoEnabledElementsList(SoEnabledElementsList * const parentlist)
90 {
91 PRIVATE(this) = new SoEnabledElementsListP;
92
93 PRIVATE(this)->prevmerge = 0;
94 PRIVATE(this)->parent = parentlist;
95 }
96
97 /*!
98 Destructor.
99 */
~SoEnabledElementsList()100 SoEnabledElementsList::~SoEnabledElementsList()
101 {
102 delete PRIVATE(this);
103 }
104
105 /*!
106 Return the list of enabled elements.
107 */
108 const SoTypeList &
getElements(void) const109 SoEnabledElementsList::getElements(void) const
110 {
111 PRIVATE(this)->lock();
112 // check if we need a new merge
113 if (PRIVATE(this)->prevmerge != enable_counter) {
114 int storedcounter = enable_counter;
115 SoEnabledElementsList * plist = (SoEnabledElementsList*) PRIVATE(this)->parent;
116 while (plist) {
117 ((SoEnabledElementsList*)this)->merge(*plist);
118 plist = plist->pimpl->parent;
119 }
120 // use and restore old counter since it might change during merge
121 ((SoEnabledElementsList*)this)->pimpl->prevmerge =
122 enable_counter = storedcounter;
123 }
124 PRIVATE(this)->unlock();
125 return PRIVATE(this)->elements;
126 }
127
128 /*!
129 Add an \a elementtype to the list of enabled elements if it's not
130 enabled already.
131 */
132 void
enable(const SoType elementtype,const int stackindex)133 SoEnabledElementsList::enable(const SoType elementtype, const int stackindex)
134 {
135 while (stackindex >= PRIVATE(this)->elements.getLength())
136 PRIVATE(this)->elements.append(SoType::badType());
137
138 SoType currtype = PRIVATE(this)->elements[stackindex];
139 if (currtype.isBad() ||
140 (elementtype != currtype && elementtype.isDerivedFrom(currtype))) {
141 PRIVATE(this)->elements.set(stackindex, elementtype);
142 // increment to detect when a new merge is needed
143 enable_counter++;
144 }
145 }
146
147 /*!
148 Enables all the elements from the \a eel list that is enabled in
149 this instance.
150 */
151 void
merge(const SoEnabledElementsList & eel)152 SoEnabledElementsList::merge(const SoEnabledElementsList & eel)
153 {
154 SoType bad = SoType::badType();
155 const int num = eel.pimpl->elements.getLength();
156 for (int i = 0; i < num; i++) {
157 if (eel.pimpl->elements[i] != bad) this->enable(eel.pimpl->elements[i], i);
158 }
159 }
160
161 /*!
162 Return the current setting of the global counter used to determine
163 when lists are out of date. It is incremented whenever a new
164 element is added to a list.
165 */
166 int
getCounter(void)167 SoEnabledElementsList::getCounter(void)
168 {
169 return enable_counter;
170 }
171
172 #undef PRIVATE
173