]> git.mxchange.org Git - flightgear.git/blob - src/Cockpit/panel.cxx
The following changes were made to flightgear-0.7.5 code to implement the follow
[flightgear.git] / src / Cockpit / panel.cxx
1 //  panel.cxx - default, 2D single-engine prop instrument panel
2 //
3 //  Written by David Megginson, started January 2000.
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License as
7 //  published by the Free Software Foundation; either version 2 of the
8 //  License, or (at your option) any later version.
9 // 
10 //  This program is distributed in the hope that it will be useful, but
11 //  WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 //  General Public License for more details.
14 // 
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //
19 //  $Id$
20
21 #ifdef HAVE_CONFIG_H
22 #  include <config.h>
23 #endif
24
25 #ifdef HAVE_WINDOWS_H          
26 #  include <windows.h>
27 #endif
28
29 #include <string.h>
30
31 #include <plib/ssg.h>
32 #include <plib/fnt.h>
33
34 #include <simgear/debug/logstream.hxx>
35 #include <simgear/misc/fgpath.hxx>
36 #include <Main/globals.hxx>
37 #include <Main/options.hxx>
38 #include <Objects/texload.h>
39
40 #include "hud.hxx"
41 #include "panel.hxx"
42
43
44 bool
45 fgPanelVisible ()
46 {
47   return ((current_options.get_panel_status()) &&
48           (current_options.get_view_mode() == fgOPTIONS::FG_VIEW_PILOT) &&
49           (globals->get_current_view()->get_view_offset() == 0.0));
50 }
51
52
53 \f
54 ////////////////////////////////////////////////////////////////////////
55 // Implementation of FGTextureManager.
56 ////////////////////////////////////////////////////////////////////////
57
58 map<string,ssgTexture *> FGTextureManager::_textureMap;
59
60 ssgTexture *
61 FGTextureManager::createTexture (const string &relativePath)
62 {
63   ssgTexture * texture = _textureMap[relativePath];
64   if (texture == 0) {
65     cerr << "Texture " << relativePath << " does not yet exist" << endl;
66     FGPath tpath(current_options.get_fg_root());
67     tpath.append(relativePath);
68     texture = new ssgTexture((char *)tpath.c_str(), false, false);
69     _textureMap[relativePath] = texture;
70     if (_textureMap[relativePath] == 0) 
71       cerr << "Texture *still* doesn't exist" << endl;
72     cerr << "Created texture " << relativePath
73          << " handle=" << texture->getHandle() << endl;
74   }
75
76   return texture;
77 }
78
79
80
81 \f
82 ////////////////////////////////////////////////////////////////////////
83 // Implementation of FGCropped Texture.
84 ////////////////////////////////////////////////////////////////////////
85
86
87 FGCroppedTexture::FGCroppedTexture ()
88   : _path(""), _texture(0),
89     _minX(0.0), _minY(0.0), _maxX(1.0), _maxY(1.0)
90 {
91 }
92
93
94 FGCroppedTexture::FGCroppedTexture (const string &path,
95                                     float minX, float minY,
96                                     float maxX, float maxY)
97   : _path(path), _texture(0),
98     _minX(minX), _minY(minY), _maxX(maxX), _maxY(maxY)
99 {
100 }
101
102
103 FGCroppedTexture::~FGCroppedTexture ()
104 {
105 }
106
107
108 ssgTexture *
109 FGCroppedTexture::getTexture ()
110 {
111   if (_texture == 0) {
112     _texture = FGTextureManager::createTexture(_path);
113   }
114   return _texture;
115 }
116
117
118 \f
119 ////////////////////////////////////////////////////////////////////////
120 // Implementation of FGPanel.
121 ////////////////////////////////////////////////////////////////////////
122
123 FGPanel * current_panel = NULL;
124 static fntRenderer text_renderer;
125
126
127 /**
128  * Constructor.
129  */
130 FGPanel::FGPanel (int window_x, int window_y, int window_w, int window_h)
131   : _mouseDown(false),
132     _mouseInstrument(0),
133     _winx(window_x), _winy(window_y), _winw(window_w), _winh(window_h),
134     _width(_winw), _height(int(_winh * 0.5768 + 1)),
135     _x_offset(0), _y_offset(0), _view_height(int(_winh * 0.4232))
136 {
137   setVisibility(fgPanelVisible());
138 }
139
140
141 /**
142  * Destructor.
143  */
144 FGPanel::~FGPanel ()
145 {
146   for (instrument_list_type::iterator it = _instruments.begin();
147        it != _instruments.end();
148        it++) {
149     delete *it;
150     *it = 0;
151   }
152 }
153
154
155 /**
156  * Add an instrument to the panel.
157  */
158 void
159 FGPanel::addInstrument (FGPanelInstrument * instrument)
160 {
161   _instruments.push_back(instrument);
162 }
163
164
165 /**
166  * Update the panel.
167  */
168 void
169 FGPanel::update () const
170 {
171                                 // Do nothing if the panel isn't visible.
172   if (!fgPanelVisible())
173     return;
174
175                                 // If the mouse is down, do something
176   if (_mouseDown) {
177     _mouseDelay--;
178     if (_mouseDelay < 0) {
179       _mouseInstrument->doMouseAction(_mouseButton, _mouseX, _mouseY);
180       _mouseDelay = 2;
181     }
182   }
183
184                                 // Now, draw the panel
185   glMatrixMode(GL_PROJECTION);
186   glPushMatrix();
187   glLoadIdentity();
188   gluOrtho2D(_winx, _winx + _winw, _winy, _winy + _winh);
189
190   glMatrixMode(GL_MODELVIEW);
191   glPushMatrix();
192   glLoadIdentity();
193
194   glTranslated(_x_offset, _y_offset, 0);
195
196                                 // Draw the background
197   glEnable(GL_TEXTURE_2D);
198   glDisable(GL_LIGHTING);
199   glEnable(GL_BLEND);
200   glEnable(GL_ALPHA_TEST);
201   glEnable(GL_COLOR_MATERIAL);
202   // glColor4f(1.0, 1.0, 1.0, 1.0);
203   if ( cur_light_params.sun_angle * RAD_TO_DEG < 95.0 ) {
204       glColor4fv( cur_light_params.scene_diffuse );
205   } else {
206       glColor4f(0.7, 0.2, 0.2, 1.0);
207   }
208   glBindTexture(GL_TEXTURE_2D, _bg->getHandle());
209   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
210   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
211   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
212   glBegin(GL_POLYGON);
213   glTexCoord2f(0.0, 0.0); glVertex3f(_winx, _winy, 0);
214   glTexCoord2f(1.0, 0.0); glVertex3f(_winx + _width, _winy, 0);
215   glTexCoord2f(1.0, 1.0); glVertex3f(_winx + _width, _winy + _height, 0);
216   glTexCoord2f(0.0, 1.0); glVertex3f(_winx, _winy + _height, 0);
217   glEnd();
218
219                                 // Draw the instruments.
220   instrument_list_type::const_iterator current = _instruments.begin();
221   instrument_list_type::const_iterator end = _instruments.end();
222
223   for ( ; current != end; current++) {
224     FGPanelInstrument * instr = *current;
225     glLoadIdentity();
226     glTranslated(_x_offset, _y_offset, 0);
227     glTranslated(instr->getXPos(), instr->getYPos(), 0);
228     instr->draw();
229   }
230
231   glMatrixMode(GL_PROJECTION);
232   glPopMatrix();
233   glMatrixMode(GL_MODELVIEW);
234   glPopMatrix();
235   ssgForceBasicState();
236   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
237 }
238
239
240 /**
241  * Set the panel's visibility.
242  */
243 void
244 FGPanel::setVisibility (bool visibility)
245 {
246   _visibility = visibility;
247 }
248
249
250 /**
251  * Return true if the panel is visible.
252  */
253 bool
254 FGPanel::getVisibility () const
255 {
256   return _visibility;
257 }
258
259
260 /**
261  * Set the panel's background texture.
262  */
263 void
264 FGPanel::setBackground (ssgTexture * texture)
265 {
266   _bg = texture;
267 }
268
269
270 /**
271  * Set the panel's x-offset.
272  */
273 void
274 FGPanel::setXOffset (int offset)
275 {
276   if (offset <= 0 && offset >= -_width + _winw)
277     _x_offset = offset;
278 }
279
280
281 /**
282  * Set the panel's y-offset.
283  */
284 void
285 FGPanel::setYOffset (int offset)
286 {
287   if (offset <= 0 && offset >= -_height)
288     _y_offset = offset;
289 }
290
291
292 /**
293  * Perform a mouse action.
294  */
295 bool
296 FGPanel::doMouseAction (int button, int updown, int x, int y)
297 {
298
299                                 // Note a released button and return
300   // cerr << "Doing mouse action\n";
301   if (updown == 1) {
302     _mouseDown = false;
303     _mouseInstrument = 0;
304     return true;
305   }
306
307                                 // Scale for the real window size.
308   x = int(((float)x / globals->get_current_view()->get_winWidth()) * _winw);
309   y = int(_winh - (((float)y / globals->get_current_view()->get_winHeight())
310                    * _winh));
311
312                                 // Adjust for offsets.
313   x -= _x_offset;
314   y -= _y_offset;
315
316                                 // Search for a matching instrument.
317   for (int i = 0; i < (int)_instruments.size(); i++) {
318     FGPanelInstrument *inst = _instruments[i];
319     int ix = inst->getXPos();
320     int iy = inst->getYPos();
321     int iw = inst->getWidth() / 2;
322     int ih = inst->getHeight() / 2;
323     if (x >= ix - iw && x < ix + iw && y >= iy - ih && y < iy + ih) {
324       _mouseDown = true;
325       _mouseDelay = 20;
326       _mouseInstrument = inst;
327       _mouseButton = button;
328       _mouseX = x - ix;
329       _mouseY = y - iy;
330                                 // Always do the action once.
331       _mouseInstrument->doMouseAction(_mouseButton, _mouseX, _mouseY);
332       return true;
333     }
334   }
335   return false;
336 }
337
338
339 \f
340 ////////////////////////////////////////////////////////////////////////.
341 // Implementation of FGPanelAction.
342 ////////////////////////////////////////////////////////////////////////
343
344 FGPanelAction::FGPanelAction ()
345 {
346 }
347
348 FGPanelAction::FGPanelAction (int button, int x, int y, int w, int h)
349   : _button(button), _x(x), _y(y), _w(w), _h(h)
350 {
351 }
352
353 FGPanelAction::~FGPanelAction ()
354 {
355 }
356
357
358 \f
359 ////////////////////////////////////////////////////////////////////////
360 // Implementation of FGAdjustAction.
361 ////////////////////////////////////////////////////////////////////////
362
363 FGAdjustAction::FGAdjustAction (int button, int x, int y, int w, int h,
364                                 SGValue * value, float increment, 
365                                 float min, float max, bool wrap)
366   : FGPanelAction(button, x, y, w, h),
367     _value(value), _increment(increment), _min(min), _max(max), _wrap(wrap)
368 {
369 }
370
371 FGAdjustAction::~FGAdjustAction ()
372 {
373 }
374
375 void
376 FGAdjustAction::doAction ()
377 {
378   float val = _value->getFloatValue();
379   val += _increment;
380   if (val < _min) {
381     val = (_wrap ? _max : _min);
382   } else if (val > _max) {
383     val = (_wrap ? _min : _max);
384   }
385   _value->setDoubleValue(val);
386 }
387
388
389 \f
390 ////////////////////////////////////////////////////////////////////////
391 // Implementation of FGSwapAction.
392 ////////////////////////////////////////////////////////////////////////
393
394 FGSwapAction::FGSwapAction (int button, int x, int y, int w, int h,
395                             SGValue * value1, SGValue * value2)
396   : FGPanelAction(button, x, y, w, h), _value1(value1), _value2(value2)
397 {
398 }
399
400 FGSwapAction::~FGSwapAction ()
401 {
402 }
403
404 void
405 FGSwapAction::doAction ()
406 {
407   float val = _value1->getFloatValue();
408   _value1->setDoubleValue(_value2->getFloatValue());
409   _value2->setDoubleValue(val);
410 }
411
412
413 \f
414 ////////////////////////////////////////////////////////////////////////
415 // Implementation of FGToggleAction.
416 ////////////////////////////////////////////////////////////////////////
417
418 FGToggleAction::FGToggleAction (int button, int x, int y, int w, int h,
419                                 SGValue * value)
420   : FGPanelAction(button, x, y, w, h), _value(value)
421 {
422 }
423
424 FGToggleAction::~FGToggleAction ()
425 {
426 }
427
428 void
429 FGToggleAction::doAction ()
430 {
431   _value->setBoolValue(!(_value->getBoolValue()));
432 }
433
434
435 \f
436 ////////////////////////////////////////////////////////////////////////
437 // Implementation of FGPanelTransformation.
438 ////////////////////////////////////////////////////////////////////////
439
440 FGPanelTransformation::FGPanelTransformation ()
441 {
442 }
443
444 FGPanelTransformation::~FGPanelTransformation ()
445 {
446 }
447
448
449 \f
450 ////////////////////////////////////////////////////////////////////////
451 // Implementation of FGPanelInstrument.
452 ////////////////////////////////////////////////////////////////////////
453
454
455 FGPanelInstrument::FGPanelInstrument ()
456 {
457   setPosition(0, 0);
458   setSize(0, 0);
459 }
460
461 FGPanelInstrument::FGPanelInstrument (int x, int y, int w, int h)
462 {
463   setPosition(x, y);
464   setSize(w, h);
465 }
466
467 FGPanelInstrument::~FGPanelInstrument ()
468 {
469   for (action_list_type::iterator it = _actions.begin();
470        it != _actions.end();
471        it++) {
472     delete *it;
473     *it = 0;
474   }
475 }
476
477 void
478 FGPanelInstrument::setPosition (int x, int y)
479 {
480   _x = x;
481   _y = y;
482 }
483
484 void
485 FGPanelInstrument::setSize (int w, int h)
486 {
487   _w = w;
488   _h = h;
489 }
490
491 int
492 FGPanelInstrument::getXPos () const
493 {
494   return _x;
495 }
496
497 int
498 FGPanelInstrument::getYPos () const
499 {
500   return _y;
501 }
502
503 int
504 FGPanelInstrument::getWidth () const
505 {
506   return _w;
507 }
508
509 int
510 FGPanelInstrument::getHeight () const
511 {
512   return _h;
513 }
514
515 void
516 FGPanelInstrument::addAction (FGPanelAction * action)
517 {
518   _actions.push_back(action);
519 }
520
521                                 // Coordinates relative to centre.
522 bool
523 FGPanelInstrument::doMouseAction (int button, int x, int y)
524 {
525   action_list_type::iterator it = _actions.begin();
526   action_list_type::iterator last = _actions.end();
527   for ( ; it != last; it++) {
528     if ((*it)->inArea(button, x, y)) {
529       (*it)->doAction();
530       return true;
531     }
532   }
533   return false;
534 }
535
536
537 \f
538 ////////////////////////////////////////////////////////////////////////
539 // Implementation of FGLayeredInstrument.
540 ////////////////////////////////////////////////////////////////////////
541
542 FGLayeredInstrument::FGLayeredInstrument (int x, int y, int w, int h)
543   : FGPanelInstrument(x, y, w, h)
544 {
545 }
546
547 FGLayeredInstrument::~FGLayeredInstrument ()
548 {
549   for (layer_list::iterator it = _layers.begin(); it != _layers.end(); it++) {
550     delete *it;
551     *it = 0;
552   }
553 }
554
555 void
556 FGLayeredInstrument::draw ()
557 {
558   for (int i = 0; i < (int)_layers.size(); i++) {
559     glPushMatrix();
560     glTranslatef(0.0, 0.0, (i / 100.0) + 0.1);
561     _layers[i]->draw();
562     glPopMatrix();
563   }
564 }
565
566 int
567 FGLayeredInstrument::addLayer (FGInstrumentLayer *layer)
568 {
569   int n = _layers.size();
570   if (layer->getWidth() == -1) {
571     layer->setWidth(getWidth());
572   }
573   if (layer->getHeight() == -1) {
574     layer->setHeight(getHeight());
575   }
576   _layers.push_back(layer);
577   return n;
578 }
579
580 int
581 FGLayeredInstrument::addLayer (FGCroppedTexture &texture,
582                                int w, int h)
583 {
584   return addLayer(new FGTexturedLayer(texture, w, h));
585 }
586
587 void
588 FGLayeredInstrument::addTransformation (FGPanelTransformation * transformation)
589 {
590   int layer = _layers.size() - 1;
591   _layers[layer]->addTransformation(transformation);
592 }
593
594
595 \f
596 ////////////////////////////////////////////////////////////////////////
597 // Implementation of FGInstrumentLayer.
598 ////////////////////////////////////////////////////////////////////////
599
600 FGInstrumentLayer::FGInstrumentLayer (int w, int h)
601   : _w(w),
602     _h(h)
603 {
604 }
605
606 FGInstrumentLayer::~FGInstrumentLayer ()
607 {
608   for (transformation_list::iterator it = _transformations.begin();
609        it != _transformations.end();
610        it++) {
611     delete *it;
612     *it = 0;
613   }
614 }
615
616 void
617 FGInstrumentLayer::transform () const
618 {
619   transformation_list::const_iterator it = _transformations.begin();
620   transformation_list::const_iterator last = _transformations.end();
621   while (it != last) {
622     FGPanelTransformation *t = *it;
623     float val = (t->value == 0 ? 0.0 : t->value->getFloatValue());
624     if (val < t->min) {
625       val = t->min;
626     } else if (val > t->max) {
627       val = t->max;
628     }
629     val = val * t->factor + t->offset;
630
631     switch (t->type) {
632     case FGPanelTransformation::XSHIFT:
633       glTranslatef(val, 0.0, 0.0);
634       break;
635     case FGPanelTransformation::YSHIFT:
636       glTranslatef(0.0, val, 0.0);
637       break;
638     case FGPanelTransformation::ROTATION:
639       glRotatef(-val, 0.0, 0.0, 1.0);
640       break;
641     }
642     it++;
643   }
644 }
645
646 void
647 FGInstrumentLayer::addTransformation (FGPanelTransformation * transformation)
648 {
649   _transformations.push_back(transformation);
650 }
651
652
653 \f
654 ////////////////////////////////////////////////////////////////////////
655 // Implementation of FGTexturedLayer.
656 ////////////////////////////////////////////////////////////////////////
657
658
659 FGTexturedLayer::FGTexturedLayer (const FGCroppedTexture &texture, int w, int h)
660   : FGInstrumentLayer(w, h)
661 {
662   setTexture(texture);
663 }
664
665
666 FGTexturedLayer::~FGTexturedLayer ()
667 {
668 }
669
670
671 void
672 FGTexturedLayer::draw ()
673 {
674   int w2 = _w / 2;
675   int h2 = _h / 2;
676
677   transform();
678   glBindTexture(GL_TEXTURE_2D, _texture.getTexture()->getHandle());
679   glBegin(GL_POLYGON);
680
681                                 // From Curt: turn on the panel
682                                 // lights after sundown.
683   if ( cur_light_params.sun_angle * RAD_TO_DEG < 95.0 ) {
684       glColor4fv( cur_light_params.scene_diffuse );
685   } else {
686       glColor4f(0.7, 0.2, 0.2, 1.0);
687   }
688
689
690   glTexCoord2f(_texture.getMinX(), _texture.getMinY()); glVertex2f(-w2, -h2);
691   glTexCoord2f(_texture.getMaxX(), _texture.getMinY()); glVertex2f(w2, -h2);
692   glTexCoord2f(_texture.getMaxX(), _texture.getMaxY()); glVertex2f(w2, h2);
693   glTexCoord2f(_texture.getMinX(), _texture.getMaxY()); glVertex2f(-w2, h2);
694   glEnd();
695 }
696
697
698 \f
699 ////////////////////////////////////////////////////////////////////////
700 // Implementation of FGTextLayer.
701 ////////////////////////////////////////////////////////////////////////
702
703 FGTextLayer::FGTextLayer (int w, int h)
704   : FGInstrumentLayer(w, h), _pointSize(14.0)
705 {
706   _then.stamp();
707   _color[0] = _color[1] = _color[2] = 0.0;
708   _color[3] = 1.0;
709 }
710
711 FGTextLayer::~FGTextLayer ()
712 {
713   chunk_list::iterator it = _chunks.begin();
714   chunk_list::iterator last = _chunks.end();
715   for ( ; it != last; it++) {
716     delete *it;
717   }
718 }
719
720 void
721 FGTextLayer::draw ()
722 {
723   glPushMatrix();
724   glColor4fv(_color);
725   transform();
726   text_renderer.setFont(guiFntHandle);
727   text_renderer.setPointSize(_pointSize);
728   text_renderer.begin();
729   text_renderer.start3f(0, 0, 0);
730
731   _now.stamp();
732   if (_now - _then > 100000) {
733     recalc_value();
734     _then = _now;
735   }
736   text_renderer.puts((char *)(_value.c_str()));
737
738   text_renderer.end();
739   glColor4f(1.0, 1.0, 1.0, 1.0);        // FIXME
740   glPopMatrix();
741 }
742
743 void
744 FGTextLayer::addChunk (FGTextLayer::Chunk * chunk)
745 {
746   _chunks.push_back(chunk);
747 }
748
749 void
750 FGTextLayer::setColor (float r, float g, float b)
751 {
752   _color[0] = r;
753   _color[1] = g;
754   _color[2] = b;
755   _color[3] = 1.0;
756 }
757
758 void
759 FGTextLayer::setPointSize (float size)
760 {
761   _pointSize = size;
762 }
763
764 void
765 FGTextLayer::setFont(fntFont * font)
766 {
767   text_renderer.setFont(font);
768 }
769
770
771 void
772 FGTextLayer::recalc_value () const
773 {
774   _value = "";
775   chunk_list::const_iterator it = _chunks.begin();
776   chunk_list::const_iterator last = _chunks.end();
777   for ( ; it != last; it++) {
778     _value += (*it)->getValue();
779   }
780 }
781
782
783 \f
784 ////////////////////////////////////////////////////////////////////////
785 // Implementation of FGTextLayer::Chunk.
786 ////////////////////////////////////////////////////////////////////////
787
788 FGTextLayer::Chunk::Chunk (const string &text, const string &fmt)
789   : _type(FGTextLayer::TEXT), _fmt(fmt)
790 {
791   _text = text;
792   if (_fmt == "") 
793     _fmt = "%s";
794 }
795
796 FGTextLayer::Chunk::Chunk (ChunkType type, const SGValue * value,
797                            const string &fmt, float mult)
798   : _type(type), _fmt(fmt), _mult(mult)
799 {
800   if (_fmt == "") {
801     if (type == TEXT_VALUE)
802       _fmt = "%s";
803     else
804       _fmt = "%.2f";
805   }
806   _value = value;
807 }
808
809 const char *
810 FGTextLayer::Chunk::getValue () const
811 {
812   switch (_type) {
813   case TEXT:
814     sprintf(_buf, _fmt.c_str(), _text.c_str());
815     return _buf;
816   case TEXT_VALUE:
817     sprintf(_buf, _fmt.c_str(), _value->getStringValue().c_str());
818     break;
819   case DOUBLE_VALUE:
820     sprintf(_buf, _fmt.c_str(), _value->getFloatValue() * _mult);
821     break;
822   }
823   return _buf;
824 }
825
826
827 \f
828 ////////////////////////////////////////////////////////////////////////
829 // Implementation of FGSwitchLayer.
830 ////////////////////////////////////////////////////////////////////////
831
832 FGSwitchLayer::FGSwitchLayer (int w, int h, const SGValue * value,
833                               FGInstrumentLayer * layer1,
834                               FGInstrumentLayer * layer2)
835   : FGInstrumentLayer(w, h), _value(value), _layer1(layer1), _layer2(layer2)
836 {
837 }
838
839 FGSwitchLayer::~FGSwitchLayer ()
840 {
841   delete _layer1;
842   delete _layer2;
843 }
844
845 void
846 FGSwitchLayer::draw ()
847 {
848   transform();
849   if (_value->getBoolValue()) {
850     _layer1->draw();
851   } else {
852     _layer2->draw();
853   }
854 }
855
856 \f
857 // end of panel.cxx