~ubuntu-branches/ubuntu/oneiric/soqt/oneiric

« back to all changes in this revision

Viewing changes to build/msvc8/src/Inventor/Qt/nodes/Slider1.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Steve M. Robbins
  • Date: 2009-03-01 11:41:00 UTC
  • mfrom: (1.1.4 upstream) (5.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20090301114100-f4zz3n1oasa52fgk
Tags: 1.4.2~svn20090224-2
* Upload upstream SVN head version containing fixes to build with Coin 3
  (Closes: #515729, #515736, #515742).  Upstream indicated to me that
  SVN is stable enough to release.

* control: Update Standards-Version to 3.8.0; no changes required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**************************************************************************\
2
 
 *
3
 
 *  This file is part of the Coin 3D visualization library.
4
 
 *  Copyright (C) 1998-2005 by Systems in Motion.  All rights reserved.
5
 
 *
6
 
 *  This library is free software; you can redistribute it and/or
7
 
 *  modify it under the terms of the GNU General Public License
8
 
 *  ("GPL") version 2 as published by the Free Software Foundation.
9
 
 *  See the file LICENSE.GPL at the root directory of this source
10
 
 *  distribution for additional information about the GNU GPL.
11
 
 *
12
 
 *  For using Coin with software that can not be combined with the GNU
13
 
 *  GPL, and for taking advantage of the additional benefits of our
14
 
 *  support services, please contact Systems in Motion about acquiring
15
 
 *  a Coin Professional Edition License.
16
 
 *
17
 
 *  See <URL:http://www.coin3d.org/> for more information.
18
 
 *
19
 
 *  Systems in Motion, Postboks 1283, Pirsenteret, 7462 Trondheim, NORWAY.
20
 
 *  <URL:http://www.sim.no/>.
21
 
 *
22
 
\**************************************************************************/
23
 
 
24
 
#ifdef HAVE_CONFIG_H
25
 
#include <config.h>
26
 
#endif /* HAVE_CONFIG_H */
27
 
 
28
 
#include <Inventor/errors/SoDebugError.h>
29
 
#include <Inventor/actions/SoGLRenderAction.h>
30
 
#include <Inventor/actions/SoHandleEventAction.h>
31
 
#include <Inventor/misc/SoState.h>
32
 
#include <Inventor/elements/SoLazyElement.h>
33
 
#include <Inventor/sensors/SoFieldSensor.h>
34
 
#include <Inventor/events/SoMouseButtonEvent.h>
35
 
#include <Inventor/events/SoLocation2Event.h>
36
 
#include <Inventor/SoPickedPoint.h>
37
 
#include <Inventor/SoLists.h>
38
 
 
39
 
#include <Inventor/nodes/SoSeparator.h>
40
 
#include <Inventor/nodes/SoMaterial.h>
41
 
#include <Inventor/nodes/SoTexture2.h>
42
 
#include <Inventor/nodes/SoCoordinate3.h>
43
 
#include <Inventor/nodes/SoTextureCoordinate2.h>
44
 
#include <Inventor/nodes/SoIndexedFaceSet.h>
45
 
#include <Inventor/nodes/SoIndexedLineSet.h>
46
 
 
47
 
#include <Inventor/Qt/common/gl.h>
48
 
#include <Inventor/Qt/SoQtBasic.h>
49
 
 
50
 
#include <Inventor/Qt/nodes/SoGuiPane.h>
51
 
#include <Inventor/Qt/nodes/SoGuiSlider1.h>
52
 
#include <assert.h>
53
 
 
54
 
// *************************************************************************
55
 
 
56
 
/*!
57
 
  \class SoGuiSlider1 Inventor/Qt/nodes/SoGuiSlider1.h
58
 
  \brief A GUI component for a 1-dimensional slider.
59
 
 
60
 
  The SoGuiSlider1 node is for creating 2D user interfaces with
61
 
  sliders.
62
 
 
63
 
  fields:
64
 
    min
65
 
    max
66
 
    value
67
 
    orientation - not supported yet
68
 
    size
69
 
*/
70
 
 
71
 
// *************************************************************************
72
 
 
73
 
class Slider1 {
74
 
public:
75
 
  SoGuiSlider1 * kit;
76
 
  SoFieldSensor * sizeSensor;
77
 
  SoFieldSensor * valueSensor;
78
 
  SoFieldSensor * minSensor;
79
 
  SoFieldSensor * maxSensor;
80
 
 
81
 
  SbBool grabbing;
82
 
  float grabpos;
83
 
  float grabval;
84
 
  float graboffset;
85
 
  float pickpos;
86
 
  SoGuiPane * pane;
87
 
 
88
 
  Slider1(void);
89
 
  ~Slider1(void);
90
 
 
91
 
  SbColor mincolor, maxcolor;
92
 
 
93
 
  // sensors callbacks
94
 
  static void sizeChangeCB(void * closure, SoSensor * sensor);
95
 
  static void valueChangeCB(void * closure, SoSensor * sensor);
96
 
  static void minChangeCB(void * closure, SoSensor * sensor);
97
 
  static void maxChangeCB(void * closure, SoSensor * sensor);
98
 
};
99
 
 
100
 
Slider1::Slider1(void)
101
 
{
102
 
  this->kit = NULL;
103
 
  this->sizeSensor = NULL;
104
 
  this->valueSensor = NULL;
105
 
  this->minSensor = NULL;
106
 
  this->maxSensor = NULL;
107
 
  this->grabbing = FALSE;
108
 
  this->pane = NULL;
109
 
}
110
 
 
111
 
#define DELETE_SENSOR(sensor) \
112
 
  if ( (sensor) != NULL ) { \
113
 
    (sensor)->detach(); \
114
 
    delete (sensor); \
115
 
    (sensor) = NULL; \
116
 
  }
117
 
 
118
 
Slider1::~Slider1(void)
119
 
{
120
 
  DELETE_SENSOR(this->sizeSensor);
121
 
  DELETE_SENSOR(this->valueSensor);
122
 
  DELETE_SENSOR(this->minSensor);
123
 
  DELETE_SENSOR(this->maxSensor);
124
 
  this->kit = NULL;
125
 
}
126
 
 
127
 
#undef DELETE_SENSOR
128
 
 
129
 
void
130
 
Slider1::sizeChangeCB(void * closure, SoSensor * sensor)
131
 
{
132
 
  assert(closure);
133
 
  Slider1 * internals = (Slider1 *) closure;
134
 
  assert(internals->kit);
135
 
  internals->kit->sizeUpdate();
136
 
}
137
 
 
138
 
void
139
 
Slider1::valueChangeCB(void * closure, SoSensor * sensor)
140
 
{
141
 
  assert(closure);
142
 
  Slider1 * internals = (Slider1 *) closure;
143
 
  assert(internals->kit);
144
 
  internals->kit->valueUpdate();
145
 
}
146
 
 
147
 
void
148
 
Slider1::minChangeCB(void * closure, SoSensor * sensor)
149
 
{
150
 
  assert(closure);
151
 
  Slider1 * internals = (Slider1 *) closure;
152
 
  assert(internals->kit);
153
 
  internals->kit->minUpdate();
154
 
}
155
 
 
156
 
void
157
 
Slider1::maxChangeCB(void * closure, SoSensor * sensor)
158
 
{
159
 
  assert(closure);
160
 
  Slider1 * internals = (Slider1 *) closure;
161
 
  assert(internals->kit);
162
 
  internals->kit->maxUpdate();
163
 
}
164
 
 
165
 
// *************************************************************************
166
 
 
167
 
#define PRIVATE(obj) ((Slider1 *) obj->internals)
168
 
 
169
 
void
170
 
SoGuiSlider1::initClass(void)
171
 
{
172
 
  SO_KIT_INIT_CLASS(SoGuiSlider1, SoBaseKit, "BaseKit");
173
 
}
174
 
 
175
 
SO_KIT_SOURCE(SoGuiSlider1);
176
 
 
177
 
SoGuiSlider1::SoGuiSlider1(void)
178
 
{
179
 
  this->internals = (void *) new Slider1;
180
 
  PRIVATE(this)->kit = this;
181
 
 
182
 
  SO_KIT_CONSTRUCTOR(SoGuiSlider1);
183
 
 
184
 
  SO_KIT_ADD_FIELD(size, (SbVec3f(1.0f, 1.0f, 0.0f)));
185
 
  SO_KIT_ADD_FIELD(orientation, (SoGuiSlider1::X));
186
 
  SO_KIT_ADD_FIELD(min, (0.0f));
187
 
  SO_KIT_ADD_FIELD(max, (1.0f));
188
 
  SO_KIT_ADD_FIELD(value, (0.0f));
189
 
  SO_KIT_ADD_FIELD(alwaysHook, (TRUE));
190
 
 
191
 
  SO_KIT_DEFINE_ENUM_VALUE(Orientation, X);
192
 
  SO_KIT_DEFINE_ENUM_VALUE(Orientation, Y);
193
 
 
194
 
  SO_KIT_SET_SF_ENUM_TYPE(orientation, Orientation);
195
 
 
196
 
  SO_KIT_ADD_CATALOG_ENTRY(knobLightLineSet, SoIndexedLineSet, FALSE, knobGeometry, "", FALSE);
197
 
  SO_KIT_ADD_CATALOG_ENTRY(knobLightMaterial, SoMaterial, FALSE, knobGeometry, knobLightLineSet, TRUE);
198
 
  SO_KIT_ADD_CATALOG_ENTRY(knobShadeLineSet, SoIndexedLineSet, FALSE, knobGeometry, knobLightMaterial, FALSE);
199
 
  SO_KIT_ADD_CATALOG_ENTRY(knobShadeMaterial, SoMaterial, FALSE, knobGeometry, knobShadeLineSet, TRUE);
200
 
  SO_KIT_ADD_CATALOG_ENTRY(knobFaceSet, SoIndexedFaceSet, FALSE, knobGeometry, knobShadeMaterial, FALSE);
201
 
  SO_KIT_ADD_CATALOG_ENTRY(knobMaterial, SoMaterial, FALSE, knobGeometry, knobFaceSet, TRUE);
202
 
  SO_KIT_ADD_CATALOG_ENTRY(knobCoords, SoCoordinate3, FALSE, knobGeometry, knobMaterial, FALSE);
203
 
 
204
 
  SO_KIT_ADD_CATALOG_ENTRY(knobGeometry, SoSeparator, FALSE, topSeparator, "", FALSE);
205
 
  SO_KIT_ADD_CATALOG_ENTRY(surfaceFaceSet, SoIndexedFaceSet, FALSE, surfaceGeometry, "", FALSE);
206
 
  SO_KIT_ADD_CATALOG_ENTRY(surfaceCoords, SoCoordinate3, FALSE, surfaceGeometry, surfaceFaceSet, FALSE);
207
 
  SO_KIT_ADD_CATALOG_ENTRY(surfaceTexCoords, SoTextureCoordinate2, FALSE, surfaceGeometry, surfaceCoords, FALSE);
208
 
  SO_KIT_ADD_CATALOG_ENTRY(surfaceTexture, SoTexture2, TRUE, surfaceGeometry, surfaceTexCoords, TRUE);
209
 
  SO_KIT_ADD_CATALOG_ENTRY(surfaceMaterial, SoMaterial, TRUE, surfaceGeometry, surfaceTexture, TRUE);
210
 
  SO_KIT_ADD_CATALOG_ENTRY(surfaceGeometry, SoSeparator, FALSE, topSeparator, knobGeometry, FALSE);
211
 
  SO_KIT_ADD_CATALOG_ENTRY(topSeparator, SoSeparator, FALSE, this, "", FALSE);
212
 
 
213
 
  SO_KIT_INIT_INSTANCE();
214
 
 
215
 
  static float surfacetexturecoordinates[][2] = { {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 0.0f} };
216
 
  SoTextureCoordinate2 * surfacetexcoords = SO_GET_ANY_PART(this, "surfaceTexCoords", SoTextureCoordinate2);
217
 
  assert(surfacetexcoords);
218
 
  surfacetexcoords->point.setValues(0, 4, surfacetexturecoordinates);
219
 
 
220
 
  static int32_t surfaceindices[] = { 0, 1, 2, -1, 0, 2, 3, -1 };
221
 
  SoIndexedFaceSet * surfacefaceset = SO_GET_ANY_PART(this, "surfaceFaceSet", SoIndexedFaceSet);
222
 
  assert(surfacefaceset);
223
 
  surfacefaceset->textureCoordIndex.setValues(0, 8, surfaceindices);
224
 
  surfacefaceset->coordIndex.setValues(0, 8, surfaceindices);
225
 
 
226
 
  static int32_t knobindices[] = {
227
 
    0, 1, 2, -1, 0, 2, 3, -1,
228
 
    4, 5, 6, -1, 4, 6, 7, -1,
229
 
    8, 2, 5, -1, 8, 5, 9, -1,
230
 
    3, 11, 10, -1, 3, 10, 4, -1
231
 
  };
232
 
  SoIndexedFaceSet * knobfaceset = SO_GET_ANY_PART(this, "knobFaceSet", SoIndexedFaceSet);
233
 
  assert(knobfaceset);
234
 
  knobfaceset->coordIndex.setValues(0, sizeof(knobindices)/sizeof(knobindices[0]), knobindices);
235
 
 
236
 
  this->sizeUpdate();
237
 
 
238
 
  SoMaterial * knobmaterial = SO_GET_ANY_PART(this, "knobMaterial", SoMaterial);
239
 
  assert(knobmaterial);
240
 
  knobmaterial->ambientColor.setValue(0.6f, 0.6f, 0.6f);
241
 
  knobmaterial->diffuseColor.setValue(0.6f, 0.6f, 0.6f);
242
 
  knobmaterial->emissiveColor.setValue(0.6f, 0.6f, 0.6f);
243
 
 
244
 
  SoMaterial * knoblightmaterial = SO_GET_ANY_PART(this, "knobLightMaterial", SoMaterial);
245
 
  assert(knoblightmaterial);
246
 
  knoblightmaterial->ambientColor.setValue(0.75f, 0.75f, 0.75f);
247
 
  knoblightmaterial->diffuseColor.setValue(0.75f, 0.75f, 0.75f);
248
 
  knoblightmaterial->emissiveColor.setValue(0.75f, 0.75f, 0.75f);
249
 
 
250
 
  SoMaterial * knobshadowmaterial = SO_GET_ANY_PART(this, "knobShadeMaterial", SoMaterial);
251
 
  assert(knobshadowmaterial);
252
 
  knobshadowmaterial->ambientColor.setValue(0.4f, 0.4f, 0.4f);
253
 
  knobshadowmaterial->diffuseColor.setValue(0.4f, 0.4f, 0.4f);
254
 
  knobshadowmaterial->emissiveColor.setValue(0.4f, 0.4f, 0.4f);
255
 
 
256
 
  // FIXME: move these to correct coordinates
257
 
  SoIndexedLineSet * lightlineset = SO_GET_ANY_PART(this, "knobLightLineSet", SoIndexedLineSet);
258
 
  assert(lightlineset);
259
 
  static int32_t lightindices[] = { 16, 17, 18, -1, 12, 15, 14, -1 };
260
 
  lightlineset->coordIndex.setValues(0, sizeof(lightindices) / sizeof(lightindices[0]), lightindices);
261
 
 
262
 
  SoIndexedLineSet * shadelineset = SO_GET_ANY_PART(this, "knobShadeLineSet", SoIndexedLineSet);
263
 
  assert(shadelineset);
264
 
  static int32_t shadeindices[] = { 12, 13, 14, -1, 16, 19, 18, -1 };
265
 
  shadelineset->coordIndex.setValues(0, sizeof(shadeindices) / sizeof(shadeindices[0]), shadeindices);
266
 
 
267
 
  // set up sensors
268
 
  PRIVATE(this)->sizeSensor = new SoFieldSensor(Slider1::sizeChangeCB, PRIVATE(this));
269
 
  PRIVATE(this)->sizeSensor->attach(&(this->size));
270
 
  PRIVATE(this)->valueSensor = new SoFieldSensor(Slider1::valueChangeCB, PRIVATE(this));
271
 
  PRIVATE(this)->valueSensor->attach(&(this->value));
272
 
  PRIVATE(this)->minSensor = new SoFieldSensor(Slider1::minChangeCB, PRIVATE(this));
273
 
  PRIVATE(this)->minSensor->attach(&(this->min));
274
 
  PRIVATE(this)->maxSensor = new SoFieldSensor(Slider1::maxChangeCB, PRIVATE(this));
275
 
  PRIVATE(this)->maxSensor->attach(&(this->max));
276
 
}
277
 
 
278
 
SoGuiSlider1::~SoGuiSlider1(void)
279
 
{
280
 
  Slider1 * obj = PRIVATE(this);
281
 
  delete obj;
282
 
  this->internals = NULL;
283
 
}
284
 
 
285
 
void
286
 
SoGuiSlider1::setSurfaceColor(const SbColor & valuearg)
287
 
{
288
 
  // FIXME: use Material or basecolor instead of texture
289
 
  this->setSurfaceColor(valuearg, valuearg);
290
 
#if 0
291
 
  PRIVATE(this)->mincolor = valuearg;
292
 
  PRIVATE(this)->maxcolor = valuearg;
293
 
  this->setPart("surfaceTexture", NULL);
294
 
#endif
295
 
}
296
 
 
297
 
void
298
 
SoGuiSlider1::setSurfaceColor(const SbColor & minvalue, const SbColor & maxvalue)
299
 
{
300
 
  PRIVATE(this)->mincolor = minvalue;
301
 
  PRIVATE(this)->maxcolor = maxvalue;
302
 
 
303
 
  this->setPart("surfaceMaterial", NULL);
304
 
  SoTexture2 * texturenode = SO_GET_ANY_PART(this, "surfaceTexture", SoTexture2);
305
 
  assert(texturenode);
306
 
 
307
 
  texturenode->image.setValue(SbVec2s(256, 1), 3, NULL);
308
 
  texturenode->model.setValue(SoTexture2::DECAL);
309
 
 
310
 
  SbVec2s sizeval;
311
 
  int nc;
312
 
  unsigned char * buf = texturenode->image.startEditing(sizeval, nc);
313
 
  float rmin = minvalue[0];
314
 
  float gmin = minvalue[1];
315
 
  float bmin = minvalue[2];
316
 
  float rmax = maxvalue[0];
317
 
  float gmax = maxvalue[1];
318
 
  float bmax = maxvalue[2];
319
 
  for ( int x = 0; x < sizeval[0]; x += 1 ) {
320
 
    buf[x*nc+0] = (unsigned char) ((rmin + ((float) x / (float) (sizeval[0]-1)) * (rmax - rmin)) * 255.0f);
321
 
    buf[x*nc+1] = (unsigned char) ((gmin + ((float) x / (float) (sizeval[0]-1)) * (gmax - gmin)) * 255.0f);
322
 
    buf[x*nc+2] = (unsigned char) ((bmin + ((float) x / (float) (sizeval[0]-1)) * (bmax - bmin)) * 255.0f);
323
 
    for ( int y = 1; y < sizeval[1]; y += 1 ) {
324
 
      buf[(y*sizeval[0]+x)*nc+0] = buf[x*nc+0];
325
 
      buf[(y*sizeval[0]+x)*nc+1] = buf[x*nc+1];
326
 
      buf[(y*sizeval[0]+x)*nc+2] = buf[x*nc+2];
327
 
    }
328
 
  }
329
 
  texturenode->image.finishEditing();
330
 
}
331
 
 
332
 
SbColor
333
 
SoGuiSlider1::getValueAsColor(void) const
334
 
{
335
 
  // FIXME: support custom textures
336
 
  float val = this->value.getValue();
337
 
  float minval = this->min.getValue();
338
 
  float maxval = this->max.getValue();
339
 
  float factor = (maxval - minval) / (val - minval);
340
 
  float r = SoQtClamp(PRIVATE(this)->mincolor[0] + (PRIVATE(this)->maxcolor[0] - PRIVATE(this)->mincolor[0]) * factor, 0.0f, 1.0f);
341
 
  float g = SoQtClamp(PRIVATE(this)->mincolor[1] + (PRIVATE(this)->maxcolor[1] - PRIVATE(this)->mincolor[1]) * factor, 0.0f, 1.0f);
342
 
  float b = SoQtClamp(PRIVATE(this)->mincolor[2] + (PRIVATE(this)->maxcolor[2] - PRIVATE(this)->mincolor[2]) * factor, 0.0f, 1.0f);
343
 
  return SbColor(r, g, b);
344
 
}
345
 
 
346
 
void
347
 
SoGuiSlider1::sizeUpdate(void)
348
 
{
349
 
  SbVec3f sizeval = this->size.getValue();
350
 
  if ( sizeval[0] != 0.0f && sizeval[1] != 0.0f ) {
351
 
    float coordinates[][3] = { {0.0f, 0.0f, 0.0f}, {sizeval[0], 0.0f, 0.0f}, {sizeval[0], sizeval[1], 0.0f}, {0.0f, sizeval[1], 0.0f} };
352
 
    SoCoordinate3 * coords = SO_GET_ANY_PART(this, "surfaceCoords", SoCoordinate3);
353
 
    assert(coords);
354
 
    coords->point.setValues(0, sizeof(coordinates) / sizeof(coordinates[0]), coordinates);
355
 
    this->valueUpdate();
356
 
  }
357
 
}
358
 
 
359
 
void
360
 
SoGuiSlider1::valueUpdate(void)
361
 
{
362
 
  SbVec3f sizeval = this->size.getValue();
363
 
  float val = this->value.getValue();
364
 
  float minval = this->min.getValue();
365
 
  float maxval = this->max.getValue();
366
 
  if ( minval < maxval ) {
367
 
    if ( val < minval ) {
368
 
      this->value.setValue(minval);
369
 
      val = minval;
370
 
    } else if ( val > maxval ) {
371
 
      this->value.setValue(maxval);
372
 
      val = maxval;
373
 
    }
374
 
  } else {
375
 
    // we also support inverse sliders where min > max
376
 
    if ( val > minval ) {
377
 
      this->value.setValue(minval);
378
 
      val = minval;
379
 
    } else if ( val < maxval ) {
380
 
      this->value.setValue(maxval);
381
 
      val = maxval;
382
 
    }
383
 
  }
384
 
  // store previous height & value to avoid redundant updates
385
 
  float voff = (float) floor(((val - minval) / (maxval - minval)) * sizeval[0]);
386
 
  float knobcoordinates[][3] = {
387
 
    // faces
388
 
    {-7.0f+voff, -4.0f, 0.0f}, {8.0f+voff, -4.0f, 0.0f}, {8.0f+voff, -1.0f, 0.0f}, {-7.0f+voff, -1.0f, 0.0f}, 
389
 
    {-7.0f+voff, sizeval[1]+1.0f, 0.0f}, {8.0f+voff, sizeval[1]+1.0f, 0.0f}, {8.0f+voff, sizeval[1]+4.0f, 0.0f}, {-7.0f+voff, sizeval[1]+4.0f, 0.0f}, 
390
 
    {3.0f+voff, -1.0f, 0.0f}, {3.0f+voff, sizeval[1]+1.0f, 0.0f}, {-2.0f+voff, sizeval[1]+1.0f, 0.0f}, {-2.0f+voff, -1.0f, 0.0f},
391
 
    // outside lines
392
 
    // also used in handleEvent() so don't change their significance based on index
393
 
    {-8.0f+voff, -5.0f, 0.0f}, {8.0f+voff, -5.0f, 0.0f}, {8.0f+voff, sizeval[1]+4.0f, 0.0f}, {-8.0f+voff, sizeval[1]+4.0f, 0.0f},
394
 
    // inside lines
395
 
    {-2.0f+voff, -1.0f, 0.0f}, {2.0f+voff, -1.0f, 0.0f}, {2.0f+voff, sizeval[1], 0.0f}, {-2.0f+voff, sizeval[1], 0.0f}
396
 
  };
397
 
  SoCoordinate3 * knobcoords = SO_GET_ANY_PART(this, "knobCoords", SoCoordinate3);
398
 
  assert(knobcoords);
399
 
  knobcoords->point.setValues(0, sizeof(knobcoordinates) / sizeof(knobcoordinates[0]), knobcoordinates);
400
 
}
401
 
 
402
 
void
403
 
SoGuiSlider1::minUpdate(void)
404
 
{
405
 
  float minval = this->min.getValue();
406
 
  float maxval = this->max.getValue();
407
 
  float val = this->value.getValue();
408
 
  if ( minval < maxval ) {
409
 
    if ( val < minval ) this->value.setValue(minval);
410
 
  } else {
411
 
    if ( val > minval ) this->value.setValue(minval);
412
 
  }
413
 
}
414
 
 
415
 
void
416
 
SoGuiSlider1::maxUpdate(void)
417
 
{
418
 
  float minval = this->min.getValue();
419
 
  float maxval = this->max.getValue();
420
 
  float val = this->value.getValue();
421
 
  if ( minval < maxval ) {
422
 
    if ( val > maxval ) this->value.setValue(maxval);
423
 
  } else {
424
 
    if ( val < maxval ) this->value.setValue(maxval);
425
 
  }
426
 
}
427
 
 
428
 
void
429
 
SoGuiSlider1::handleEvent(SoHandleEventAction * action)
430
 
{
431
 
  if ( action->isHandled() ) return;
432
 
  const SoEvent * event = action->getEvent();
433
 
 
434
 
  if ( PRIVATE(this)->grabbing ) { // click-and-drag
435
 
    if ( event->isOfType(SoLocation2Event::getClassTypeId()) ) {
436
 
      assert(PRIVATE(this)->pane != NULL);
437
 
      // although the return value is discarded, we need to make this call to make
438
 
      // sure the raypick action is run over the scene graph so the pane can return
439
 
      // a useful value...
440
 
      action->getPickedPoint();
441
 
      SbVec2f raypos = PRIVATE(this)->pane->getRayPickIntersectionPoint();
442
 
      if ( raypos[0] != -1.0f ) {
443
 
        float imagpos = raypos[0] + PRIVATE(this)->graboffset;
444
 
        float minval = this->min.getValue();
445
 
        float maxval = this->max.getValue();
446
 
        float imagval;
447
 
        if ( minval < maxval ) imagval = SoQtClamp(imagpos / this->size.getValue()[0], minval, maxval);
448
 
        else imagval = SoQtClamp(imagpos / this->size.getValue()[0], maxval, minval);
449
 
        this->value.setValue(imagval);
450
 
      }
451
 
      action->setHandled();
452
 
    }
453
 
    else if ( event->isOfType(SoMouseButtonEvent::getClassTypeId()) ) {
454
 
      SoMouseButtonEvent * mbevent = (SoMouseButtonEvent *) event;
455
 
      if ( (mbevent->getButton() == SoMouseButtonEvent::BUTTON1) &&
456
 
           (mbevent->getState() == SoButtonEvent::UP) ) {
457
 
        PRIVATE(this)->grabbing = FALSE;
458
 
        PRIVATE(this)->pane = NULL;
459
 
        action->setHandled();
460
 
      }
461
 
    }
462
 
  }
463
 
  else if ( event->isOfType(SoMouseButtonEvent::getClassTypeId()) ) {
464
 
    SoMouseButtonEvent * mbevent = (SoMouseButtonEvent *) event;
465
 
    if ( (mbevent->getButton() == SoMouseButtonEvent::BUTTON1) &&
466
 
         (mbevent->getState() == SoButtonEvent::DOWN) ) {
467
 
      action->setPickRadius(0);
468
 
      const SoPickedPointList & pplist = action->getPickedPointList();
469
 
      if ( pplist.getLength() > 0 ) {
470
 
        int i;
471
 
        for ( i = 0; i < pplist.getLength(); i++ ) {
472
 
          if ( action->isHandled() ) break;
473
 
          const SoPickedPoint * pp = pplist[i];
474
 
          const SoPath * path = pp->getPath();
475
 
          SoNode * node = ((SoFullPath *) path)->getTail();
476
 
          if ( node == ((SoNode *) SO_GET_ANY_PART(this, "knobFaceSet", SoIndexedFaceSet)) ) {
477
 
            SbVec3f point = pp->getObjectPoint();
478
 
            SbVec3f sizeval = this->size.getValue();
479
 
            SoCoordinate3 * knobcoords = SO_GET_ANY_PART(this, "knobCoords", SoCoordinate3);
480
 
            assert(knobcoords);
481
 
            SbVec3f knobmin = knobcoords->point[12];
482
 
            SbVec3f knobmax = knobcoords->point[14];
483
 
            if ( point[0] >= knobmin[0] && point[0] <= knobmax[0] &&
484
 
                 point[1] >= knobmin[1] && point[1] <= knobmax[1] ) {
485
 
              PRIVATE(this)->grabbing = TRUE;
486
 
              action->setHandled();
487
 
  
488
 
              const SoFullPath * path = (const SoFullPath *) action->getCurPath();
489
 
              int i = path->getLength() - 1;
490
 
              SoNode * node = NULL;
491
 
              for ( ; i >= 0; i-- ) {
492
 
                node = path->getNode(i);
493
 
                if ( node->isOfType(SoGuiPane::getClassTypeId()) ) break;
494
 
                node = NULL;
495
 
              }
496
 
              assert(node != NULL);
497
 
              PRIVATE(this)->pane = (SoGuiPane *) node;
498
 
              PRIVATE(this)->grabval = this->value.getValue();
499
 
              PRIVATE(this)->pickpos = point[0];
500
 
  
501
 
              SbVec2f raypos = PRIVATE(this)->pane->getRayPickIntersectionPoint();
502
 
              PRIVATE(this)->grabpos = raypos[0];
503
 
              float realval = ((this->value.getValue() - this->min.getValue()) /
504
 
                (this->max.getValue() - this->min.getValue())) * this->size.getValue()[0];
505
 
              PRIVATE(this)->graboffset = realval - raypos[0];
506
 
            }
507
 
          }
508
 
        }
509
 
        for ( i = 0; i < pplist.getLength(); i++ ) {
510
 
          if ( action->isHandled() ) break;
511
 
          const SoPickedPoint * pp = pplist[i];
512
 
          const SoPath * path = pp->getPath();
513
 
          SoNode * node = ((SoFullPath *) path)->getTail();
514
 
          if ( node == ((SoNode *) SO_GET_ANY_PART(this, "surfaceFaceSet", SoIndexedFaceSet)) ) {
515
 
            SbVec3f point = pp->getObjectPoint();
516
 
            SbVec3f sizeval = this->size.getValue();
517
 
            this->value = this->min.getValue() + ((point[0] / sizeval[0]) * (this->max.getValue() - this->min.getValue()));
518
 
            action->setHandled();
519
 
            if ( this->alwaysHook.getValue() ) {
520
 
              PRIVATE(this)->grabbing = TRUE;
521
 
              const SoFullPath * path = (const SoFullPath *) action->getCurPath();
522
 
              int i = path->getLength() - 1;
523
 
              SoNode * node = NULL;
524
 
              for ( ; i >= 0; i-- ) {
525
 
                node = path->getNode(i);
526
 
                if ( node->isOfType(SoGuiPane::getClassTypeId()) ) break;
527
 
                node = NULL;
528
 
              }
529
 
              assert(node != NULL);
530
 
              PRIVATE(this)->pane = (SoGuiPane *) node;
531
 
              PRIVATE(this)->grabval = this->value.getValue();
532
 
              PRIVATE(this)->pickpos = point[0];
533
 
              SbVec2f raypos = PRIVATE(this)->pane->getRayPickIntersectionPoint();
534
 
                PRIVATE(this)->grabpos = raypos[0];
535
 
              float realval = ((this->value.getValue() - this->min.getValue()) /
536
 
                (this->max.getValue() - this->min.getValue())) * this->size.getValue()[0];
537
 
              PRIVATE(this)->graboffset = realval - raypos[0];
538
 
            }
539
 
          }
540
 
        }
541
 
      }
542
 
    }
543
 
  }
544
 
}
545
 
 
546
 
#undef PRIVATE
547