G4OpenInventorXtExaminerViewer.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * License and Disclaimer                                           *
00004 // *                                                                  *
00005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
00006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
00007 // * conditions of the Geant4 Software License,  included in the file *
00008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
00009 // * include a list of copyright holders.                             *
00010 // *                                                                  *
00011 // * Neither the authors of this software system, nor their employing *
00012 // * institutes,nor the agencies providing financial support for this *
00013 // * work  make  any representation or  warranty, express or implied, *
00014 // * regarding  this  software system or assume any liability for its *
00015 // * use.  Please see the license in the file  LICENSE  and URL above *
00016 // * for the full disclaimer and the limitation of liability.         *
00017 // *                                                                  *
00018 // * This  code  implementation is the result of  the  scientific and *
00019 // * technical work of the GEANT4 collaboration.                      *
00020 // * By using,  copying,  modifying or  distributing the software (or *
00021 // * any work based  on the software)  you  agree  to acknowledge its *
00022 // * use  in  resulting  scientific  publications,  and indicate your *
00023 // * acceptance of all terms of the Geant4 Software license.          *
00024 // ********************************************************************
00025 //
00026 //
00027 // Open Inventor Xt Extended Viewer - 30 Oct 2012
00028 // Rastislav Ondrasek, Pierre-Luc Gagnon, Frederick Jones TRIUMF
00029 
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <string>
00033 #include <sstream>
00034 #include <cmath>
00035 #include <iostream>
00036 #include <iomanip>
00037 #include <algorithm> // For using sort on a vector
00038 #include <X11/keysym.h>
00039 
00040 #include <Xm/Xm.h>
00041 #include <Xm/Text.h>
00042 #include <Xm/List.h>
00043 #include <Xm/MessageB.h>
00044 #include <Xm/PushB.h>
00045 #include <Xm/ToggleB.h>
00046 #include <Xm/CascadeB.h>
00047 #include <Xm/ArrowBG.h>
00048 #include <Xm/Form.h>
00049 #include <Xm/RowColumn.h>
00050 #include <Xm/FileSB.h>
00051 #include <Xm/SelectioB.h>
00052 #include <Xm/Protocols.h>
00053 #include <Xm/SeparatoG.h>
00054 #include <Xm/DialogS.h>  
00055 #include <Xm/PanedW.h>
00056 #include <Xm/LabelG.h>
00057 #include <Xm/Scale.h>
00058 #include <Xm/DrawingA.h>
00059 
00060 #include <Inventor/Xt/SoXt.h>
00061 //#include <Inventor/Xt/SoXtInternal.h>
00062 #include <Inventor/Xt/SoXtCursor.h>
00063 #include <Inventor/events/SoKeyboardEvent.h>
00064 #include <Inventor/events/SoMouseButtonEvent.h>
00065 #include <Inventor/events/SoLocation2Event.h>
00066 #include <Inventor/nodes/SoSeparator.h>
00067 #include <Inventor/nodes/SoOrthographicCamera.h>
00068 #include <Inventor/nodes/SoPerspectiveCamera.h>
00069 #include <Inventor/nodes/SoEventCallback.h>
00070 #include <Inventor/nodes/SoLineSet.h>
00071 #include <Inventor/nodes/SoMaterial.h>
00072 #include <Inventor/errors/SoDebugError.h>
00073 #include <Inventor/SoPickedPoint.h>
00074 #include <Inventor/actions/SoWriteAction.h>
00075 
00076 #include "G4OpenInventorXtExaminerViewer.hh"
00077 #include "wheelmouse.h"  // To use mouse scrolling in dialogs
00078 #include "SoXtInternal.h"
00079 #include <Inventor/sensors/SoTimerSensor.h>   // Animation
00080 #include <Inventor/sensors/SoNodeSensor.h>    // Detect start of run
00081 #include "saveViewPt.h"
00082 #include "console.h"
00083 #include "favorites.h"
00084 
00085 #include "Geant4_SoPolyhedron.h"
00086 //#include "G4RunManager.hh"
00087 //#include "G4Run.hh"
00088 #include "G4TrajectoryPoint.hh"
00089 #include "G4AttHolder.hh"
00090 #include "G4AttCheck.hh"
00091 
00092 #include <Inventor/nodes/SoCallback.h>
00093 #include <Inventor/nodes/SoSwitch.h>
00094 #include <Inventor/nodes/SoScale.h>
00095 #include <Inventor/nodes/SoTranslation.h>
00096 #include <Inventor/actions/SoSearchAction.h>
00097 #include <Inventor/actions/SoGetBoundingBoxAction.h>
00098 
00099 #include <Inventor/nodes/SoCoordinate3.h>
00100 // For rendering distance during animation:
00101 #include <Inventor/nodes/SoText2.h>
00102 #include <Inventor/nodes/SoFont.h>
00103 #include <Inventor/nodes/SoPointSet.h>
00104 #include <Inventor/nodes/SoDrawStyle.h>
00105 #include <Inventor/nodes/SoBaseColor.h>
00106 
00107 // For searching for nodes within kits:
00108 #include <Inventor/nodekits/SoBaseKit.h>
00109 
00110 G4OpenInventorXtExaminerViewer* G4OpenInventorXtExaminerViewer::viewer = 0;
00111 
00112 static const char* thisClassName = "G4OpenInventorXtExaminerViewer";
00113  
00114 #define MIN_SPEED  2.1        // Lower number means faster
00115 #define START_STEP 0.3
00116 #define SPEED_INDICATOR_STEP 0.045
00117 #define MAX_SPEED_INDICATOR  0.81
00118 // Number of steps 90 degree rotation around an element is split into
00119 #define ROT_CNT 6
00120 
00121 // Public constructor
00122 G4OpenInventorXtExaminerViewer::G4OpenInventorXtExaminerViewer(Widget parent,
00123                 const char *name, SbBool embed,
00124                 SoXtFullViewer::BuildFlag flag, SoXtViewer::Type type) :
00125    SoXtExaminerViewer(parent, name, embed, flag, type, FALSE)
00126 {
00127 // Tell GLWidget not to build just yet
00128    this->constructor(TRUE);
00129 }
00130 
00131 // Protected constructor for classes deriving from this viewer.
00132 G4OpenInventorXtExaminerViewer::G4OpenInventorXtExaminerViewer(Widget parent,
00133                 const char *name, SbBool embed,
00134                 SoXtFullViewer::BuildFlag flag, SoXtViewer::Type type,
00135                 SbBool build) :
00136    SoXtExaminerViewer(parent, name, embed, flag, type, FALSE)
00137 {
00138    this->constructor(build);
00139 }
00140 
00141 // Called by all constructors to set up widgets and initialize member fields.
00142 void G4OpenInventorXtExaminerViewer::constructor(const SbBool build)
00143 {
00144    setClassName(thisClassName);
00145 
00146    hookBeamOn = new HookEventProcState(this);
00147    this->newEvents = false;
00148 
00149    fileName = ".bookmarkFile"; // Default viewpoint file name
00150    viewPtIdx = -1; // index of the most recent viewpoint in viewPtList vector
00151    animateSensor = new SoTimerSensor(
00152                        G4OpenInventorXtExaminerViewer::animateSensorCB, this);
00153    animateSensorRotation = new SoTimerSensor(
00154                G4OpenInventorXtExaminerViewer::animateSensorRotationCB, this);
00155    animateBtwPtsPeriod = MIN_SPEED;
00156    currentState = GENERAL;
00157    myCam = new SoPerspectiveCamera;
00158    MAX_VP_IDX = 3;
00159    MAX_VP_NAME = 35; // Max length of a viewpoint name, padded with spaces
00160    rotCnt = ROT_CNT; // For 90 degree rotations
00161    curViewPtName = new char[MAX_VP_NAME + 1];
00162    left_right = up_down = 0; // For movements around the beam during animation
00163    speedStep = START_STEP; // For smoother animation speed increase/decrease
00164    rotUpVec = false; // Used during scene element rotations
00165    step = 1;    //By default
00166    // Used for moving along the beam with the
00167    // mouse instead of rotating the view
00168    lshiftdown = rshiftdown = false;
00169    // Used for rotating the view with the camera
00170    // staying in place
00171    lctrldown = rctrldown = false;
00172    // Used to send abbreviated output to the console when
00173    abbrOutputFlag = false;
00174    pickRefPathFlag = false;
00175    prevColorField = NULL;
00176    warningFlag = false; // We come from the warning dialog
00177    viewer = this;
00178    openFileDialog = newFileDialog = listsDialog = (Widget) NULL;
00179    loadRefCoordsDialog = saveRefCoordsDialog = NULL;
00180    loadSceneGraphDialog = saveSceneGraphDialog = NULL;
00181    myElementList = NULL;
00182 
00183    newSceneGraph = NULL;
00184    zcoordSetFlag = false;
00185 
00187    searcher = NULL;
00188    // Used in animation; progressively scaled for gradual speed change
00189    maxSpeed = 0.0f;
00190 
00191    static const char * superimposed[] = {
00192       "#Inventor V2.1 ascii", "",
00193       "Separator ",
00194       "{",
00195       " MaterialBinding ",
00196       " {",
00197       "         value OVERALL",
00198       " }",
00199       "         OrthographicCamera ",
00200       " {",
00201       "         height 1",
00202       "         nearDistance 0",
00203       "         farDistance 1",
00204       " }",
00205       "         DEF soxt->callback Callback { }",
00206       "         Separator ",
00207       " {",
00208       "         DEF soxt->translation Translation ",
00209       "         {",
00210       "                 translation 0 0 0",
00211       "     }",
00212       "     DEF soxt->scale Scale ",
00213       "         {",
00214       "                 scaleFactor 1 1 1",
00215       "     }",
00216       "         DEF soxt->geometry Coordinate3 ",
00217       "         {",
00218       "             point ",
00219       "                 [",
00220       "                         -0.81   -0.04   0,      -0.81   0               0,",
00221       "                 -0.81   0.04    0,      0       -0.04   0,",
00222       "                 0       0       0,  0       0.04        0,",
00223       "                 0.81    -0.04   0,  0.81        0           0,",
00224       "                 0.81    0.04    0,",
00225       "                 0       0.02    0,", // idx 9
00226       "                 0.81    0.02    0,  0.81        -0.02   0,",
00227       "                 0       -0.02   0,",
00228       "                 0       0.01    0,", // idx 13
00229       "                 0.4     0.01    0,  0.4         -0.01   0,",
00230       "                 0       -0.01   0",
00231       "                 ]",
00232       "         }",
00233       // current speed indicator (outline)
00234       "         DEF soxt->animSpeedOutlineSwitch Switch ",
00235       "         {",
00236       "                 whichChild -3",
00237       "                 Material ",
00238       "                 {",
00239       "                    emissiveColor 0 0 0",
00240       "             }",
00241       "                 IndexedFaceSet ",
00242       "                 {",
00243       "                 coordIndex ",
00244       "                         [",
00245       "                                 12, 11, 10, 9, -1",
00246       "                         ]",
00247       "         }",
00248       "                  }",
00249       // the coordinate system
00250       "         DEF soxt->axisSwitch Switch ",
00251       "         {",
00252       "                 whichChild -3",
00253       "                 BaseColor ",
00254       "                 {",
00255       "                     rgb 1 1 1",
00256       "                 }",
00257       "                 IndexedLineSet ",
00258       "                 {",
00259       "                         coordIndex ",
00260       "                         [",
00261       "                                 0, 2, -1,",
00262       "                                 3, 5, -1,",
00263       "                                 6, 8, -1,",
00264       "                                 1, 7, -1",
00265       "                         ]",
00266       "                     }",
00267       "                 }",
00268       // current speed indicator
00269       "         DEF soxt->animSpeedSwitch Switch ",
00270       "         {",
00271       "                     whichChild -3",
00272       "                 Material ",
00273       "                 {",
00274       "                 emissiveColor 0 1 0",
00275       "         }",
00276       "                 IndexedFaceSet ",
00277       "                 {",
00278       "                 coordIndex ",
00279       "                         [",
00280       "                                 16, 15, 14, 13, -1",
00281       "                         ]",
00282       "                 }",
00283       "         }",
00284       "         }",
00285       // For displaying either z position (during animation) or current viewpoint name
00286       " DEF soxt->curInfoSwitch Switch ",
00287       " {",
00288       "         whichChild -3",
00289       "         DEF soxt->curInfoTrans Translation ",
00290       "         {",
00291       "                 translation 10 20 30    ",
00292       "         }",
00293       "         DEF soxt->curInfoFont Font ",
00294       "         {",
00295       "                 name defaultFont:Bold",
00296       "                 size 16",
00297       "                 }",
00298       "         DEF soxt->curInfoText Text2 ",
00299       "         {",
00300       "                 string Hello",
00301       "     }",
00302       " }",
00303       // Need to use different fields for mouseover
00304       // because newlines are ignored when the scene is rendered
00305       " Separator ",
00306       " {",
00307       "         DEF soxt->mouseOverTransLogName Translation ",
00308       "         {",
00309       "                 translation 0 0 0    ",
00310       "         }",
00311       "         DEF soxt->mouseOverFontLogName Font ",
00312       "         {",
00313       "                 name defaultFont:Bold",
00314       "                 size 16",
00315       "                 }",
00316       "         DEF soxt->mouseOverTextLogName Text2 { } ",
00317       " }",
00318       " Separator ",
00319       " {",
00320       "         DEF soxt->mouseOverTransSolid Translation ",
00321       "         {",
00322       "                 translation 0 0 0    ",
00323       "         }",
00324       "         DEF soxt->mouseOverFontSolid Font ",
00325       "         {",
00326       "                 name defaultFont:Bold",
00327       "                 size 16",
00328       "                 }",
00329       "         DEF soxt->mouseOverTextSolid Text2 { } ",
00330       " }",
00331       " Separator ",
00332       " {",
00333       "         DEF soxt->mouseOverTransMaterial Translation ",
00334       "         {",
00335       "                 translation 0 0 0    ",
00336       "         }",
00337       "         DEF soxt->mouseOverFontMaterial Font ",
00338       "         {",
00339       "                 name defaultFont:Bold",
00340       "                 size 16",
00341       "                 }",
00342       "         DEF soxt->mouseOverTextMaterial Text2 { } ",
00343       " }",
00344       " Separator ",
00345       " {",
00346       "         DEF soxt->mouseOverTransZPos Translation ",
00347       "         {",
00348       "                 translation 0 0 0    ",
00349       "         }",
00350       "         DEF soxt->mouseOverFontZPos Font ",
00351       "         {",
00352       "                 name defaultFont:Bold",
00353       "                 size 16",
00354       "                 }",
00355       "         DEF soxt->mouseOverTextZPos Text2 { } ",
00356       " }",
00357       "}", NULL
00358    };
00359 
00360    int i, bufsize;
00361    for (i = bufsize = 0; superimposed[i]; i++)
00362       bufsize += strlen(superimposed[i]) + 1;
00363    char * buf = new char[bufsize + 1];
00364    for (i = bufsize = 0; superimposed[i]; i++) {
00365       strcpy(buf + bufsize, superimposed[i]);
00366       bufsize += strlen(superimposed[i]);
00367       buf[bufsize] = '\n';
00368       bufsize++;
00369    }
00370    SoInput * input = new SoInput;
00371    input->setBuffer(buf, bufsize);
00372    SbBool ok = SoDB::read(input, this->superimposition);
00373    (void)ok;   // FWJ added to avoid compiler warning
00374    assert(ok);
00375    delete input;
00376    delete[] buf;
00377    this->superimposition->ref();
00378 
00379    this->sscale = (SoScale *) this->getSuperimpositionNode(
00380                                  this->superimposition, "soxt->scale");
00381    this->stranslation = (SoTranslation *) this->getSuperimpositionNode(
00382                                  this->superimposition, "soxt->translation");
00383    this->sgeometry = (SoCoordinate3 *) this->getSuperimpositionNode(
00384                                  this->superimposition, "soxt->geometry");
00385    this->axisSwitch = (SoSwitch *) this->getSuperimpositionNode(
00386                                  this->superimposition, "soxt->axisSwitch");
00387    this->animSpeedOutlineSwitch = (SoSwitch *) this->getSuperimpositionNode(
00388                        this->superimposition, "soxt->animSpeedOutlineSwitch");
00389    this->animSpeedSwitch = (SoSwitch *) this->getSuperimpositionNode(
00390                        this->superimposition, "soxt->animSpeedSwitch");
00391    this->curInfoSwitch = (SoSwitch *) this->getSuperimpositionNode(
00392                              this->superimposition, "soxt->curInfoSwitch");
00393    this->curInfoTrans = (SoTranslation *) this->getSuperimpositionNode(
00394                              this->superimposition, "soxt->curInfoTrans");
00395    this->curInfoFont = (SoFont *) this->getSuperimpositionNode(
00396                              this->superimposition, "soxt->curInfoFont");
00397    this->curInfoText = (SoText2 *) this->getSuperimpositionNode(
00398                              this->superimposition, "soxt->curInfoText");
00399    this->mouseOverTransLogName = (SoTranslation*)this->getSuperimpositionNode(
00400                    this->superimposition, "soxt->mouseOverTransLogName");
00401    this->mouseOverFontLogName = (SoFont *) this->getSuperimpositionNode(
00402                    this->superimposition, "soxt->mouseOverFontLogName");
00403    this->mouseOverTextLogName = (SoText2 *) this->getSuperimpositionNode(
00404                    this->superimposition, "soxt->mouseOverTextLogName");
00405    this->mouseOverTransSolid = (SoTranslation *) this->getSuperimpositionNode(
00406                    this->superimposition, "soxt->mouseOverTransSolid");
00407    this->mouseOverFontSolid = (SoFont *) this->getSuperimpositionNode(
00408                    this->superimposition, "soxt->mouseOverFontSolid");
00409    this->mouseOverTextSolid = (SoText2 *) this->getSuperimpositionNode(
00410                    this->superimposition, "soxt->mouseOverTextSolid");
00411    this->mouseOverTransMaterial = (SoTranslation*)this->getSuperimpositionNode(
00412                    this->superimposition, "soxt->mouseOverTransMaterial");
00413    this->mouseOverFontMaterial = (SoFont *) this->getSuperimpositionNode(
00414                    this->superimposition, "soxt->mouseOverFontMaterial");
00415    this->mouseOverTextMaterial = (SoText2 *) this->getSuperimpositionNode(
00416                    this->superimposition, "soxt->mouseOverTextMaterial");
00417    this->mouseOverTransZPos = (SoTranslation *) this->getSuperimpositionNode(
00418                    this->superimposition, "soxt->mouseOverTransZPos");
00419    this->mouseOverFontZPos = (SoFont *) this->getSuperimpositionNode(
00420                    this->superimposition, "soxt->mouseOverFontZPos");
00421    this->mouseOverTextZPos = (SoText2 *) this->getSuperimpositionNode(
00422                    this->superimposition, "soxt->mouseOverTextZPos");
00423 
00424    SoCallback * cb = (SoCallback *) this->getSuperimpositionNode(
00425                    this->superimposition, "soxt->callback");
00426    cb->setCallback(superimpositionCB, this);
00427 
00428    this->addSuperimposition(this->superimposition);
00429    this->setSuperimpositionEnabled(this->superimposition, FALSE);
00430    axisSwitch->whichChild.setValue(SO_SWITCH_NONE);
00431    animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE);
00432    animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE);
00433 
00435 
00436    // Build everything else like the parent viewer does
00437    if (build) {
00438       Widget w = buildWidget(getParentWidget());
00439       setBaseWidget(w);
00440 
00441       // Make this window a little bigger because of the extra buttons
00442       // FWJ but it is already set to 600x600 by vis/open
00443       //      setSize(SbVec2s(500, 550));
00444    }
00445 
00446 }
00447 
00448 
00449 // Static function that returns the pointer to G4OpenInventorXtExaminerViewer
00450 G4OpenInventorXtExaminerViewer *G4OpenInventorXtExaminerViewer::getObject()
00451 {
00452    if (!viewer)
00453       new G4OpenInventorXtExaminerViewer();
00454    return viewer;
00455 }
00456 
00457 
00458 // This method locates a named node in the superimposed or original scene.
00459 SoNode *
00460 G4OpenInventorXtExaminerViewer::getSuperimpositionNode(SoNode *root,
00461                                                      const char * name)
00462 {
00463    if (!this->searcher)
00464       this->searcher = new SoSearchAction;
00465    searcher->reset();
00466    searcher->setName(SbName(name));
00467    searcher->setInterest(SoSearchAction::FIRST);
00468    searcher->setSearchingAll(TRUE);
00469    searcher->apply(root);
00470    assert(searcher->getPath());
00471    return searcher->getPath()->getTail();
00472 }
00473 
00474 
00475 void G4OpenInventorXtExaminerViewer::superimpositionCB(void * closure,
00476                                                      SoAction * action)
00477 {
00478    if (closure)
00479       ((G4OpenInventorXtExaminerViewer*)closure)->superimpositionEvent(action);
00480 }
00481 
00482 
00483 // Renders and positions speed indicator and longitudinal
00484 // distance/viewpoint name on the drawing canvas
00485 void G4OpenInventorXtExaminerViewer::superimpositionEvent(SoAction * action)
00486 {
00487 
00488    if (!action->isOfType(SoGLRenderAction::getClassTypeId()))
00489       return;
00490    SbViewportRegion vpRegion =
00491       ((SoGLRenderAction *) action)->getViewportRegion();
00492    SbVec2s viewportSize = vpRegion.getViewportSizePixels();
00493 
00494    float aspect = float(viewportSize[0]) / float(viewportSize[1]);
00495    float factorx = 1.0f / float(viewportSize[1]) * 220.0f;
00496    float factory = factorx;
00497 
00498    if (aspect > 1.0f) {
00499       this->stranslation->translation.setValue(SbVec3f(0.0f, -0.4f, 0.0f));
00500    } else {
00501       this->stranslation->translation.setValue(
00502                        SbVec3f(0.0f, -0.4f / aspect, 0.0f));
00503       factorx /= aspect;
00504       factory /= aspect;
00505    }
00506    if (viewportSize[0] > 500)
00507       factorx *= 500.0f / 400.0f;
00508    else
00509       factorx *= float(viewportSize[0]) / 400.0f;
00510    this->sscale->scaleFactor.setValue(SbVec3f(factorx, factory, 1.0f));
00511 
00512    float xInfo, yInfo, xMouseLogName, yMouseLogName, xMouseSolid, yMouseSolid,
00513       xMouseMaterial, yMouseMaterial, xMouseZPos, yMouseZPos;
00514    xInfo = -.45;
00515    yInfo = .45;
00516    xMouseLogName = 0.0;
00517    yMouseLogName = -.75;
00518    xMouseSolid = 0.0;
00519    yMouseSolid = -.78;
00520    xMouseMaterial = 0.0;
00521    yMouseMaterial = -.81;
00522    xMouseZPos = 0.0;
00523    yMouseZPos = -.84;
00524 
00525    if (aspect > 1.0f) {
00526       xInfo *= aspect;
00527       xMouseSolid *= aspect;
00528       xMouseMaterial *= aspect;
00529       this->curInfoTrans->translation.setValue(SbVec3f(xInfo, yInfo, 0.0));
00530       this->mouseOverTransLogName->translation.setValue(
00531                         SbVec3f(xMouseLogName, yMouseLogName, 0.0));
00532       this->mouseOverTransSolid->translation.setValue(
00533                         SbVec3f(xMouseSolid, yMouseSolid, 0.0));
00534       this->mouseOverTransMaterial->translation.setValue(
00535                         SbVec3f(xMouseMaterial, yMouseMaterial, 0.0));
00536       this->mouseOverTransZPos->translation.setValue(
00537                         SbVec3f(xMouseZPos, yMouseZPos, 0.0));
00538    } else {
00539       yInfo /= aspect;
00540       yMouseSolid /= aspect;
00541       yMouseMaterial /= aspect;
00542       this->curInfoTrans->translation.setValue(SbVec3f(xInfo, yInfo, 0.0));
00543       this->mouseOverTransLogName->translation.setValue(
00544                         SbVec3f(xMouseLogName, yMouseLogName, 0.0));
00545       this->mouseOverTransSolid->translation.setValue(
00546                         SbVec3f(xMouseSolid, yMouseSolid, 0.0));
00547       this->mouseOverTransMaterial->translation.setValue(
00548                         SbVec3f(xMouseMaterial, yMouseMaterial, 0.0));
00549       this->mouseOverTransZPos->translation.setValue(
00550                         SbVec3f(xMouseZPos, yMouseZPos, 0.0));
00551    }
00552 
00553    if (currentState == VIEWPOINT) { // Displaying viewpoint name
00554       this->curInfoFont->size.setValue(15);
00555       this->curInfoFont->name.setValue("defaultFont:Italic");
00556       this->curInfoText->string.setValue(SbString(curViewPtName));
00557    }
00558    else if(currentState == GENERAL) { // Displaying longitudinal distance
00559       this->curInfoFont->size.setValue(16);
00560       this->curInfoFont->name.setValue("defaultFont:Bold");
00561       this->curInfoText->string.setValue(SbString(""));
00562    }
00563    else {
00564       if (refParticleIdx < (int) refParticleTrajectory.size() - 1) {
00565          this->curInfoFont->size.setValue(16);
00566          this->curInfoFont->name.setValue("defaultFont:Bold");
00567 
00568          char zPos[20];
00569          sprintf(zPos, "%7.2f [m]", refZPositions[refParticleIdx] / 1000);
00570 
00571          this->curInfoText->string.setValue(SbString(zPos));
00572       }
00573    }
00574 }
00575 
00576 
00577 G4OpenInventorXtExaminerViewer::~G4OpenInventorXtExaminerViewer()
00578 {
00579    if (superimposition != NULL) {
00580       removeSuperimposition(superimposition);
00581       superimposition->unref();
00582       superimposition = NULL;
00583    }
00584    if (animateSensor->isScheduled())
00585       animateSensor->unschedule();
00586    delete animateSensor;
00587    delete sceneChangeSensor;
00588 
00589    delete[] curViewPtName;
00590    delete searcher;
00591 
00592    viewer = 0;
00593 }
00594 
00595 
00596 // Adds a menu bar and a few menu items to the viewer.
00597 Widget G4OpenInventorXtExaminerViewer::buildWidget(Widget parent)
00598 {
00599    Widget shell;
00600    Atom WM_DELETE_WINDOW;
00601 
00602    if (!parent)
00603       SoDebugError::post("G4OpenInventorXtExaminerViewer::buildWidget", "Error: Parent is null.");
00604 
00605    Arg args[10];
00606    XtSetArg(args[0], XmNtopAttachment, XmATTACH_FORM);
00607    XtSetArg(args[1], XmNleftAttachment, XmATTACH_FORM);
00608    XtSetArg(args[2], XmNrightAttachment, XmATTACH_FORM);
00609    XtSetArg(args[3], XmNbottomAttachment, XmATTACH_FORM);
00610    Widget form = XmCreateForm(parent, (char *) "Form", args, 4);
00611    XtManageChild(form);
00612 
00613    shell = XtParent(form);
00614    WM_DELETE_WINDOW = XInternAtom(XtDisplay(parent), "WM_DELETE_WINDOW",
00615                                   False);
00616    XmAddWMProtocolCallback(shell, WM_DELETE_WINDOW,
00617                            (XtCallbackProc)closeMainWindowCB, this);
00618 
00619    XtSetArg(args[0], XmNtopAttachment, XmATTACH_FORM);
00620    XtSetArg(args[1], XmNleftAttachment, XmATTACH_FORM);
00621    XtSetArg(args[2], XmNrightAttachment, XmATTACH_FORM);
00622    menuBar = XmCreateMenuBar(form, (char *) "MenuBar", args, 3);
00623    XtManageChild(menuBar);
00624 
00625    fileMenu = addMenu("File");
00626    this->addButton(fileMenu, "Open Viewpoint File...", openViewPtFileCB);
00627    addButton(fileMenu, "New Viewpoint File", newViewPtFileCB);
00628    addButton(fileMenu, "Load Ref. Coords", loadRefCoordsDialogCB);
00629    addButton(fileMenu, "Save Ref. Coords", saveRefCoordsDialogCB);
00630    addButton(fileMenu, "Load Scene Graph", loadSceneGraphDialogCB);
00631    addButton(fileMenu, "Save Scene Graph", saveSceneGraphDialogCB);
00632    XtManageChild(
00633           XmCreateSeparatorGadget(fileMenu, (char *) "Separator", NULL, 0));
00634 
00635    Widget menu = addMenu("Tools");
00636    addButton(menu, "Animate Ref. Particle", animateRefParticleCB);
00637    addButton(menu, "Go to start of Ref path", gotoRefPathStartCB);
00638    addButton(menu, "Invert Ref path", invertRefPathCB);
00639 
00640    Widget viewerBase = SoXtFullViewer::buildWidget(form);
00641 
00642    XtSetArg(args[0], XmNtopAttachment, XmATTACH_WIDGET);
00643    XtSetArg(args[1], XmNtopWidget, menuBar);
00644    XtSetArg(args[2], XmNleftAttachment, XmATTACH_FORM);
00645    XtSetArg(args[3], XmNrightAttachment, XmATTACH_FORM);
00646    XtSetArg(args[4], XmNbottomAttachment, XmATTACH_FORM);
00647    XtSetValues(viewerBase, args, 5);
00648 
00649    return viewerBase;
00650 }
00651 
00652 
00653 // Adds a new menu to menuBar
00654 Widget G4OpenInventorXtExaminerViewer::addMenu(std::string name)
00655 {
00656    Arg args[1];
00657    Widget menu = XmCreatePulldownMenu(menuBar, (char *) name.c_str(), NULL, 0);
00658 
00659    XtSetArg(args[0], XmNsubMenuId, menu);
00660    Widget w = XmCreateCascadeButton(menuBar, (char *) name.c_str(), args, 1);
00661    XtManageChild(w);
00662 
00663    return menu;
00664 }
00665 
00666 
00667 // Adds a new button to menu
00668 void G4OpenInventorXtExaminerViewer::addButton(Widget menu, std::string name,
00669                                              XtCallbackProc cb)
00670 {
00671    Widget button = XmCreatePushButton(menu, (char *) name.c_str(), NULL, 0);
00672    XtManageChild(button);
00673    XtAddCallback(button, XmNactivateCallback, cb, this);
00674 }
00675 
00676 
00677 // Overloaded for saving of and browsing through viewpoints.
00678 void G4OpenInventorXtExaminerViewer::createViewerButtons(Widget parent,
00679                                                        SbPList * buttonlist)
00680 {
00681    int n;
00682    Arg args[6];
00683    Widget saveViewPtButton, abbrOutputButton, pickRefPathButton;
00684 
00685    // Create original buttons
00686    SoXtExaminerViewer::createViewerButtons(parent, buttonlist);
00687 
00688    // Handle disappearing button caused by SoXtExaminerViewer::setCamera
00689    Widget emptyButton = XtVaCreateManagedWidget("", xmPushButtonWidgetClass,
00690                                                 parent, NULL);
00691    buttonlist->append(emptyButton);
00692 
00693    // Left arrow that goes back one view point on click
00694    n = 0;
00695    XtSetArg(args[n], XmNtopPosition, 1);        n++;
00696    XtSetArg(args[n], XmNbottomPosition, 2);     n++;
00697    XtSetArg(args[n], XmNleftPosition, 0);       n++;
00698    XtSetArg(args[n], XmNrightPosition, 1);      n++;
00699    XtSetArg(args[n], XmNarrowDirection, XmARROW_LEFT);  n++;
00700    XtSetArg(args[n], XmNsensitive, False);      n++;
00701    prevViewPtButton = XmCreateArrowButtonGadget(parent, (char *) "ArrowL",
00702                                                 args, n);
00703    XtManageChild(prevViewPtButton);
00704    XtAddCallback(prevViewPtButton, XmNactivateCallback,
00705                  G4OpenInventorXtExaminerViewer::prevViewPtCB, this);
00706    buttonlist->append(prevViewPtButton);
00707 
00708    // Right arrow that goes forward one view point on click
00709    n = 0;
00710    XtSetArg(args[n], XmNtopPosition, 1);        n++;
00711    XtSetArg(args[n], XmNbottomPosition, 2);     n++;
00712    XtSetArg(args[n], XmNleftPosition, 0);       n++;
00713    XtSetArg(args[n], XmNrightPosition, 1);      n++;
00714    XtSetArg(args[n], XmNarrowDirection, XmARROW_RIGHT); n++;
00715    XtSetArg(args[n], XmNsensitive, False);      n++;
00716    nextViewPtButton = XmCreateArrowButtonGadget(parent, (char *) "ArrowR",
00717                                                 args, n);
00718    XtManageChild(nextViewPtButton);
00719    XtAddCallback(nextViewPtButton, XmNactivateCallback,
00720                  G4OpenInventorXtExaminerViewer::nextViewPtCB, this);
00721    buttonlist->append(nextViewPtButton);
00722 
00723    // Save button for storing current camera parameters
00724    saveViewPtButton = XtVaCreateManagedWidget("Save", xmPushButtonWidgetClass,
00725                                               parent, NULL);
00726    XtAddCallback(saveViewPtButton, XmNactivateCallback,
00727                  G4OpenInventorXtExaminerViewer::saveViewPtCB, this);
00728    Pixmap saveVP, saveVP_ins;
00729    saveVP = SoXtInternal::createPixmapFromXpm(saveViewPtButton,
00730                                               saveViewPt_xpm);
00731    saveVP_ins = SoXtInternal::createPixmapFromXpm(saveViewPtButton,
00732                                                   saveViewPt_xpm, TRUE);
00733    XtVaSetValues(saveViewPtButton, XmNlabelType, XmPIXMAP, XmNlabelPixmap,
00734                  saveVP, XmNselectPixmap, saveVP, XmNlabelInsensitivePixmap,
00735                  saveVP_ins, XmNselectInsensitivePixmap, saveVP_ins, NULL);
00736    buttonlist->append(saveViewPtButton);
00737 
00738    // Toggle button to get abbreviated output
00739    abbrOutputButton = XtVaCreateManagedWidget("Abbr",
00740                                               xmToggleButtonWidgetClass, parent, XmNindicatorOn, False, NULL);
00741    XtAddCallback(abbrOutputButton, XmNdisarmCallback, G4OpenInventorXtExaminerViewer::abbrOutputCB,
00742                  this);
00743    Pixmap consolexpm, consolexpm_ins;
00744    consolexpm = SoXtInternal::createPixmapFromXpm(abbrOutputButton,
00745                                                   console_xpm);
00746    consolexpm_ins = SoXtInternal::createPixmapFromXpm(abbrOutputButton,
00747                                                       console_xpm, TRUE);
00748    XtVaSetValues(abbrOutputButton, XmNlabelType, XmPIXMAP, XmNlabelPixmap,
00749                  consolexpm, XmNselectPixmap, consolexpm, XmNlabelInsensitivePixmap,
00750                  consolexpm_ins, XmNselectInsensitivePixmap, consolexpm_ins, NULL);
00751    buttonlist->append(abbrOutputButton);
00752 
00753    // Button for selecting the beam that will act as reference path
00754    pickRefPathButton = XtVaCreateManagedWidget("Refpath", xmPushButtonWidgetClass,
00755                                                parent, NULL);
00756    XtAddCallback(pickRefPathButton, XmNactivateCallback,
00757                  G4OpenInventorXtExaminerViewer::pickRefPathCB, this);
00758    Pixmap favoritesxpm, favoritesxpm_ins;
00759    favoritesxpm = SoXtInternal::createPixmapFromXpm(pickRefPathButton,
00760                                                     favorites_xpm);
00761    favoritesxpm_ins = SoXtInternal::createPixmapFromXpm(pickRefPathButton,
00762                                                         favorites_xpm, TRUE);
00763    XtVaSetValues(pickRefPathButton, XmNlabelType, XmPIXMAP, XmNlabelPixmap,
00764        favoritesxpm, XmNselectPixmap, favoritesxpm, XmNlabelInsensitivePixmap,
00765        favoritesxpm_ins, XmNselectInsensitivePixmap, favoritesxpm_ins, NULL);
00766    buttonlist->append(pickRefPathButton);
00767 
00768 }
00769 
00770 
00771 // Called right after buttons and widgets get realized.
00772 // It sets the viewpoint last accessed.
00773 void G4OpenInventorXtExaminerViewer::afterRealizeHook()
00774 {
00775    SoXtExaminerViewer::afterRealizeHook();
00776 
00777    // Default height is used when selecting and viewing scene elements
00778    // FWJ Added defaultHeight for Ortho camera
00779    SoCamera *cam = getCamera();
00780    if (cam) {
00781       if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
00782          defaultHeightAngle =
00783             ((SoPerspectiveCamera *) cam)->heightAngle.getValue();
00784          toggleCameraType();
00785          defaultHeight =
00786             ((SoOrthographicCamera *) cam)->height.getValue();
00787          toggleCameraType();
00788       } else {
00789          defaultHeight =
00790             ((SoOrthographicCamera *) cam)->height.getValue();
00791          toggleCameraType();
00792          cam = getCamera();
00793          if (cam->isOfType(SoPerspectiveCamera::getClassTypeId()))
00794             defaultHeightAngle =
00795                ((SoPerspectiveCamera *) cam)->heightAngle.getValue();
00796          toggleCameraType();
00797       }
00798    }
00799 
00800    // Open the default bookmark file
00801    fileIn.open(fileName.c_str());
00802    if (!fileIn.fail()) {
00803       if (!loadViewPts()) {
00804          String dialogName = (char *) "Error Loading File";
00805          std::string msg = "Wrong or corrupted input file.";
00806          warningMsgDialog(msg, dialogName, NULL);
00807       } else {
00808          // Opens a file without erasing it
00809          fileOut.open(fileName.c_str(), std::ios::in);
00810          fileOut.seekp(0, std::ios::end); // For appending new data to the end
00811          constructListsDialog(getParentWidget(), this, NULL); // Pop up listsDialog
00812 
00813          if (viewPtList.size()) {
00814             // FWJ disabled auto-selection of first viewpoint.
00815             // Initial view should be user-controllable & not forced
00816             //            setViewPt();
00817             XtSetSensitive(nextViewPtButton, True);
00818             XtSetSensitive(prevViewPtButton, True);
00819          }
00820       }
00821 
00822       fileIn.close();
00823    } else {
00824       // Creates a new default bookmark file
00825       fileOut.open(fileName.c_str());
00826       constructListsDialog(getParentWidget(), this, NULL); // Pop up listsDialog
00827    }
00828 
00829    fileIn.clear();
00830 
00831    SoSeparator *root = (SoSeparator *) (getSceneManager()->getSceneGraph());
00832    if (root == NULL)
00833       SoDebugError::post("G4OpenInventorXtExaminerViewer::afterRealizeHook", "Root is null.");
00834    else {
00835       root->addChild(myCam); // For position/orientation calculation during animation
00836    }
00837 
00838    sceneChangeSensor = new SoNodeSensor;
00839    sceneChangeSensor->setFunction(sceneChangeCB);
00840    sceneChangeSensor->attach(root);
00841    sceneChangeSensor->setData(this);
00842 
00843    // Monitor mouseover events for displaying the name of scene elements
00844    // An SoEventCallback is needed instead of using the default processSoEvent
00845    // because that last one does not provide us with an SoPath to the object
00846    // that was picked
00847    SoEventCallback *moCB = new SoEventCallback;
00848    moCB->addEventCallback(
00849                           SoLocation2Event::getClassTypeId(),
00850                           mouseoverCB, static_cast<void *>(this));
00851    root->addChild(moCB);
00852 
00853    // Override the default picking mechanism present in G4OpenInventorViewer
00854    // because we want abbreviated output when picking a trajectory
00855    SoEventCallback *pickCB = new SoEventCallback;
00856    pickCB->addEventCallback(
00857                             SoMouseButtonEvent::getClassTypeId(),
00858                             pickingCB, static_cast<void *>(this));
00859    root->addChild(pickCB);
00860 
00861 }
00862 
00863 
00864 // Rotates camera 90 degrees around a scene element.
00865 // Rotation is animated for smoothness.
00866 void G4OpenInventorXtExaminerViewer::rotateCamera()
00867 {
00868    SoCamera *cam = getCamera();
00869 
00870    SbRotation rot(rotAxis, M_PI / (2 * ROT_CNT));
00871    rot.multVec(camDir, camDir);
00872    rot.multVec(camUpVec, camUpVec);
00873 
00874    SbVec3f camPosNew = prevPt - (camDir*distance);
00875    cam->position = camPosNew;
00876    cam->pointAt(prevPt, camUpVec);
00877    cam->focalDistance = (prevPt - camPosNew).length();
00878 
00879    rotCnt--;
00880 
00881    if (animateSensorRotation->isScheduled()) {
00882       animateSensorRotation->unschedule();
00883    }
00884 
00885    animateSensorRotation->setBaseTime(SbTime::getTimeOfDay());
00886    animateSensorRotation->setInterval(SbTime(0.02));
00887    animateSensorRotation->schedule();
00888 
00889 }
00890 
00891 
00892 // Slides camera along the beamline.
00893 void G4OpenInventorXtExaminerViewer::moveCamera(float dist, bool lookdown)
00894 {
00895 
00896    SoCamera *cam = getCamera();
00897    SbVec3f p1, p2;       // The particle moves from p1 to p2
00898    SbVec3f particleDir;  // Direction vector from p1 to p2
00899    SbVec3f camPosNew;    // New position of the camera
00900 
00901    if(refParticleTrajectory.size() == 0) {
00902       //refParticleTrajectory hasn't been set yet
00903       if(dist)
00904          distance = dist;
00905       else
00906          distance = (cam->position.getValue() - center).length();
00907 
00908       cam->position.setValue(center + offsetFromCenter*distance);
00909       cam->focalDistance = (cam->position.getValue() - center).length();
00910       cam->pointAt(center, upVector);
00911    }
00912    else{
00913 
00914       // If we move forward past the last trajectory point,
00915       // go back to the beginning
00916       if (refParticleIdx >= (int) refParticleTrajectory.size() - 1) {
00917          prevPt = refParticleTrajectory[refParticleIdx - step];
00918          dist = (prevPt - cam->position.getValue()).length();
00919          refParticleIdx = 0;
00920       }
00921       // If we move backward past the beginning,
00922       // go to the last trajectory point
00923       if (refParticleIdx < 0) {
00924          prevPt = refParticleTrajectory[refParticleIdx + step];
00925          dist = (prevPt - cam->position.getValue()).length();
00926          refParticleIdx = refParticleTrajectory.size() - 2;
00927       }
00928 
00929       // Set start and end points
00930       p1 = refParticleTrajectory[refParticleIdx];
00931       p2 = refParticleTrajectory[refParticleIdx + step];
00932 
00933       // Get the direction from p1 to p2
00934       particleDir = p2 - p1;
00935       particleDir.normalize();
00936 
00937       if(prevParticleDir == SbVec3f(0,0,0)){
00938          // First time entering BEAMLINE mode, look at
00939          // the element from the front, with camera upright
00940          if(lookdown)
00941             camDir = SbVec3f(0,0,1);
00942          else
00943             camDir = SbVec3f(1,0,0);
00944          camUpVec = SbVec3f(0,1,0);
00945 
00946          // In case the start of the goes in a
00947          // direction other than +z, rotate the camera accordingly
00948          SbRotation rot(SbVec3f(0,0,1), particleDir);
00949          rot.multVec(camDir, camDir);
00950          rot.multVec(camUpVec, camUpVec);
00951 
00952       }
00953       else if(particleDir != prevParticleDir) {
00954          // The beamline has changed direction
00955 
00956          SbRotation rot(prevParticleDir, particleDir);
00957          rot.multVec(camDir, camDir);
00958          rot.multVec(camUpVec, camUpVec);
00959 
00960       }
00961 
00962       if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
00963          if (!dist)
00964             distance = (prevPt - cam->position.getValue()).length();
00965          else
00966             distance = dist;
00967       }
00968 
00969       if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) {
00970          if (!dist)
00971             distance = (prevPt - cam->position.getValue()).length();
00972          else
00973             distance = dist;
00974       }
00975 
00976 
00977       float x,y,z;
00978       prevPt.getValue(x,y,z);
00979 
00980 
00981       if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
00982          camPosNew = p2 - (camDir*distance);
00983       }
00984       if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) {
00985          camPosNew = p2 - (camDir);
00986       }
00987 
00988       cam->position = camPosNew;
00989       cam->pointAt(p2, camUpVec);
00990       // FWJ Disabled: zooms out the Persp camera much too far
00991       // and can't recover by zooming in!
00992       //      cam->focalDistance = (p2 - camPosNew).length();
00993 
00994       p2.getValue(x,y,z);
00995       camPosNew.getValue(x,y,z);
00996 
00997       prevParticleDir = particleDir;
00998       prevPt = p1; // For accurate distance calculation
00999 
01000    }
01001 
01002 }
01003 
01004 
01005 void G4OpenInventorXtExaminerViewer::pickingCB(void *aThis, 
01006                                                SoEventCallback *eventCB)
01007 {
01008    SoHandleEventAction* action = eventCB->getAction();
01009    const SoPickedPoint *pp = action->getPickedPoint();
01010    G4OpenInventorXtExaminerViewer* This = (G4OpenInventorXtExaminerViewer*)aThis;
01011 
01012    if(pp != NULL) {
01013 
01014       SoPath* path = pp->getPath();
01015       SoNode* node = ((SoFullPath*)path)->getTail();
01016 
01017       if(node->getTypeId() == SoLineSet::getClassTypeId()){
01018 
01019          if(This->pickRefPathFlag){
01020             This->pickRefPathFlag = false;
01021             if(This->viewingBeforePickRef != This->isViewing())
01022                This->setViewing(This->viewingBeforePickRef);
01023             else
01024                This->setComponentCursor(SoXtCursor(SoXtCursor::DEFAULT));
01025 
01026             // The trajectory is a set of lines stored in a LineSet
01027             SoLineSet * trajectory = (SoLineSet *)node;
01028 
01029        // The set of all trajectories is stored in a Seperator group node
01030        // one level above the LineSet that was picked. The nodes under that
01031        // seperator are as follows (in this order): Material, LightModel,
01032        // ResetTransform, MatrixTransform, Coordinate3, DrawStyle, LineSet
01033             SoSeparator * grpNode = 
01034                (SoSeparator*)(((SoFullPath*)path)->getNodeFromTail(1));
01035 
01036    // The node that contains the coordinates for the trajectory is a
01037    // Coordinate3 node which occurs before the LineSet node.  We iterate
01038    // back through the nodes in the group until we find the Coordinate3 node
01039             int nodeIndex = grpNode->findChild(trajectory);
01040             SoNode * tmpNode;
01041             // FWJ needs initialization
01042             SoCoordinate3 * coords = 0;
01043             //            SoCoordinate3 * coords;
01044             // We allow only 100 iterations, in case the node isn't found
01045             // (should take only a few iterations)
01046             for(int i = 0; i < 100; ++i) {
01047                --nodeIndex;
01048 
01049                tmpNode = grpNode->getChild(nodeIndex);
01050                if(tmpNode->getTypeId() == SoCoordinate3::getClassTypeId()){
01051                   //node found
01052                   coords = (SoCoordinate3 *)tmpNode;
01053                   break;
01054                }
01055             }
01056 
01057             if(coords == NULL){
01058                String dialogName = (char *) "No coordinates";
01059                std::string msg = "Could not find the coordinates node"
01060                   " for the picked trajectory."
01061                   " Reference trajectory not set";
01062                This->warningMsgDialog(msg, dialogName, NULL);
01063                return;
01064             }
01065 
01066 
01067             if ((This->lshiftdown)      || (This->rshiftdown))
01068                This->setReferencePath(trajectory, coords, true);
01069             else
01070                This->setReferencePath(trajectory, coords, false);
01071 
01072             return;
01073 
01074          }
01075          else if(This->abbrOutputFlag) {
01076 
01077             G4AttHolder* attHolder = dynamic_cast<G4AttHolder*>(node);
01078             if(attHolder && attHolder->GetAttDefs().size()) {
01079 
01080                std::string strTrajPoint = "G4TrajectoryPoint:";
01081                std::ostringstream oss;
01082                for (size_t i = 0; i < attHolder->GetAttDefs().size(); ++i) {
01083                   G4cout << G4AttCheck(attHolder->GetAttValues()[i],
01084                                        attHolder->GetAttDefs()[i]);
01085                   oss << G4AttCheck(attHolder->GetAttValues()[i],
01086                                     attHolder->GetAttDefs()[i]);
01087                   if(oss.str().find(strTrajPoint) != std::string::npos) {
01088 
01089            // Last attribute displayed was a trajectory point.  Since we
01090            // want abbreviated output, display the last one and exit
01091            // (unless we're already at the last (and only) trajectory point)
01092                      if(i != attHolder->GetAttDefs().size()-1) {
01093                         G4cout << G4AttCheck(
01094               attHolder->GetAttValues()[attHolder->GetAttDefs().size()-1],
01095               attHolder->GetAttDefs()[attHolder->GetAttDefs().size()-1]);
01096                      }
01097                      break;
01098                   }
01099                }
01100             } else {
01101                G4String name((char*)node->getName().getString());
01102                G4String cls((char*)node->getTypeId().getName().getString());
01103                G4cout << "SoNode : " << node
01104                       << " SoType : " << cls
01105                       << " name : " << name
01106                       << G4endl;
01107                G4cout << "No attributes attached." << G4endl;
01108             }
01109 
01110             return;
01111          }
01112          else{
01113             //Go to default behavior
01114          }
01115       }
01116       else {
01117          //Go to default behavior
01118       }
01119 
01120       // Default behavior in G4OpenInventorViewer::SelectionCB
01121       G4AttHolder* attHolder = dynamic_cast<G4AttHolder*>(node);
01122       if(attHolder && attHolder->GetAttDefs().size()) {
01123          for (size_t i = 0; i < attHolder->GetAttDefs().size(); ++i) {
01124             G4cout << G4AttCheck(attHolder->GetAttValues()[i],
01125                                  attHolder->GetAttDefs()[i]);
01126          }
01127       } else {
01128          G4String name((char*)node->getName().getString());
01129          G4String cls((char*)node->getTypeId().getName().getString());
01130          G4cout << "SoNode : " << node
01131                 << " SoType : " << cls
01132                 << " name : " << name
01133                 << G4endl;
01134          G4cout << "No attributes attached." << G4endl;
01135       }
01136 
01137       //Suppress other event handlers
01138       eventCB->setHandled();
01139    }
01140 }
01141 
01142 
01143 void G4OpenInventorXtExaminerViewer::mouseoverCB(void *aThis, SoEventCallback *eventCB)
01144 {
01145    SoHandleEventAction* action = eventCB->getAction();
01146    const SoPickedPoint *pp = action->getPickedPoint();
01147    G4OpenInventorXtExaminerViewer* This = (G4OpenInventorXtExaminerViewer*)aThis;
01148 
01149    if(!This->abbrOutputFlag)
01150       return;
01151 
01152    if(pp != NULL) {
01153 
01154       const SbViewportRegion & viewportRegion = action->getViewportRegion();
01155 
01156       std::string sLogName;
01157       float x,y,z;
01158       std::stringstream ssZPos;
01159       std::stringstream ssSolids;
01160       std::stringstream ssMaterials;
01161       SoPath * path = pp->getPath();
01162       SoNode* node = ((SoFullPath*)path)->getTail();
01163 
01164       if(node->getTypeId() == Geant4_SoPolyhedron::getClassTypeId()) {
01165 
01166          sLogName = "Logical Volume:  ";
01167          sLogName += ((Geant4_SoPolyhedron *)node)->getName().getString();
01168 
01169          SoGetBoundingBoxAction bAction(viewportRegion);
01170          bAction.apply((SoFullPath*)path);
01171          SbBox3f bBox = bAction.getBoundingBox();
01172          SbVec3f center = bBox.getCenter();
01173          center.getValue(x,y,z);
01174          ssZPos << "Pos:  " << x << "  " << y << "  " << z;
01175 
01176          G4AttHolder* attHolder = dynamic_cast<G4AttHolder*>(node);
01177          if(attHolder && attHolder->GetAttDefs().size()) {
01178 
01179             std::vector<const std::map<G4String,G4AttDef>*> vecDefs =
01180                attHolder->GetAttDefs();
01181             std::vector<const std::vector<G4AttValue>*> vecVals =
01182                attHolder->GetAttValues();
01183             for (size_t i = 0; i < vecDefs.size(); ++i) {
01184                const std::vector<G4AttValue> * vals = vecVals[i];
01185 
01186                std::vector<G4AttValue>::const_iterator iValue;
01187 
01188                for (iValue = vals->begin(); iValue != vals->end(); ++iValue) {
01189                   const G4String& valueName = iValue->GetName();
01190                   const G4String& value = iValue->GetValue();
01191 
01192                   if(valueName == "Solid") {
01193                      if(ssSolids.str() == "")
01194                         ssSolids << "Solid Name:  " << value;
01195                      else
01196                         ssSolids << ", " << value;
01197                   }
01198 
01199                   if(valueName == "Material") {
01200                      if(ssMaterials.str() == "")
01201                         ssMaterials << "Material Name:  " << value;
01202                      else
01203                         ssMaterials << ", " << value;
01204                   }
01205                }
01206             }
01207          }
01208       }
01209 
01210       bool redraw = false;
01211       if(std::string(This->mouseOverTextLogName->string.getValues(0)->getString()) != sLogName) {
01212          This->mouseOverTextLogName->string.setValue(SbString(sLogName.c_str()));
01213          redraw = true;
01214       }
01215       if(std::string(This->mouseOverTextSolid->string.getValues(0)->getString()) != ssSolids.str()) {
01216          This->mouseOverTextSolid->string.setValue(SbString(ssSolids.str().c_str()));
01217          redraw = true;
01218       }
01219       if(std::string(This->mouseOverTextMaterial->string.getValues(0)->getString()) != ssMaterials.str()){
01220          This->mouseOverTextMaterial->string.setValue(SbString(ssMaterials.str().c_str()));
01221          redraw = true;
01222       }
01223       if(std::string(This->mouseOverTextZPos->string.getValues(0)->getString()) != ssZPos.str()) {
01224          This->mouseOverTextZPos->string.setValue(SbString(ssZPos.str().c_str()));
01225          redraw = true;
01226       }
01227 
01228       if(redraw) {
01229          This->setSuperimpositionEnabled(This->superimposition, TRUE);
01230          This->scheduleRedraw();
01231       }
01232 
01233       eventCB->setHandled();
01234    }
01235    else {
01236       if(std::string(This->mouseOverTextLogName->string.getValues(0)->getString()) != "") {
01237          This->mouseOverTextLogName->string.setValue(SbString(""));
01238          This->scheduleRedraw();
01239       }
01240       if(std::string(This->mouseOverTextSolid->string.getValues(0)->getString()) != "") {
01241          This->mouseOverTextSolid->string.setValue(SbString(""));
01242          This->scheduleRedraw();
01243       }
01244       if(std::string(This->mouseOverTextMaterial->string.getValues(0)->getString()) != "") {
01245          This->mouseOverTextMaterial->string.setValue(SbString(""));
01246          This->scheduleRedraw();
01247       }
01248       if(std::string(This->mouseOverTextZPos->string.getValues(0)->getString()) != "") {
01249          This->mouseOverTextZPos->string.setValue(SbString(""));
01250          This->scheduleRedraw();
01251       }
01252    }
01253 }
01254 
01255 
01256 SbBool G4OpenInventorXtExaminerViewer::processSoEvent(const SoEvent * const ev) {
01257    SoCamera *cam = getCamera();
01258    const SoType type(ev->getTypeId());
01259 
01260    if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
01261       SoMouseButtonEvent * me = (SoMouseButtonEvent *) ev;
01262 
01263       if (currentState == ANIMATION || currentState == REVERSED_ANIMATION
01264           || currentState == PAUSED_ANIMATION) {
01265          switch (me->getButton()) {
01266          case SoMouseButtonEvent::BUTTON4: // Scroll wheel up
01267             if (me->getState() == SoButtonEvent::DOWN) {
01268                if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
01269                   float hAngle =
01270                      ((SoPerspectiveCamera *) cam)->heightAngle.getValue();
01271                   ((SoPerspectiveCamera *) cam)->heightAngle = hAngle
01272                      + 0.01f;
01273                   return TRUE;
01274                } else if (cam->isOfType(
01275                                         SoOrthographicCamera::getClassTypeId())) {
01276                   float height =
01277                      ((SoOrthographicCamera *) cam)->height.getValue();
01278                   ((SoOrthographicCamera *) cam)->height = height + 5;
01279                   return TRUE;
01280                }
01281             }
01282             break;
01283          case SoMouseButtonEvent::BUTTON5: // Scroll wheel down
01284             if (me->getState() == SoButtonEvent::DOWN) {
01285                if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
01286                   float hAngle =
01287                      ((SoPerspectiveCamera *) cam)->heightAngle.getValue();
01288                   if (hAngle > 0.01)
01289                      ((SoPerspectiveCamera *) cam)->heightAngle = hAngle
01290                         - 0.01f;
01291                   return TRUE;
01292                } else if (cam->isOfType(
01293                                         SoOrthographicCamera::getClassTypeId())) {
01294                   float height =
01295                      ((SoOrthographicCamera *) cam)->height.getValue();
01296                   if (height > 5)
01297                      ((SoOrthographicCamera *) cam)->height = height - 5;
01298                   return TRUE;
01299                }
01300             }
01301             break;
01302          default:
01303             break;
01304          }
01305       }
01306       if (currentState == GENERAL) {
01307 
01308       }
01309    }
01310 
01311    if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
01312       SoKeyboardEvent * ke = (SoKeyboardEvent *) ev;
01313 
01314       if (SoKeyboardEvent::isKeyPressEvent(ev, ke->getKey())) {
01315          switch (ke->getKey()) {
01316          case SoKeyboardEvent::LEFT_SHIFT:
01317             this->lshiftdown = true;
01318             return TRUE;
01319          case SoKeyboardEvent::RIGHT_SHIFT:
01320             this->rshiftdown = true;
01321             return TRUE;
01322          case SoKeyboardEvent::LEFT_CONTROL:
01323             this->lctrldown = true;
01324             return TRUE;
01325          case SoKeyboardEvent::RIGHT_CONTROL:
01326             this->rctrldown = true;
01327             return TRUE;
01328          case SoKeyboardEvent::SPACE:
01329             if (currentState == ANIMATION
01330                 || currentState == REVERSED_ANIMATION) {
01331                beforePausing = currentState;
01332                currentState = PAUSED_ANIMATION;
01333                if (animateSensor->isScheduled())
01334                   animateSensor->unschedule();
01335                return TRUE;
01336             } else if (currentState == PAUSED_ANIMATION) {
01337                if (maxSpeed) {
01338                   if ((beforePausing == ANIMATION
01339                        && refParticleIdx
01340                        < (int) refParticleTrajectory.size() - 1)
01341                       || (beforePausing == REVERSED_ANIMATION
01342                           && refParticleIdx > 0)) {
01343                      currentState = beforePausing;
01344                      animateRefParticle();
01345                   }
01346                }
01347                return TRUE;
01348             }
01349             break;
01350          case SoKeyboardEvent::ESCAPE:
01351             if (currentState == ANIMATION
01352                 || currentState == REVERSED_ANIMATION
01353                 || currentState == PAUSED_ANIMATION) {
01354 
01355                if (animateSensor->isScheduled())
01356                   animateSensor->unschedule();
01357                currentState = prevState;
01358                refParticleIdx = prevRefIdx;
01359                setSuperimpositionEnabled(superimposition, FALSE);
01360                maxSpeed = 0.0f;
01361                step = 1;
01362 
01363                scheduleRedraw();
01364                if (currentState == VIEWPOINT) {
01365                   setSuperimpositionEnabled(superimposition, TRUE);
01366                   axisSwitch->whichChild.setValue(SO_SWITCH_NONE);
01367                   animSpeedOutlineSwitch->whichChild.setValue(
01368                                                               SO_SWITCH_NONE);
01369                   animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE);
01370 
01371                   scheduleRedraw();
01372                }
01373                restoreCamera();
01374                return TRUE;
01375             }
01376             break;
01377          case SoKeyboardEvent::DELETE:
01378             if (viewPtList.size()
01379                 && (currentState != ANIMATION
01380                     || currentState != REVERSED_ANIMATION
01381                     || currentState != PAUSED_ANIMATION)) {
01382                String dialogName = (char *) "Delete Viewpoint";
01383                std::string msg = "Are you sure you want to delete current viewpoint?";
01384                warningMsgDialog(msg, dialogName, deleteViewPtCB);
01385                return TRUE;
01386             }
01387             break;
01388          case SoKeyboardEvent::LEFT_ARROW:
01389             switch (currentState) {
01390             case BEAMLINE:
01391                if ((this->lshiftdown)   || (this->rshiftdown)){
01392                   refParticleIdx -= step;
01393                   moveCamera();
01394                }
01395                else if ((this->lctrldown)       || (this->rctrldown)){
01396                   if (SoXtExaminerViewer::isAnimating())
01397                      stopAnimating();
01398                   prevState = currentState;
01399                   currentState = ROTATING;
01400                   animateBtwPtsPeriod = 0.08f;
01401 
01402                   SbVec3f tmp = camDir;
01403                   tmp.negate();
01404                   rotAxis = tmp;
01405 
01406                   rotCnt = ROT_CNT;
01407                   moveCamera(); // To make sure camera is perpendicular to the beamline
01408 
01409                   rotateCamera();
01410                }
01411                else{
01412                   if (SoXtExaminerViewer::isAnimating())
01413                      stopAnimating();
01414                   prevState = currentState;
01415                   currentState = ROTATING;
01416                   animateBtwPtsPeriod = 0.08f;
01417 
01418                   SbVec3f tmp = camUpVec;
01419                   tmp.negate();
01420                   rotAxis = tmp;
01421 
01422                   rotCnt = ROT_CNT;
01423                   moveCamera(); // To make sure camera is perpendicular to the beamline
01424 
01425                   rotateCamera();
01426 
01427                }
01428                return TRUE;
01429 
01430             case ANIMATION:
01431             case REVERSED_ANIMATION:
01432                left_right -= 1.5f;
01433                return TRUE;
01434             case PAUSED_ANIMATION:
01435                left_right -= 1.5f;
01436                setStartingPtForAnimation();
01437                cam->position = myCam->position;
01438                return TRUE;
01439             case GENERAL:
01440             case VIEWPOINT:
01441                if ((!this->lshiftdown) && (!this->rshiftdown)) {
01442                   // Using this allows us to look around without
01443                   // changing the camera parameters (camDir, camUpVec)
01444                   this->bottomWheelMotion(
01445                                           this->getBottomWheelValue() + 0.1f);
01446 
01447                   return TRUE;
01448                }
01449                break;
01450             case ROTATING:
01451                // For this state, let the keyboard event
01452                // be handled by superclass
01453                break;
01454             default:
01455                SoDebugError::post("G4OpenInventorXtExaminerViewer::processSoEvent",
01456                                   "Unhandled viewer state");
01457                break;
01458             }
01459             break;
01460 
01461          case SoKeyboardEvent::RIGHT_ARROW:
01462             switch(currentState){
01463             case BEAMLINE:
01464                if ((this->lshiftdown)   || (this->rshiftdown)){
01465                   refParticleIdx += step;
01466                   moveCamera();
01467                }
01468                else if ((this->lctrldown)       || (this->rctrldown)){
01469                   if (SoXtExaminerViewer::isAnimating())
01470                      stopAnimating();
01471                   prevState = currentState;
01472                   currentState = ROTATING;
01473                   animateBtwPtsPeriod = 0.08f;
01474 
01475                   rotAxis = camDir;
01476 
01477                   rotCnt = ROT_CNT;
01478                   moveCamera(); // To make sure camera is perpendicular to the beamline
01479 
01480                   rotateCamera();
01481                }
01482                else{
01483                   if (SoXtExaminerViewer::isAnimating())
01484                      stopAnimating();
01485                   prevState = currentState;
01486                   currentState = ROTATING;
01487                   animateBtwPtsPeriod = 0.08f;
01488 
01489                   rotAxis = camUpVec;
01490 
01491                   rotCnt = ROT_CNT;
01492                   moveCamera(); // To make sure camera is perpendicular to the beamline
01493 
01494                   rotateCamera();
01495                }
01496                return TRUE;
01497 
01498             case ANIMATION:
01499             case REVERSED_ANIMATION:
01500                left_right += 1.5f;
01501                return TRUE;
01502             case PAUSED_ANIMATION:
01503                left_right += 1.5f;
01504                setStartingPtForAnimation();
01505                cam->position = myCam->position;
01506                return TRUE;
01507             case GENERAL:
01508             case VIEWPOINT:
01509                if ((!this->lshiftdown) && (!this->rshiftdown)) {
01510                   // Using this allows us to look around without
01511                   // changing the camera parameters (camDir, camUpVec)
01512                   this->bottomWheelMotion(
01513                                           this->getBottomWheelValue() - 0.1f);
01514                   return TRUE;
01515                }
01516                break;
01517             case ROTATING:
01518                // For this state, let the keyboard event
01519                // be handled by superclass
01520                break;
01521             default:
01522                SoDebugError::post("G4OpenInventorXtExaminerViewer::processSoEvent",
01523                                   "Unhandled viewer state");
01524                break;
01525             }
01526             break;
01527 
01528          case SoKeyboardEvent::DOWN_ARROW:
01529             switch(currentState){
01530             case BEAMLINE:
01531 
01532                if ((this->lshiftdown)   || (this->rshiftdown)){
01533                   refParticleIdx -= step;
01534                   moveCamera();
01535                }
01536                else{
01537                   if (SoXtExaminerViewer::isAnimating())
01538                      stopAnimating();
01539                   prevState = currentState;
01540                   currentState = ROTATING;
01541                   animateBtwPtsPeriod = 0.08f;
01542 
01543                   rotAxis = camDir.cross(camUpVec);
01544 
01545                   rotCnt = ROT_CNT;
01546                   moveCamera(); // To make sure camera is perpendicular to the beamline
01547 
01548                   rotateCamera();
01549 
01550                }
01551                return TRUE;
01552 
01553             case ANIMATION:
01554             case REVERSED_ANIMATION:
01555                up_down -= 1.5f;
01556                return TRUE;
01557             case PAUSED_ANIMATION:
01558                up_down -= 1.5f;
01559                setStartingPtForAnimation();
01560                cam->position = myCam->position;
01561                return TRUE;
01562             case GENERAL:
01563             case VIEWPOINT:
01564                // Using this allows us to look around without
01565                // changing the camera parameters (camDir, camUpVec)
01566                if ((!this->lshiftdown) && (!this->rshiftdown)) {
01567                   this->leftWheelMotion(this->getLeftWheelValue() - 0.1f);
01568                   return TRUE;
01569                }
01570                break;
01571             case ROTATING:
01572                // For this state, let the keyboard event
01573                // be handled by superclass
01574                break;
01575             default:
01576                SoDebugError::post("G4OpenInventorXtExaminerViewer::processSoEvent",
01577                                   "Unhandled viewer state");
01578                break;
01579             }
01580             break;
01581 
01582          case SoKeyboardEvent::UP_ARROW:
01583             switch(currentState){
01584             case BEAMLINE:
01585                if ((this->lshiftdown)   || (this->rshiftdown)){
01586                   refParticleIdx -= step;
01587                   moveCamera();
01588                }
01589                else{
01590                   if (SoXtExaminerViewer::isAnimating())
01591                      stopAnimating();
01592                   prevState = currentState;
01593                   currentState = ROTATING;
01594                   animateBtwPtsPeriod = 0.08f;
01595 
01596                   rotAxis = camUpVec.cross(camDir);
01597 
01598                   rotCnt = ROT_CNT;
01599                   moveCamera();
01600 
01601                   rotateCamera();
01602 
01603 
01604                }
01605                return TRUE;
01606             case ANIMATION:
01607             case REVERSED_ANIMATION:
01608                up_down += 1.5f;
01609                return TRUE;
01610             case PAUSED_ANIMATION:
01611                up_down += 1.5f;
01612                setStartingPtForAnimation();
01613                cam->position = myCam->position;
01614                return TRUE;
01615             case GENERAL:
01616             case VIEWPOINT:
01617                // Using this allows us to look around without
01618                // changing the camera parameters (camDir, camUpVec)
01619                if ((!this->lshiftdown) && (!this->rshiftdown)) {
01620                   this->leftWheelMotion(this->getLeftWheelValue() + 0.1f);
01621                   return TRUE;
01622                }
01623                break;
01624             case ROTATING:
01625                // For this state, let the keyboard event
01626                // be handled by superclass
01627                break;
01628             default:
01629                SoDebugError::post("G4OpenInventorXtExaminerViewer::processSoEvent",
01630                                   "Unhandled viewer state");
01631                break;
01632             }
01633             break;
01634 
01635          case SoKeyboardEvent::PAGE_UP:
01636             switch(currentState){
01637             case BEAMLINE:
01638                if (step < (int) refParticleTrajectory.size() / 5) // Magic number
01639                   step++;
01640                return TRUE;
01641             case ANIMATION:
01642                incSpeed();
01643                maxSpeed += SPEED_INDICATOR_STEP;
01644                if (maxSpeed > 0.8)
01645                   maxSpeed = MAX_SPEED_INDICATOR;
01646                scheduleRedraw();
01647 
01648                return TRUE;
01649             case REVERSED_ANIMATION:
01650                if(!animateSensor->isScheduled()){
01651                   currentState = ANIMATION;
01652                   if (refParticleIdx
01653                       < (int) refParticleTrajectory.size() - 1) {
01654                      refParticleIdx++;
01655                      maxSpeed = SPEED_INDICATOR_STEP;
01656                      scheduleRedraw();
01657                      animateRefParticle();
01658                   }
01659                }
01660                else{
01661                   maxSpeed += SPEED_INDICATOR_STEP;
01662                   decSpeed();
01663                   scheduleRedraw();
01664                }
01665                return TRUE;
01666             case PAUSED_ANIMATION:
01667                maxSpeed += SPEED_INDICATOR_STEP;
01668                if (maxSpeed > 0.8)
01669                   maxSpeed = MAX_SPEED_INDICATOR;
01670 
01671                if (beforePausing == ANIMATION) {
01672                   incSpeed();
01673                } else {
01674                   decSpeed();
01675                   if (animateBtwPtsPeriod >= MIN_SPEED)
01676                      beforePausing = ANIMATION;
01677                }
01678 
01679                scheduleRedraw();
01680                return TRUE;
01681             default:    //fall through
01682                break;
01683             }
01684             break;
01685 
01686          case SoKeyboardEvent::PAGE_DOWN:
01687             switch(currentState){
01688             case BEAMLINE:
01689                if (step > 1)
01690                   step--;
01691                return TRUE;
01692             case ANIMATION:
01693                if(!animateSensor->isScheduled()){
01694                   currentState = REVERSED_ANIMATION;
01695                   if (refParticleIdx > 1) {
01696                      refParticleIdx--;
01697                      maxSpeed = -SPEED_INDICATOR_STEP;
01698                      scheduleRedraw();
01699                      animateRefParticle();
01700                   }
01701                }
01702                else{
01703                   maxSpeed -= SPEED_INDICATOR_STEP;
01704                   decSpeed();
01705                   scheduleRedraw();
01706                }
01707                return TRUE;
01708             case REVERSED_ANIMATION:
01709                incSpeed();
01710                maxSpeed -= SPEED_INDICATOR_STEP;
01711                if (maxSpeed < -0.8)
01712                   maxSpeed = -MAX_SPEED_INDICATOR;
01713                scheduleRedraw();
01714                return TRUE;
01715             case PAUSED_ANIMATION:
01716                maxSpeed -= SPEED_INDICATOR_STEP;
01717                if (maxSpeed < -0.8)
01718                   maxSpeed = -MAX_SPEED_INDICATOR;
01719                if (beforePausing == REVERSED_ANIMATION) {
01720                   incSpeed();
01721                } else {
01722                   decSpeed();
01723                   if (animateBtwPtsPeriod >= MIN_SPEED)
01724                      beforePausing = REVERSED_ANIMATION;
01725                }
01726                scheduleRedraw();
01727                return TRUE;
01728             default:
01729                //fall through
01730                break;
01731             }
01732             break;
01733 
01734          case SoKeyboardEvent::E:
01735             this->escapeCallback(this->examinerObject);
01736             break;
01737 
01738          default:
01739             break; // To get rid of compiler warnings
01740          }
01741       }
01742       if (SoKeyboardEvent::isKeyReleaseEvent(ev, ke->getKey())) {
01743          switch (ke->getKey()) {
01744          case SoKeyboardEvent::LEFT_SHIFT:
01745             this->lshiftdown = false;
01746             return TRUE;
01747          case SoKeyboardEvent::RIGHT_SHIFT:
01748             this->rshiftdown = false;
01749             return TRUE;
01750          case SoKeyboardEvent::LEFT_CONTROL:
01751             this->lctrldown = false;
01752             return TRUE;
01753          case SoKeyboardEvent::RIGHT_CONTROL:
01754             this->rctrldown = false;
01755             return TRUE;
01756          default:
01757             break;
01758          }
01759       }
01760    }
01761 
01762    if (currentState == ANIMATION || currentState == REVERSED_ANIMATION
01763        || currentState == ROTATING)
01764       return FALSE;
01765    else
01766       return SoXtExaminerViewer::processSoEvent(ev);
01767 }
01768 
01769 // Called by hitting PageUp during animation.
01770 void G4OpenInventorXtExaminerViewer::incSpeed() {
01771         if (std::ceil(animateBtwPtsPeriod * 100) >= 4) {
01772                 if (speedStep > 0.08)
01773                         speedStep -= 0.02;
01774                 else
01775                         speedStep = 0.02;
01776                 animateBtwPtsPeriod -= speedStep;
01777         } else
01778                 animateBtwPtsPeriod = 0.0;
01779 
01780         if (currentState != PAUSED_ANIMATION) {
01781                 int lastIdx = refParticleTrajectory.size() - 1;
01782                 if (refParticleIdx < lastIdx && !animateSensor->isScheduled())
01783                         animateRefParticle();
01784         }
01785 }
01786 
01787 // Called by hitting PageDown during animation.
01788 void G4OpenInventorXtExaminerViewer::decSpeed() {
01789         animateBtwPtsPeriod += speedStep;
01790         if (animateBtwPtsPeriod < MIN_SPEED) {
01791                 if (std::floor(animateBtwPtsPeriod * 100) == 12) { // Errors in double representation
01792                         speedStep = 0.08;
01793                 } else if (animateBtwPtsPeriod > 0.12)
01794                         speedStep += 0.02;
01795         } else {
01796                 animateBtwPtsPeriod = MIN_SPEED;
01797                 speedStep = START_STEP;
01798                 maxSpeed = 0.0f;
01799                 if (animateSensor->isScheduled())
01800                         animateSensor->unschedule();
01801         }
01802 }
01803 
01804 // Based on the user's interaction the speed indicator bar needs to be adjusted.
01805 void G4OpenInventorXtExaminerViewer::updateSpeedIndicator(void) {
01806         assert(this->sgeometry != NULL);
01807 
01808         SbVec3f * points = this->sgeometry->point.startEditing();
01809 
01810         if (points[10][0] == 0.0f)
01811                 this->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_ALL);
01812         if (points[14][0] == 0.0f)
01813                 this->animSpeedSwitch->whichChild.setValue(SO_SWITCH_ALL);
01814         points[10][0] = this->maxSpeed;
01815         points[11][0] = this->maxSpeed;
01816         points[14][0] = this->maxSpeed;
01817         points[15][0] = this->maxSpeed;
01818         this->sgeometry->point.finishEditing();
01819 
01820         if (this->maxSpeed == 0.0f) {
01821                 this->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE);
01822                 this->animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE);
01823         }
01824 }
01825 
01826 void G4OpenInventorXtExaminerViewer::actualRedraw(void) {
01827         switch (currentState) {
01828         case ANIMATION:
01829         case REVERSED_ANIMATION:
01830         case PAUSED_ANIMATION:
01831                 updateSpeedIndicator();
01832                 SoXtExaminerViewer::actualRedraw();
01833                 break;
01834         default:
01835                 SoXtExaminerViewer::actualRedraw();
01836                 break;
01837         }
01838 }
01839 
01840 void G4OpenInventorXtExaminerViewer::setReferencePath(SoLineSet *lineset, SoCoordinate3 *coords, bool append)
01841 {
01842    // TODO:  Color the reference path
01843    // Disable the color stuff for now: changes all trajectories
01844 
01845 // // We change the color of the trajectory too, so we get its material
01846 //      nodeIndex = grpNode->findChild(trajectory);
01847 //      SoMaterial * mat;
01848 //      for(int i = 0; i < 100; ++i){
01849 //              --nodeIndex;
01850 //
01851 //              tmpNode = grpNode->getChild(nodeIndex);
01852 //              if(tmpNode->getTypeId() == SoMaterial::getClassTypeId()){
01853 //                      //node found
01854 //                      mat = (SoMaterial *)tmpNode;
01855 //
01856 //                      break;
01857 //              }
01858 //      }
01859 //
01860 //
01861 // // Restore default color for previously picked trajectory
01862 // // and set different color for current pick
01863 //      if(This->prevColorField)
01864 //              ((SoMFColor *)This->prevColorField)->setValue(0.0, 1.0, 0.0);
01865 //      This->prevColorField = (void *)&mat->diffuseColor;
01866 //
01867 //
01868 //      if(mat->diffuseColor.isConnected())
01869 //              std::cout << "connected" << std::endl;
01870 //
01871 //      mat->diffuseColor.setValue(41.0/255.0, 230.0/255.0, 230.0/255.0);
01872 //
01873 //      std::cout << "R: " << mat->diffuseColor[0][0] << " ";
01874 //      std::cout << "G: " << mat->diffuseColor[0][1] << " ";
01875 //      std::cout << "B: " << mat->diffuseColor[0][2] << std::endl;
01876 
01877    // The trajectory is composed of all the polyline segments in the
01878    // multiple value field (SoMFInt32) numVertices.
01879    // For each of the numVertices.getNum()* polyline segments,
01880    // retrieve the points from the SoCoordinate3 node
01881    SbVec3f refParticlePt;
01882 
01883    if(!append)
01884       this->refParticleTrajectory.clear();
01885 
01886    for(int i = 0; i < lineset->numVertices.getNum(); ++i){
01887       for(int j = 0; j < lineset->numVertices[i]; ++j){
01888          refParticlePt = coords->point[j];
01889          this->refParticleTrajectory.push_back(refParticlePt);
01890       }
01891    }
01892    // Remove points that are too close to each other
01893    this->evenOutRefParticlePts();
01894    this->setReferencePathZPos();
01895    this->sortElements();
01896 }
01897 
01898 
01899 void G4OpenInventorXtExaminerViewer::setReferencePathZPos()
01900 {
01901    refZPositions.clear();
01902    refZPositions.push_back(0);
01903    float dist;
01904    for(unsigned int i=0; i < this->refParticleTrajectory.size() - 1; ++i){
01905       dist = (refParticleTrajectory[i] - 
01906               refParticleTrajectory[i + 1]).length();
01907       refZPositions.push_back(refZPositions[i] + dist);
01908    }
01909 }
01910 
01911 
01912 void G4OpenInventorXtExaminerViewer::findAndSetRefPath()
01913 {
01914    SoSearchAction action;
01915    action.setType(SoLineSet::getClassTypeId(),false);
01916    action.setInterest(SoSearchAction::ALL);
01917    action.apply(this->getSceneGraph());
01918 
01919    SoPathList &pathList = action.getPaths();
01920 
01921    if(pathList.getLength() != 0){
01922 
01923       SoCoordinate3 * coords = NULL;
01924       std::vector<SoCoordinate3 *> coordvec;
01925       std::vector<SoLineSet *> linevec;
01926 
01927       bool refPathFound = false;
01928       for(int i = 0; i < pathList.getLength(); ++i) {
01929          SoFullPath *path = (SoFullPath *)pathList[i];
01930 
01931          G4AttHolder* attHolder = dynamic_cast<G4AttHolder*>(path->getTail());
01932          for (size_t j = 0; j < attHolder->GetAttDefs().size(); ++j) {
01933             std::ostringstream oss;
01934             oss << G4AttCheck(attHolder->GetAttValues()[j],     attHolder->GetAttDefs()[j]);
01935 
01936             std::string findStr = "Type of trajectory (Type): ";
01937             std::string compareValue = "REFERENCE";
01938             size_t idx = oss.str().find(findStr);
01939 
01940             if(idx != std::string::npos) {
01941                if(oss.str().substr(idx + findStr.size(), compareValue.size()) == compareValue) {
01942                   coords = this->getCoordsNode(path);
01943                   if(coords != NULL){
01944                      refPathFound = true;
01945                      coordvec.push_back(coords);
01946                      linevec.push_back((SoLineSet *)path->getTail());
01947                   }
01948                   break;
01949                }
01950             }
01951 
01952             findStr = "Track ID (ID): ";
01953             idx = oss.str().find(findStr);
01954             if(idx != std::string::npos) {
01955                //index all primary tracks
01956                std::string tmpstr = oss.str().substr(idx + findStr.size(),1);
01957                std::istringstream buffer(tmpstr);
01958                int num;
01959                buffer >> num;
01960                if(num == 1) {
01961 
01962                   // Check if next character is a number, 
01963                   // in which case we don't have Track ID 1
01964                   const char * nextChar = 
01965                      oss.str().substr(idx + findStr.size() + 1,1).c_str();
01966                   if(std::isdigit(nextChar[0]))
01967                      break;     //Not a primary track, continue with next track
01968 
01969                   coords = this->getCoordsNode(path);
01970                   if(coords != NULL){
01971                      coordvec.push_back(coords);
01972                      linevec.push_back((SoLineSet *)path->getTail());
01973                      break; //Found coords node, continue with next track
01974                   }
01975                }
01976                else
01977                   break;        //Not a primary track, continue with next track
01978             }
01979             else{
01980                //Not a Track ID attribute, fall through
01981             }
01982          }
01983 
01984          if(refPathFound)
01985             break;
01986       }
01987 
01988       if(coordvec.empty())
01989          return;                //No track with a Coordinate3 node found
01990 
01991       if(refPathFound){
01992          //set ref path to last traj, coord in the vecs
01993          this->setReferencePath(linevec.back(), coordvec.back());
01994          return;
01995       }
01996       //else
01997 
01998       int longestIdx = 0;
01999       float longestLength = 0.0;
02000       // For all paths
02001       for(unsigned int i=0;i < linevec.size(); ++i){
02002 
02003          //First generate a vector with all the points in this lineset
02004          std::vector<SbVec3f> trajectory;
02005          // For all lines in the i path
02006          for(int j=0; j < linevec[i]->numVertices.getNum(); ++j){
02007             // For all points in line j
02008             for(int k=0; k < linevec[i]->numVertices[j]; ++k){
02009                trajectory.push_back(coordvec[i]->point[k]);
02010             }
02011          }
02012 
02013          // Then calculate the total length
02014          float tmpLength=0.0;
02015          for(unsigned int j=0; j < trajectory.size() - 1; ++j){
02016             tmpLength += (trajectory[j] - trajectory[j + 1]).length();
02017          }
02018 
02019          if(tmpLength > longestLength){
02020             longestIdx = i;
02021             longestLength = tmpLength;
02022          }
02023       }
02024 
02025       // Set the longest path as the reference path
02026       this->setReferencePath(linevec[longestIdx], coordvec[longestIdx]);
02027    }
02028 }
02029 
02030 
02031 SoCoordinate3 * G4OpenInventorXtExaminerViewer::getCoordsNode(SoFullPath *path)
02032 {
02033    SoLineSet *trajectory = (SoLineSet *)path->getTail();
02034    SoSeparator * grpNode = (SoSeparator*)(((SoFullPath*)path)->getNodeFromTail(1));
02035    int nodeIndex = grpNode->findChild(trajectory);
02036    SoNode * tmpNode;
02037 
02038    // We allow only 100 iterations, in case the node isn't found
02039    // (should take only a few iterations)
02040    for(int i = 0; i < 100; ++i){
02041       --nodeIndex;
02042 
02043       tmpNode = grpNode->getChild(nodeIndex);
02044       if(tmpNode->getTypeId() == SoCoordinate3::getClassTypeId()){
02045          //node found
02046          return (SoCoordinate3 *)tmpNode;
02047       }
02048    }
02049    return NULL; //coords node not found
02050 }
02051 
02052 
02053 // Displays scene elements on the right side of listsDialog.
02054 // else: scene graph is searched for Geant4_SoPolyhedron type nodes
02055 void G4OpenInventorXtExaminerViewer::getSceneElements()
02056 {
02057    std::string field, eltName;
02058 
02059    std::map<std::string, int> duplicates;
02060    std::map<std::string, int> sceneElts;
02061    SoSearchAction search;
02062    Geant4_SoPolyhedron *node;
02063    SoGroup *root = (SoGroup *)getSceneManager()->getSceneGraph();
02064 
02065    SoBaseKit::setSearchingChildren(TRUE);
02066 
02067    search.reset();
02068    search.setSearchingAll(TRUE);
02069    search.setInterest(SoSearchAction::ALL);
02070    search.setType(Geant4_SoPolyhedron::getClassTypeId(), 0);
02071    search.apply(root);
02072 
02073    SoPathList &pl = search.getPaths();
02074 
02075 
02076    // First find which names occur more than once so we can append a counter to them
02077    for(int i = 0; i < pl.getLength(); i++) {
02078       SoFullPath *path = (SoFullPath *)pl[i];
02079       node = (Geant4_SoPolyhedron *)path->getTail();
02080       eltName = node->getName();
02081       if(duplicates.count(eltName))
02082          duplicates[eltName]++;
02083       else
02084          duplicates[eltName] = 1;
02085    }
02086 
02087    for(int i = 0; i < pl.getLength(); i++) {
02088       float x,y,z;
02089       std::stringstream ssCount;
02090       SoFullPath *path = (SoFullPath *)pl[i];
02091       node = (Geant4_SoPolyhedron *)path->getTail();
02092       eltName = node->getName();
02093       field = eltName;
02094       if(duplicates[eltName] == 1)
02095          ssCount << "";//duplicates[field]
02096       else {
02097          if(sceneElts.count(eltName))
02098             sceneElts[eltName]++;
02099          else
02100             sceneElts[eltName] = 1;
02101 
02102          ssCount << sceneElts[eltName];
02103          field += "_";
02104       }
02105 
02106       field += ssCount.str();
02107 
02108       SoGetBoundingBoxAction bAction(getViewportRegion());
02109       bAction.apply(path);
02110       SbBox3f bBox = bAction.getBoundingBox();
02111 
02112       SbVec3f centr = bBox.getCenter();
02113       centr.getValue(x,y,z);
02114 
02115       path->ref();
02116       sceneElement el = { field, path, centr, 0.0 };
02117       this->sceneElements.push_back(el);
02118    }
02119 }
02120 
02121 
02122 float G4OpenInventorXtExaminerViewer::sqrlen(const SbVec3f &a)
02123 {
02124    float x,y,z;
02125    a.getValue(x,y,z);
02126    return x*x + y*y + z*z;
02127 }
02128 
02129 
02130 void G4OpenInventorXtExaminerViewer::distanceToTrajectory(const SbVec3f &q,
02131                                                           float &dist,
02132                                                 SbVec3f &closestPoint,
02133                                                           int &index)
02134 {
02135    // a : Previous point on trajectory
02136    // b : Next point on trajectory
02137    // q : the point in space
02138    // dab, daq, dbq: distance between a & b, a & q, b & q
02139    //    
02140    // Theory:  A point p on a line ab is defined as:
02141    //
02142    //                           p(t) = a+t⋅(b–a)
02143    //
02144    //                   note: All are vectors except the parameter t
02145    //
02146    // When t is between 0 and 1 the point p is situated between a and b on ab.
02147    // The point p is defined in terms of the parameter t, subsequently so does
02148    // the distance from the query point q to the point p. To find the minimum
02149    // of that distance we differentiate it and set equal to zero:
02150    //
02151    //                   diff(Norm(p(t)- q)) = 0
02152    //
02153    //           note: diff means taking the derivative with regard to t
02154    //
02155    // The resulting t is given in the code below. The square of the distance
02156    // between p and q is given by:
02157    //
02158    //                   d^2 = (Norm(p(t)-q))^2
02159    //
02160    // The expression found is given in the code below (current_dist)
02161    //
02162    // Ref: http://programmizm.sourceforge.net/blog/2012/
02163    //           distance-from-a-point-to-a-polyline
02164    //
02165    //    --PLG
02166 
02167    const size_t count = this->refParticleTrajectory.size();
02168    assert(count>0);
02169 
02170    SbVec3f b = this->refParticleTrajectory[0];
02171    SbVec3f dbq = b - q;
02172    float sqrDist = sqrlen(dbq);
02173    closestPoint = b;
02174    index = 0;
02175    for (size_t i = 1; i < count; ++i) {
02176       const SbVec3f a = b;
02177       const SbVec3f daq = dbq;
02178       b = this->refParticleTrajectory[i];
02179       dbq = b - q;
02180       const SbVec3f dab = a - b;
02181 
02182       float dab_x, dab_y, dab_z;
02183       dab.getValue(dab_x,dab_y,dab_z);
02184       float daq_x, daq_y, daq_z;
02185       daq.getValue(daq_x, daq_y, daq_z);
02186       float dbq_x, dbq_y, dbq_z;
02187       dbq.getValue(dbq_x, dbq_y, dbq_z);
02188 
02189       const float inv_sqrlen = 1./sqrlen(dab);
02190       const float t = (dab_x*daq_x + dab_y*daq_y + dab_z*daq_z)*inv_sqrlen;
02191 
02192       if (t<0.){
02193          // The trajectory point occurs before point a
02194          // Go to the next point
02195          continue;
02196       }
02197       float current_dist;
02198       if (t<=1.){
02199          // The trajectory point occurs between a and b.
02200          // Compute the distance to that point
02201          current_dist = daq_x*daq_x + daq_y*daq_y + daq_z*daq_z
02202             - t*(daq_x*dab_x + daq_y*dab_y + daq_z*dab_z)
02203             + t*t*(dab_x*dab_x + dab_y*dab_y + dab_z*dab_z);
02204       }
02205       else { //t>1.
02206          // The trajectory point occurs after b.
02207          // Get the distance to point b
02208          current_dist = sqrlen(dbq);
02209       }
02210 
02211       if (current_dist < sqrDist){
02212          sqrDist = current_dist;
02213          closestPoint = a + t*(b-a);
02214          index = i;
02215       }
02216    }
02217 
02218    dist = std::sqrt(sqrDist);
02219 }
02220 
02221 
02222 void G4OpenInventorXtExaminerViewer::sortElements()
02223 {
02224    if(this->refParticleTrajectory.empty())
02225       return;
02226 
02227    float * trajLength = new float[this->refParticleTrajectory.size()];
02228    typedef std::map<elementForSorting, sceneElement> sortedMap;
02229    sortedMap sorted;
02230 
02231    // For every point on the reference trajectory, compute
02232    // the total length from the start
02233    SbVec3f prevPoint;
02234    std::vector<SbVec3f>::iterator itRef = this->refParticleTrajectory.begin();
02235    int trajIndex = 0;
02236    prevPoint = *itRef;
02237    trajLength[trajIndex] = 0.0;
02238    ++itRef;
02239    ++trajIndex;
02240    for(; itRef != this->refParticleTrajectory.end(); ++itRef, ++trajIndex){
02241       trajLength[trajIndex] = trajLength[trajIndex-1] + (*itRef - prevPoint).length();
02242       prevPoint = *itRef;
02243    }
02244 
02245    // Compute the smallest distance between the element
02246    // and the reference trajectory (find the closest point),
02247    // then map the element to the trajectory length of that
02248    // point (calculated above)
02249    SoGetBoundingBoxAction bAction(this->getViewportRegion());
02250    SbVec3f elementCoord;
02251    std::vector<sceneElement>::iterator itEl;
02252    int elementIndex;
02253    elementForSorting el;
02254    for(itEl = this->sceneElements.begin(), elementIndex = 0;
02255        itEl != this->sceneElements.end(); ++itEl, ++elementIndex){
02256       bAction.apply(itEl->path);
02257       elementCoord = bAction.getBoundingBox().getCenter();
02258 
02259       int index;
02260       distanceToTrajectory(elementCoord, el.smallestDistance, el.closestPoint, index);
02261       itEl->closestPointZCoord = el.closestPointZCoord = trajLength[index];
02262       el.distanceToBeamlineStart = (itEl->center - this->refParticleTrajectory[0]).length();
02263 
02264       // This map of the scene elements (or their coordinates rather)
02265       // is automatically sorted by trajectory length (Z coord), then
02266       // by the distance between the element and the point in case the Z coord
02267       // is the same as another element.  This is done by using as a key
02268       // an element structure which implements the operator for weak ordering
02269       sorted.insert(std::make_pair(el,*itEl));
02270    }
02271 
02272    // store the sorted elements into the vector field
02273    this->sceneElements.clear();
02274 
02275    sortedMap::iterator itSorted = sorted.begin();
02276    for(; itSorted != sorted.end(); itSorted++)
02277       this->sceneElements.push_back(itSorted->second);
02278 
02279    this->zcoordSetFlag = true;
02280 
02281 
02282    Widget formTop = XtNameToWidget(this->listsDialog, "FormTop");
02283    Widget formTopRight = XtNameToWidget(formTop, "FormTopRight");
02284 
02285    this->createElementsList(formTopRight);
02286 
02287    delete[] trajLength;
02288 }
02289 
02290 
02291 void G4OpenInventorXtExaminerViewer::createElementsList(Widget formTopRight)
02292 {
02293    if(this->myElementList != NULL)
02294       XtUnmanageChild(this->myElementList);
02295 
02296    int size = this->sceneElements.size();
02297    XmString *elements = (XmString *) XtMalloc(size * sizeof(XmString));
02298 
02299    std::vector<sceneElement>::const_iterator it;
02300    int count = 0;
02301    std::stringstream ss;
02302    for(it=this->sceneElements.begin(); it!=this->sceneElements.end(); ++it) {
02303       ss << it->name;
02304       if(zcoordSetFlag)
02305          ss << " [" << it->closestPointZCoord << "]";
02306       elements[count] = XmStringCreateLocalized((char *)ss.str().c_str());
02307       ++count;
02308       ss.str("");
02309    }
02310 
02311    Arg args[10];
02312    int n;
02313 
02314    // Label Right
02315    n = 0;
02316    Widget labelRight;
02317    XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM);  n++;
02318 
02319    labelRight = XmCreateLabelGadget(formTopRight, (char*)"Element [S mm]",
02320                                     args, n);
02321    XtManageChild(labelRight);
02322 
02323    // List Right
02324    n = 0;
02325    XtSetArg(args[n], XmNvisibleItemCount, 7);   n++;
02326    XtSetArg(args[n], XmNitemCount, size);       n++;
02327    XtSetArg(args[n], XmNitems, elements);       n++;
02328    XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET);        n++;
02329    XtSetArg(args[n], XmNtopWidget, labelRight); n++;
02330    XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM);        n++;
02331    XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM);       n++;
02332    XtSetArg(args[n], XmNwidth, 280);    n++;
02333    //   XtSetArg(args[n], XmNwidth, 300);       n++;
02334 
02335    this->myElementList = XmCreateScrolledList(formTopRight, (char *) "ListRight", args, n);
02336 
02337    XtAddCallback(this->myElementList, XmNbrowseSelectionCallback,
02338                  (XtCallbackProc) lookAtSceneElementCB, this);
02339    xmAddMouseEventHandler(this->myElementList); // Add scrolling functionality
02340    XtManageChild(this->myElementList);
02341 
02342    if (elements != NULL) {
02343       for (int i = 0; i < size; i++)
02344          XmStringFree(elements[i]);
02345       XtFree((char *) elements);
02346    }
02347 }
02348 
02349 
02350 // Pops up a custom dialog listsDialog containing 
02351 // scene elements and viewpoints.
02352 
02353 void G4OpenInventorXtExaminerViewer::constructListsDialog(Widget w,
02354                                              XtPointer client_data,
02355                                              XtPointer)
02356 {
02357    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
02358    if (This->listsDialog) {
02359       return;
02360    }
02361 
02362    if (This->currentState == ANIMATION || This->currentState == PAUSED_ANIMATION) {
02363       if (This->animateSensor->isScheduled())
02364          This->animateSensor->unschedule();
02365       This->refParticleIdx = This->prevRefIdx;
02366       This->restoreCamera();
02367       This->currentState = This->prevState;
02368    }
02369 
02370    This->step = 1; // Default values
02371    This->refParticleIdx = 0;
02372    if (This->refParticleTrajectory.size()){
02373       This->prevPt = This->refParticleTrajectory[0]; // For calculating distance
02374    }
02375 
02376    This->getSceneElements();
02377 
02378    int n = 0;
02379    Arg args[10];
02380    Atom WM_DELETE_WINDOW;
02381 
02383 
02384    Widget topShell;
02385    topShell = SoXt::getShellWidget(This->getParentWidget());
02386 
02387    // Shell Dialog
02388    std::string dialogNameStr = This->fileName.substr(This->fileName.rfind('/') + 1);
02389    char *dialogName = new char[dialogNameStr.size() + 1];
02390    strcpy(dialogName, dialogNameStr.c_str());
02391 
02392    n = 0;
02393    XtSetArg(args[n], XmNx, 610);        n++;
02394    This->myShellDialog = XmCreateDialogShell(topShell, dialogName, args, n);
02395 
02396    delete[] dialogName;
02397    WM_DELETE_WINDOW = XInternAtom(XtDisplay(w), "WM_DELETE_WINDOW", False);
02398    XmAddWMProtocolCallback(This->myShellDialog, WM_DELETE_WINDOW,
02399                            (XtCallbackProc)closeListsDialogCB, This);
02400 
02401    // Main Pane(listsDialog)
02402    n = 0;
02403    XtSetArg(args[n], XmNsashWidth, 1);  n++;
02404    XtSetArg(args[n], XmNsashHeight, 1); n++;
02405    XtSetArg(args[n], XmNseparatorOn, False);    n++;
02406    This->listsDialog = XmCreatePanedWindow(This->myShellDialog, (char *) "MainPane",
02407                                            args, n);
02408 
02409 
02411    n = 0;
02412    Widget formTop = XmCreateForm(This->listsDialog, (char *) "FormTop", args, n);
02413 
02414    n = 0;
02415    XtSetArg(args[n], XmNmarginWidth, 8);        n++;
02416    XtSetArg(args[n], XmNmarginHeight, 8);       n++;
02417    XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM);  n++;
02418    XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM);        n++;
02419    XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM);       n++;
02420    Widget formTopRight = XmCreateForm(formTop, (char *) "FormTopRight", args,
02421                                       n);
02422 
02423    n = 0;
02424    XtSetArg(args[n], XmNmarginWidth, 8);        n++;
02425    XtSetArg(args[n], XmNmarginHeight, 8);       n++;
02426    XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM);  n++;
02427    XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
02428    XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET);      n++;
02429    XtSetArg(args[n], XmNrightWidget, formTopRight);     n++;
02430    XtSetArg(args[n], XmNrightOffset, 10);       n++;
02431    XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM);       n++;
02432    Widget formTopLeft = XmCreateForm(formTop, (char *) "FormTopLeft", args, n);
02433 
02435 
02436    This->createElementsList(formTopRight);
02437    XtManageChild(formTopRight);
02438 
02440 
02441    // Label Left
02442    n = 0;
02443    XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM);  n++;
02444    XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
02445    Widget labelLeft = XmCreateLabelGadget(formTopLeft, (char *) "ViewPoints",
02446                                           args, n);
02447    XtManageChild(labelLeft);
02448 
02449    // List Left
02450    n = 0;
02451    XtSetArg(args[n], XmNlistSizePolicy, XmRESIZE_IF_POSSIBLE);  n++;
02452    XtSetArg(args[n], XmNvisibleItemCount, 7);   n++;
02453    //   XtSetArg(args[n], XmNwidth, 140);       n++;
02454    XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET);        n++;
02455    XtSetArg(args[n], XmNtopWidget, labelLeft);  n++;
02456    XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET);      n++;
02457    XtSetArg(args[n], XmNrightWidget, This->myElementList);      n++;
02458    XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
02459    XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM);       n++;
02460    XtSetArg(args[n], XmNwidth, 200);    n++;
02461 
02462    This->myViewPtList = XmCreateScrolledList(formTopLeft, (char *) "ListLeft",
02463                                              args, n);
02464    if (This->viewPtList.size())
02465       This->addViewPoints();
02466    XtAddCallback(This->myViewPtList, XmNbrowseSelectionCallback,
02467                  (XtCallbackProc) loadBookmarkCB, This);
02468    xmAddMouseEventHandler(This->myViewPtList); // Add scrolling functionality
02469 
02470    XtManageChild(This->myViewPtList);
02471 
02472    XtManageChild(formTopLeft);
02473 
02474    XtManageChild(formTop);
02475 
02477    n = 0;
02478    XtSetArg(args[n], XmNmarginWidth, 6);        n++;
02479    Widget formMiddle = XmCreateForm(This->listsDialog, (char *) "MiddleForm", args,
02480                                     n);
02481 
02482    // Label
02483    n = 0;
02484    XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
02485    XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET);        n++;
02486    XtSetArg(args[n], XmNtopWidget, This->myViewPtList); n++;
02487    Widget label = XmCreateLabelGadget(formMiddle, (char *) "Selection", args,
02488                                       n);
02489    XtManageChild(label);
02490 
02491    // Text
02492    n = 0;
02493    XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
02494    XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM);        n++;
02495    XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET);        n++;
02496    XtSetArg(args[n], XmNtopWidget, label);      n++;
02497    XtSetArg(args[n], XmNtopOffset, 3);  n++;
02498    XtSetArg(args[n], XmNmaxLength, This->MAX_VP_NAME);  n++;
02499    This->viewPtSelection = XmCreateText(formMiddle, (char *) "Txt", args, n);
02500    XtManageChild(This->viewPtSelection);
02501 
02502    Dimension h1, h2, h;
02503    XtVaGetValues(label, XmNheight, &h1, NULL);
02504    XtVaGetValues(This->viewPtSelection, XmNheight, &h2, NULL);
02505 
02506    h = (Dimension) (1.1 * (h1 + h2));
02507 
02508    XtVaSetValues(formMiddle, XmNpaneMaximum, h, XmNpaneMinimum, h, NULL);
02509    XtManageChild(formMiddle);
02510 
02512    // Action Area Form
02513    n = 0;
02514    XtSetArg(args[n], XmNfractionBase, 4);       n++;
02515    XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET);        n++;
02516    XtSetArg(args[n], XmNtopWidget, This->viewPtSelection);      n++;
02517    Widget formAction = XmCreateForm(This->listsDialog, (char *) "ActionForm", args,
02518                                     n);
02519 
02520    n = 0;
02521    XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
02522    XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM);        n++;
02523    XtSetArg(args[n], XmNtopOffset, 3);  n++;
02524    XtSetArg(args[n], XmNbottomOffset, 5);       n++;
02525    Widget separator = XmCreateSeparatorGadget(formAction, (char *) "Sep", args, n);
02526 
02527    XtManageChild(separator);
02528 
02529    Widget button = XmCreatePushButton(formAction, (char *) "Delete", NULL, 0);
02530    XtVaSetValues(button, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget,
02531                  separator, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
02532                  XmATTACH_POSITION, XmNleftPosition, 0, XmNrightAttachment,
02533                  XmATTACH_POSITION, XmNrightPosition, 1,
02534                  XmNdefaultButtonShadowThickness, 2, XmNwidth, 40, XmNheight, 30,
02535                  NULL);
02536 
02537    XtAddCallback(button, XmNactivateCallback,
02538                  (XtCallbackProc) deleteBookmarkCB, This);
02539    XtManageChild(button);
02540 
02541    button = XmCreatePushButton(formAction, (char *) "Rename", NULL, 0);
02542    XtVaSetValues(button, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget,
02543                  separator, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
02544                  XmATTACH_POSITION, XmNleftPosition, 1, XmNrightAttachment,
02545                  XmATTACH_POSITION, XmNrightPosition, 2,
02546                  XmNdefaultButtonShadowThickness, 2, XmNwidth, 40, XmNheight, 30,
02547                  NULL);
02548 
02549    XtAddCallback(button, XmNactivateCallback,
02550                  (XtCallbackProc) renameBookmarkCB, This);
02551    XtManageChild(button);
02552 
02553    button = XmCreatePushButton(formAction, (char *) "Sort", NULL, 0);
02554    XtVaSetValues(button, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget,
02555                  separator, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
02556                  XmATTACH_POSITION, XmNleftPosition, 2, XmNrightAttachment,
02557                  XmATTACH_POSITION, XmNrightPosition, 3,
02558                  XmNdefaultButtonShadowThickness, 2, XmNwidth, 40, XmNheight, 30,
02559                  NULL);
02560 
02561    XtAddCallback(button, XmNactivateCallback, (XtCallbackProc) sortBookmarksCB, This);
02562    XtManageChild(button);
02563 
02564    button = XmCreatePushButton(formAction, (char *) "Close", NULL, 0);
02565    XtVaSetValues(button, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget,
02566                  separator, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
02567                  XmATTACH_POSITION, XmNleftPosition, 3, XmNrightAttachment,
02568                  XmATTACH_POSITION, XmNrightPosition, 4,
02569                  XmNdefaultButtonShadowThickness, 2, XmNwidth, 40, XmNheight, 30,
02570                  NULL);
02571 
02572    XtAddCallback(button, XmNactivateCallback, (XtCallbackProc) closeListsDialogCB, This);
02573    XtManageChild(button);
02574 
02575    XtManageChild(formAction);
02576    XtVaGetValues(button, XmNheight, &h1, NULL);
02577    XtVaSetValues(formAction, XmNpaneMaximum, h1, XmNpaneMinimum, h1, NULL);
02578 
02579    XtManageChild(This->listsDialog);
02580 
02582 }
02583 
02584 
02585 // Called when user clicks a scene element in listsDialog.
02586 // Zooms onto that element.
02587 void G4OpenInventorXtExaminerViewer::lookAtSceneElementCB(Widget,
02588                                            XtPointer client_data,
02589                                            XtPointer call_data)
02590 {
02591    char *value;
02592    std::string elementField;
02593    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
02594    SoCamera * cam = This->getCamera();
02595 
02596    if (This->SoXtExaminerViewer::isAnimating())
02597       This->stopAnimating();
02598 
02599    XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data;
02600 
02601    value = (char *) XmStringUnparse(cbs->item, XmFONTLIST_DEFAULT_TAG,
02602                                     XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL);
02603    if (This->currentState == ANIMATION || This->currentState == REVERSED_ANIMATION
02604        || This->currentState == PAUSED_ANIMATION ) {
02605       if (This->animateSensor->isScheduled())
02606          This->animateSensor->unschedule();
02607       This->setSuperimpositionEnabled(This->superimposition, FALSE);
02608       This->maxSpeed = 0.0f;
02609       This->scheduleRedraw();
02610       This->restoreCamera();
02611       This->currentState = This->prevState;
02612    } else if (This->currentState == VIEWPOINT)
02613       This->setSuperimpositionEnabled(This->superimposition, FALSE);
02614 
02615    elementField = value;
02616 
02617    int idx = elementField.find_last_of("[");
02618    if(idx == -1)
02619       idx = elementField.size(); //if "[" not found for whatever reason (list not sorted)
02620    else
02621       idx--; // To get rid of the space that is between the name and '['
02622 
02623    bool error = false;
02624    SoFullPath *path;
02625    SoSearchAction search;
02626    SoNode *root = This->getSceneManager()->getSceneGraph();
02627    int counter, idxUnderscore = elementField.find_last_of("_");
02628 
02629    This->parseString<int>(counter, elementField.substr(idxUnderscore + 1, idx), error);
02630 
02631    SoBaseKit::setSearchingChildren(TRUE);
02632    search.reset();
02633    search.setSearchingAll(TRUE);
02634 
02635    if(error) { // No counter is present => element name was not modified
02636       This->curEltName = elementField.substr(0, idx);
02637       search.setName(This->curEltName.c_str());
02638       search.apply(root);
02639 
02640       path = (SoFullPath *)search.getPath();
02641    }
02642    else {
02643       This->curEltName = elementField.substr(0, idxUnderscore);
02644       search.setInterest(SoSearchAction::ALL);
02645       search.setName(This->curEltName.c_str());
02646       search.apply(root);
02647 
02648       SoPathList &pl = search.getPaths();
02649       path = (SoFullPath *)pl[counter - 1]; // Since counter starts at 1, not 0
02650    }
02651 
02652    G4ThreeVector global;
02653 
02654    if ((idx > 0) && (path)) {
02655 
02656       if(!This->refParticleTrajectory.empty()){
02657 
02658          SoGetBoundingBoxAction bAction(This->getViewportRegion());
02659          bAction.apply(path);
02660          SbBox3f bBox = bAction.getBoundingBox();
02661          SbVec3f elementCoord = bBox.getCenter();
02662 
02663          This->refParticleIdx = 0;
02664          SbVec3f p;
02665 
02666          float absLengthNow, absLengthMin;
02667          int maxIdx = This->refParticleTrajectory.size() - 2;
02668          int targetIdx = 0;
02669          SbVec3f dir;
02670 
02671          p = This->refParticleTrajectory[This->refParticleIdx];
02672          absLengthMin = (p - elementCoord).length();
02673          This->refParticleIdx++;
02674 
02675          // Find a ref. particle's point closest to element's global coords
02676          while (This->refParticleIdx < maxIdx) {
02677             p = This->refParticleTrajectory[This->refParticleIdx];
02678             absLengthNow = (p - elementCoord).length();
02679 
02680             if (absLengthNow < absLengthMin) {
02681                absLengthMin = absLengthNow;
02682                targetIdx = This->refParticleIdx;
02683             }
02684             This->refParticleIdx++;
02685          }
02686 
02687          if (This->currentState != BEAMLINE) { // Set up default zoom
02688             SbVec3f p1, pN;
02689             This->currentState = BEAMLINE;
02690             This->prevParticleDir = SbVec3f(0,0,0); //so that moveCamera() knows sets default parameters
02691 
02692             p1 = This->prevPt = This->refParticleTrajectory[0];
02693             pN = This->refParticleTrajectory[This->refParticleTrajectory.size() - 1];
02694             This->distance = (pN - p1).length() / 10;
02695 
02696             // FWJ Restore the default height instead of hard-wired value
02697             if (cam->isOfType(SoOrthographicCamera::getClassTypeId()))
02698                ((SoOrthographicCamera *) cam)->height.setValue(This->defaultHeight);
02699             // ((SoOrthographicCamera *) cam)->height.setValue(10000.0f);
02700             else if (cam->isOfType(SoPerspectiveCamera::getClassTypeId()))
02701                ((SoPerspectiveCamera *) cam)->heightAngle.setValue(
02702                                                                    This->defaultHeightAngle);
02703          } else {
02704             if (cam->isOfType(SoPerspectiveCamera::getClassTypeId()))
02705                This->distance = (This->prevPt - cam->position.getValue()).length();
02706          }
02707          This->refParticleIdx = targetIdx;
02708 
02710          This->setSuperimpositionEnabled(This->superimposition, TRUE);
02711          This->axisSwitch->whichChild.setValue(SO_SWITCH_NONE);
02712          This->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE);
02713          This->animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE);
02714          This->scheduleRedraw();
02716 
02717          This->moveCamera(This->distance);
02718          XtFree(value);
02719 
02720       }
02721       else{
02722          This->offsetFromCenter.setValue(0, 0, 1);
02723          This->distance = 50;// small number since using viewAll() for default zoom
02724          This->upVector.setValue(0, 1, 0);
02725 
02726          This->moveCamera(This->distance);
02727          cam->viewAll(path, This->getViewportRegion());
02728       }
02729    }
02730 
02731    XmTextSetString(This->viewPtSelection, NULL);
02732 }
02733 
02734 
02735 // Destroyes listsDialog and resets necessary member fields.
02736 
02737 void G4OpenInventorXtExaminerViewer::closeListsDialogCB(Widget, 
02738                                          XtPointer client_data,
02739                                          XtPointer)
02740 {
02741    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
02742 
02743    This->sceneElements.clear();
02744    This->refParticleTrajectory.clear();
02745 
02746    This->currentState = GENERAL;
02747    XtDestroyWidget(This->myShellDialog);
02748    This->listsDialog = NULL;
02749 }
02750 
02751 // Called when user clicks left arrow button. Loads previous viewpoint.
02752 void G4OpenInventorXtExaminerViewer::prevViewPtCB(Widget, XtPointer client_data,
02753                                                   XtPointer) {
02754    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
02755 
02756    if (This->viewPtIdx == 0)
02757       This->viewPtIdx = This->viewPtList.size() - 1;
02758    else
02759       This->viewPtIdx--;
02760 
02761    This->writeViewPtIdx();
02762    This->setViewPt();
02763 }
02764 
02765 // Called when user clicks right arrow button. Loads next viewpoint.
02766 void G4OpenInventorXtExaminerViewer::nextViewPtCB(Widget, XtPointer client_data,
02767                                                   XtPointer) {
02768    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
02769 
02770    if (This->viewPtIdx >= (int) This->viewPtList.size() - 1)
02771       This->viewPtIdx = 0;
02772    else
02773       This->viewPtIdx++;
02774 
02775    This->writeViewPtIdx();
02776    This->setViewPt();
02777 }
02778 
02779 
02780 // Updates the viewPtIdx in a viewpoint file.
02781 
02782 void G4OpenInventorXtExaminerViewer::writeViewPtIdx()
02783 {
02784    std::string idxStr;
02785    std::stringstream out;
02786    out << viewPtIdx;
02787    idxStr = out.str();
02788    fileOut.seekp(0, std::ios::beg);
02789 
02790    while ((int) idxStr.length() < MAX_VP_IDX) {
02791       idxStr += " ";
02792    }
02793 
02794    fileOut << idxStr << "\n";
02795    fileOut.flush();
02796    fileOut.seekp(0, std::ios::end);
02797 }
02798 
02799 
02800 // Sets the viewpoint based on camera data that viewPtIdx is pointing to.
02801 
02802 void G4OpenInventorXtExaminerViewer::setViewPt()
02803 {
02804    if (currentState == ANIMATION || currentState == REVERSED_ANIMATION
02805        || currentState == ROTATING) {
02806 
02807       if (animateSensor->isScheduled())
02808          animateSensor->unschedule();
02809       setSuperimpositionEnabled(superimposition, FALSE);
02810       maxSpeed = 0.0f;
02811       scheduleRedraw();
02812    }
02813 
02814    SoCamera * camera = getCamera();
02815    if (camera == NULL) {
02816       String dialogName = (char *) "Missing Camera Node";
02817       std::string msg = "Camera is null. Unable to set the viewpoint.";
02818       warningMsgDialog(msg, dialogName, NULL);
02819       return;
02820    }
02821 
02822    if (!viewPtList.size()) {
02823       String dialogName = (char *) "Missing Viewpoints";
02824       std::string msg = "There are no viewpoints to load.";
02825       warningMsgDialog(msg, dialogName, NULL);
02826       return;
02827    }
02828 
02829    if (SoXtExaminerViewer::isAnimating())
02830       stopAnimating();
02831 
02832    if (currentState != VIEWPOINT) {
02833       currentState = VIEWPOINT;
02835       setSuperimpositionEnabled(superimposition, TRUE);
02836       axisSwitch->whichChild.setValue(SO_SWITCH_NONE);
02837       animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE);
02838       animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE);
02839 
02840       scheduleRedraw();
02842    }
02843 
02844    curViewPtName = viewPtList[viewPtIdx].viewPtName;
02845    camera->viewportMapping = viewPtList[viewPtIdx].viewportMapping;
02846    camera->position = viewPtList[viewPtIdx].position;
02847    camera->orientation = viewPtList[viewPtIdx].orientation;
02848    camera->aspectRatio = viewPtList[viewPtIdx].aspectRatio;
02849    camera->nearDistance = viewPtList[viewPtIdx].nearDistance;
02850    camera->farDistance = viewPtList[viewPtIdx].farDistance;
02851    camera->focalDistance = viewPtList[viewPtIdx].focalDistance;
02852 
02853    // Restore camera height (changed by zooming)
02854    if (camera->isOfType(SoPerspectiveCamera::getClassTypeId())) {
02855       if (viewPtList[viewPtIdx].camType == ORTHOGRAPHIC) {
02856          toggleCameraType();
02857          camera = getCamera();
02858          ((SoOrthographicCamera *) camera)->height.setValue(
02859                                                             viewPtList[viewPtIdx].height);
02860       } else
02861          ((SoPerspectiveCamera *) camera)->heightAngle.setValue(
02862                                                                 viewPtList[viewPtIdx].height);
02863    } else if (camera->isOfType(SoOrthographicCamera::getClassTypeId())) {
02864       if (viewPtList[viewPtIdx].camType == PERSPECTIVE) {
02865          toggleCameraType();
02866          camera = getCamera();
02867          ((SoPerspectiveCamera *) camera)->heightAngle.setValue(
02868                                                                 viewPtList[viewPtIdx].height);
02869       } else
02870          ((SoOrthographicCamera *) camera)->height.setValue(
02871                                                             viewPtList[viewPtIdx].height);
02872    } else {
02873       SoDebugError::post("G4OpenInventorXtExaminerViewer::setViewPt",
02874                          "Only Perspective and Orthographic cameras are supported.");
02875       return;
02876    }
02877 
02878 }
02879 
02880 
02881 // Pops up a prompt asking for a new viewpoint name.
02882 
02883 void G4OpenInventorXtExaminerViewer::saveViewPtCB(Widget w, 
02884                                      XtPointer client_data,
02885                                      XtPointer)
02886 {
02887    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
02888 
02889    if (This->fileName.empty()) {
02890       newViewPtFileCB(w, This, NULL);
02891       This->returnToSaveVP = true;
02892       return; // Need to return and call this fn again from newViewPtFileCB since flow of control does not stall here but keeps going
02893    }
02894 
02895    int n = 0;
02896    Arg args[4];
02897    Widget nameViewPtDialog;
02898    Widget parent = This->getParentWidget();     //gets the dialogshell of the ExaminerViewer widget
02899    XmString label = XmStringCreateLocalized((char *) "Name the viewpoint:");
02900 
02901    XtSetArg(args[n], XmNselectionLabelString, label);   n++;
02902    XtSetArg(args[n], XmNautoUnmanage, False);   n++;    //prevent the dialog from closing
02903    //automatically, in case the name
02904    //is wrong
02905 
02906    nameViewPtDialog = XmCreatePromptDialog(parent, (char *) "Save Viewpoint",
02907                                            args, n);
02908 
02909    XmStringFree(label);
02910    XtAddCallback(nameViewPtDialog, XmNokCallback, getViewPtNameCB, This);
02911    XtAddCallback(nameViewPtDialog, XmNcancelCallback,
02912                  (XtCallbackProc) XtDestroyWidget, NULL);
02913 
02914    Widget text = XtNameToWidget(nameViewPtDialog, "Text");
02915    XtVaSetValues(text, XmNmaxLength, This->MAX_VP_NAME, NULL);
02916    std::string autoName = "";
02917    if (!This->warningFlag) { //leave the TextField as it is if coming back from warning dialog
02918       autoName = This->viewPtAutoName();
02919    }
02920    This->warningFlag = false;
02921    XmTextSetString(text, (char *) autoName.c_str());
02922    XmTextSetInsertionPosition(text, autoName.length());
02923 
02924    XtUnmanageChild(XtNameToWidget(nameViewPtDialog, "Help"));
02925    XtManageChild(nameViewPtDialog);
02926 }
02927 
02928 
02929 std::string G4OpenInventorXtExaminerViewer::viewPtAutoName()
02930 {
02931    std::string viewPt;
02932    std::stringstream sstream;
02933    std::vector<int> existingViewPts;
02934    int tmp;
02935 
02936    //Build the list of names of the form viewpoint_* already present
02937    for (unsigned int i = 0; i < this->viewPtList.size(); ++i) {
02938       viewPt = this->viewPtList[i].viewPtName;
02939       if (viewPt.find("viewpoint_") != std::string::npos) {
02940          tmp = atoi(viewPt.substr(10).c_str());
02941          if (tmp == 0) {
02942             //0 means couldn't convert to integer OR viewpoint_0
02943             if (!viewPt.compare("viewpoint_0"))
02944                existingViewPts.push_back(0);
02945          } else
02946             existingViewPts.push_back(tmp);
02947       }
02948    }
02949 
02950    sstream.str("");
02951    sstream.clear();
02952 
02953    //Return the view viewpoint_* name available
02954    if (existingViewPts.size() > 0) {
02955       int vpNum = 0;
02956       while (true) {
02957          if (std::find(existingViewPts.begin(), existingViewPts.end(), vpNum)
02958              == existingViewPts.end()) {
02959             sstream << "viewpoint_" << vpNum;
02960             return sstream.str();
02961          }
02962          ++vpNum;
02963       }
02964    } else {
02965       return "viewpoint_0";
02966    }
02967    return "";
02968 }
02969 
02970 
02971 void G4OpenInventorXtExaminerViewer::abbrOutputCB(Widget,
02972                                    XtPointer client_data,
02973                                    XtPointer)
02974 {
02975    G4OpenInventorXtExaminerViewer * This = 
02976       (G4OpenInventorXtExaminerViewer *) client_data;
02977    This->abbrOutputFlag = !(This->abbrOutputFlag);
02978 }
02979 
02980 
02981 void G4OpenInventorXtExaminerViewer::pickRefPathCB(Widget,
02982                                     XtPointer client_data,
02983                                     XtPointer)
02984 {
02985    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
02986 
02987    // Save viewing state and go to picking mode
02988    This->viewingBeforePickRef = This->isViewing();
02989    if(This->isViewing())
02990       This->setViewing(false);
02991    This->setComponentCursor(SoXtCursor(SoXtCursor::CROSSHAIR));
02992    This->pickRefPathFlag = true;
02993 }
02994 
02995 
02996 // Examines new viewpoint name and if OK calls saveViewPt.
02997 
02998 void G4OpenInventorXtExaminerViewer::getViewPtNameCB(Widget w, 
02999                                         XtPointer client_data,
03000                                         XtPointer call_data)
03001 {
03002    char *name = NULL;
03003    std::string strName;
03004    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
03005    XmSelectionBoxCallbackStruct *cbs =
03006       (XmSelectionBoxCallbackStruct *) call_data;
03007    XmStringGetLtoR(cbs->value, XmFONTLIST_DEFAULT_TAG, &name);
03008 
03009    if (!name) {
03010       return;
03011    }
03012    if (!*name) {
03013       XtFree(name);
03014       return;
03015    }
03016 
03017    strName = name;
03018    XtFree(name);
03019 
03020    int beg = strName.find_first_not_of(' '); // Remove leading/trailing spaces
03021    int end = strName.find_last_not_of(' ');
03022    strName = strName.substr(beg, end - beg + 1);
03023 
03024    bool nameExists = false;
03025    int size = This->viewPtList.size();
03026    for (int i = 0; i < size; i++) {
03027       if (!strcmp(This->viewPtList[i].viewPtName, strName.c_str())) {
03028          nameExists = true;
03029          break;
03030       }
03031    }
03032 
03033    if (!nameExists) {
03034       name = new char[This->MAX_VP_NAME + 1];
03035       strcpy(name, strName.c_str());
03036       if (This->viewPtIdx == -1)
03037          This->viewPtIdx = 0;
03038       This->saveViewPt(name);
03039       if (This->listsDialog) {
03040          XmListAddItemUnselected(This->myViewPtList, cbs->value, 0); // vpName
03041       }
03042       //Dismiss the nameViewPtDialog dialog
03043       XtUnmanageChild(w);
03044    } else {
03045       String dialogName = (char *) "Existing Viewpoint";
03046       std::string msg = "The viewpoint already exists.";
03047       This->warningMsgDialog(msg, dialogName, NULL);
03048 
03049    }
03050 }
03051 
03052 
03053 // Saves current camera parameters to a viewpoint file.
03054 
03055 void G4OpenInventorXtExaminerViewer::saveViewPt(char *name)
03056 {
03057    SbVec3f axis;
03058    viewPtData tmp;
03059    float x, y, z, angle;
03060    SoCamera * camera = getCamera();
03061 
03062    if (viewPtList.size() == 0) {
03063       writeViewPtIdx();
03064       XtSetSensitive(nextViewPtButton, True); // Makes arrow buttons clickable
03065       XtSetSensitive(prevViewPtButton, True);
03066    }
03067 
03068    tmp.viewPtName = name;
03069    tmp.viewportMapping = camera->viewportMapping.getValue();
03070    tmp.position = camera->position.getValue();
03071    tmp.orientation = camera->orientation.getValue();
03072    tmp.aspectRatio = camera->aspectRatio.getValue();
03073    tmp.nearDistance = camera->nearDistance.getValue();
03074    tmp.farDistance = camera->farDistance.getValue();
03075    tmp.focalDistance = camera->focalDistance.getValue();
03076 
03077    // Save camera height (changed by zooming)
03078    if (camera->isOfType(SoPerspectiveCamera::getClassTypeId())) {
03079       tmp.height = ((SoPerspectiveCamera *) camera)->heightAngle.getValue();
03080       tmp.camType = PERSPECTIVE;
03081    } else if (camera->isOfType(SoOrthographicCamera::getClassTypeId())) {
03082       tmp.height = ((SoOrthographicCamera *) camera)->height.getValue();
03083       tmp.camType = ORTHOGRAPHIC;
03084    } else {
03085       SoDebugError::post("G4OpenInventorXtExaminerViewer::saveViewPtCB",
03086                          "Only Perspective and Orthographic cameras are supported.");
03087       return;
03088    }
03089 
03090    viewPtList.push_back(tmp);
03091 
03092    // Now save the view point to a .txt file
03093    std::string vpName = name;
03094 
03095    while ((int) vpName.size() <= MAX_VP_NAME)
03096       vpName += " ";
03097 
03098    fileOut << vpName << std::endl;
03099    tmp.position.getValue(x, y, z);
03100    fileOut << x << " " << y << " " << z << std::endl;
03101 
03102    // Reusing x, y and z for storing the axis
03103    tmp.orientation.getValue(axis, angle);
03104    axis.getValue(x, y, z);
03105    fileOut << x << " " << y << " " << z << " " << angle << std::endl;
03106 
03107    fileOut << tmp.camType << " " << tmp.height << std::endl;
03108    fileOut << tmp.focalDistance << " ";
03109    fileOut << tmp.nearDistance << " ";
03110    fileOut << tmp.farDistance << std::endl;
03111    fileOut << tmp.viewportMapping << " ";
03112    fileOut << tmp.aspectRatio << "\n" << std::endl;
03113    fileOut.flush();
03114    viewPtIdx++;
03115 }
03116 
03117 
03118 void G4OpenInventorXtExaminerViewer::deleteViewPtCB(Widget,
03119                                      XtPointer client_data,
03120                                      XtPointer)
03121 {
03122    G4OpenInventorXtExaminerViewer * This =
03123       (G4OpenInventorXtExaminerViewer *) client_data;
03124    This->deleteViewPt();
03125 }
03126 
03127 
03128 // Deletes current viewpoint the user is looking at.
03129 // Updates the input file and bookmarks as well.
03130 
03131 void G4OpenInventorXtExaminerViewer::deleteViewPt(char *vpName)
03132 {
03133    std::string line;
03134    int end;
03135    fileIn.open(fileName.c_str());
03136    std::ofstream out("temporaryFile.txt");
03137 
03138    if (!vpName)
03139       vpName = viewPtList[viewPtIdx].viewPtName;
03140 
03141    if (listsDialog) {
03142       XmString vpNameStr = XmStringCreateLocalized(vpName);
03143 
03144       XmListDeleteItem(myViewPtList, vpNameStr);
03145       XmStringFree(vpNameStr);
03146    }
03147 
03148    getline(fileIn, line); // Printing the viewpoint idx
03149    out << line << "\n";
03150 
03151    while (getline(fileIn, line)) {
03152       end = line.find_last_not_of(' ');
03153       line = line.substr(0, end + 1);
03154       if (!strcmp(line.c_str(), vpName)) { // Equal
03155          while (line.size()) {
03156             getline(fileIn, line);
03157          }
03158 
03159          while (getline(fileIn, line))
03160             out << line << "\n";
03161       } else {
03162          while (line.size()) {
03163             out << line << "\n";
03164             getline(fileIn, line);
03165          }
03166          out << "\n";
03167       }
03168    }
03169 
03170    int idx = 0; // Remove viewpoint from the vector
03171    int size = viewPtList.size();
03172    while (idx < size) {
03173       if (!strcmp(viewPtList[idx].viewPtName, vpName)) {
03174          viewPtList.erase(viewPtList.begin() + idx);
03175          break;
03176       }
03177       idx++;
03178    }
03179 
03180    out.close();
03181    fileOut.close();
03182    fileIn.clear();
03183    fileIn.close();
03184 
03185    remove(fileName.c_str());
03186    rename("temporaryFile.txt", fileName.c_str());
03187 
03188    fileOut.open(fileName.c_str(), std::ios::in);
03189    fileOut.seekp(0, std::ios::end);
03190 
03191    if (!viewPtList.size()) { // viewPtList is empty
03192       curViewPtName = (char *) "";
03193       scheduleRedraw();
03194       XtSetSensitive(nextViewPtButton, False);
03195       XtSetSensitive(prevViewPtButton, False);
03196    } else {
03197       if (viewPtIdx >= (int) viewPtList.size())
03198          viewPtIdx--;
03199       writeViewPtIdx();
03200       setViewPt();
03201    }
03202 }
03203 
03204 
03205 // Renames currently selected viewpoint.
03206 
03207 void G4OpenInventorXtExaminerViewer::renameViewPt(char *vpName)
03208 {
03209    int idx = 0, end, pos;
03210    int size = viewPtList.size();
03211    std::string line, newName;
03212    fileIn.open(fileName.c_str());
03213 
03214    newName = vpName;
03215    while ((int) newName.size() < MAX_VP_NAME)
03216       newName += " ";
03217 
03218    getline(fileIn, line);
03219    pos = fileIn.tellg();
03220    while (getline(fileIn, line)) {
03221       end = line.find_last_not_of(' ');
03222       line = line.substr(0, end + 1);
03223       if (!strcmp(line.c_str(), curViewPtName)) {
03224          fileOut.seekp(pos);
03225          fileOut << newName;
03226          fileOut.seekp(0, std::ios::end); // Set the file pointer to the end of the file
03227          break;
03228       }
03229       while (line.size())
03230          getline(fileIn, line);
03231       pos = fileIn.tellg();
03232    }
03233 
03234    fileIn.close();
03235    fileIn.clear();
03236 
03237    while (idx < size) {
03238       if (!strcmp(viewPtList[idx].viewPtName, curViewPtName)) {
03239          strcpy(viewPtList[idx].viewPtName, vpName);
03240          break;
03241       }
03242       idx++;
03243    }
03244 }
03245 
03246 
03247 // Rewrites entire viewpoint file with sorted viewpoints.
03248 
03249 void G4OpenInventorXtExaminerViewer::sortViewPts(std::vector<std::string> sortedViewPts) 
03250 {
03251    SbVec3f axis;
03252    float x, y, z, angle;
03253    int sortIdx = 0, unsortIdx = 0;
03254 
03255    if (fileOut.is_open())
03256       fileOut.close();
03257 
03258    fileOut.open(fileName.c_str()); // Erase current viewpoint file
03259 
03260    writeViewPtIdx();
03261 
03262    int size = sortedViewPts.size();
03263    while (sortIdx < size) {
03264       while (strcmp(sortedViewPts[sortIdx].c_str(),
03265                     viewPtList[unsortIdx].viewPtName))
03266          unsortIdx++;
03267 
03268       std::string vpName = viewPtList[unsortIdx].viewPtName;
03269 
03270       while ((int) vpName.size() < MAX_VP_NAME)
03271          vpName += " ";
03272       fileOut << vpName << std::endl;
03273       viewPtList[unsortIdx].position.getValue(x, y, z);
03274       fileOut << x << " " << y << " " << z << std::endl;
03275 
03276       // Reusing x, y and z for storing the axis
03277       viewPtList[unsortIdx].orientation.getValue(axis, angle);
03278       axis.getValue(x, y, z);
03279       fileOut << x << " " << y << " " << z << " " << angle << std::endl;
03280 
03281       fileOut << viewPtList[unsortIdx].camType << " "
03282               << viewPtList[unsortIdx].height << std::endl;
03283       fileOut << viewPtList[unsortIdx].focalDistance << " ";
03284 
03285       fileOut << viewPtList[unsortIdx].nearDistance << " ";
03286 
03287       fileOut << viewPtList[unsortIdx].farDistance << std::endl;
03288 
03289       fileOut << viewPtList[unsortIdx].viewportMapping << " ";
03290       fileOut << viewPtList[unsortIdx].aspectRatio << "\n" << std::endl;
03291       fileOut.flush();
03292 
03293       unsortIdx = 0;
03294       sortIdx++;
03295    }
03296 }
03297 
03298 
03299 //  Loads view point data from a file into a vector.
03300 
03301 bool G4OpenInventorXtExaminerViewer::loadViewPts() 
03302 {
03303    bool error = false;
03304    viewPtData tmp;
03305    std::string token;
03306    SbVec3f axis;
03307    SbRotation orient;
03308    float x, y, z, angle;
03309 
03310    // Gets the last view point accessed, stored in the first line of the data file.
03311    fileIn >> token;
03312    parseString<int>(viewPtIdx, token, error);
03313    getline(fileIn, token); // Remove "\n"
03314    // Converts data from string type into necessary types
03315    while (getline(fileIn, token)) {
03316 
03317       int end = token.find_last_not_of(' '); // Remove padded spaces
03318       token = token.substr(0, end + 1);
03319 
03320       char *vpName = new char[token.size() + 1];
03321       strcpy(vpName, token.c_str());
03322       tmp.viewPtName = vpName;
03323       fileIn >> token;
03324 
03325       parseString<float>(x, token, error);
03326       fileIn >> token;
03327       parseString<float>(y, token, error);
03328       fileIn >> token;
03329       parseString<float>(z, token, error);
03330       fileIn >> token;
03331       tmp.position = axis.setValue(x, y, z);
03332 
03333       parseString<float>(x, token, error);
03334       fileIn >> token;
03335       parseString<float>(y, token, error);
03336       fileIn >> token;
03337       parseString<float>(z, token, error);
03338       fileIn >> token;
03339       parseString<float>(angle, token, error);
03340       fileIn >> token;
03341       orient.setValue(axis.setValue(x, y, z), angle);
03342       tmp.orientation = orient.getValue();
03343 
03344       int camType;
03345       parseString<int>(camType, token, error);
03346       fileIn >> token;
03347       tmp.camType = (CameraType) camType;
03348 
03349       parseString<float>(tmp.height, token, error);
03350       fileIn >> token;
03351       parseString<float>(tmp.focalDistance, token, error);
03352       fileIn >> token;
03353       parseString<float>(tmp.nearDistance, token, error);
03354       fileIn >> token;
03355       parseString<float>(tmp.farDistance, token, error);
03356       fileIn >> token;
03357       parseString<int>(tmp.viewportMapping, token, error);
03358       fileIn >> token;
03359       parseString<float>(tmp.aspectRatio, token, error);
03360 
03361       getline(fileIn, token); // To remove "\n" characters
03362       getline(fileIn, token);
03363 
03364       if (error) {
03365          viewPtIdx = 0;
03366          viewPtList.clear();
03367          return false;
03368       }
03369       viewPtList.push_back(tmp);
03370    }
03371 
03372    return true;
03373 }
03374 
03375 
03376 // Converts a string type word into a float type.
03377 
03378 template<class T> 
03379 void G4OpenInventorXtExaminerViewer::parseString(T &t, const std::string &s,
03380                                                  bool &error) 
03381 {
03382    std::istringstream str(s);
03383    if ((str >> t).fail())
03384       error = true;
03385 }
03386 
03387 
03388 // Generic fileSelectionDialog creation.
03389 
03390 void G4OpenInventorXtExaminerViewer::popUpFileSelDialog(Widget &dialog,
03391                                                 std::string dialogName,
03392                                                 std::string buttonLabel,
03393                                                 XtCallbackProc cbOK)
03394 {
03395    int n;
03396    Arg args[3];
03397    Widget parent, scrollWidget;
03398    parent = SoXt::getShellWidget(getParentWidget());
03399 
03400    if (dialog == NULL) {
03401 
03402       // Change the 'OK' button to whatever buttonLabel contains
03403       XmString str = XmStringCreateLocalized((char *) buttonLabel.c_str());
03404 
03405       n = 0;
03406       XtSetArg(args[n], XmNokLabelString, str);         n++;
03407       XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE);                n++;
03408 
03409       dialog = XmCreateFileSelectionDialog(parent,
03410                                            (char *) dialogName.c_str(), args, n);
03411 
03412       XtAddCallback(dialog, XmNokCallback, cbOK, this);
03413       XtAddCallback(dialog, XmNcancelCallback, cancelFileSelDialogCB, this);
03414 
03415       // Adding scrolling functionality to the widget
03416       scrollWidget = XmFileSelectionBoxGetChild(dialog, XmDIALOG_DIR_LIST);
03417       if (scrollWidget)
03418          xmAddMouseEventHandler(scrollWidget);
03419       scrollWidget = XmFileSelectionBoxGetChild(dialog, XmDIALOG_LIST);
03420       if (scrollWidget)
03421          xmAddMouseEventHandler(scrollWidget);
03422 
03423       XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
03424       XmStringFree(str);
03425    }
03426    XtManageChild(dialog);
03427 }
03428 
03429 
03430 // Generic fileSelectionDialog cancelation.
03431 
03432 void G4OpenInventorXtExaminerViewer::cancelFileSelDialogCB(Widget w,
03433                                                            XtPointer,
03434                                                            XtPointer)
03435 {
03436    XtUnmanageChild(w);
03437 }
03438 
03439 
03440 // Displays a file selection dialog that allows to open a new viewpoint file.
03441 
03442 void G4OpenInventorXtExaminerViewer::openViewPtFileCB(Widget,
03443                                        XtPointer client_data,
03444                                        XtPointer)
03445 {
03446    G4OpenInventorXtExaminerViewer * This =
03447       (G4OpenInventorXtExaminerViewer *) client_data;
03448    This->popUpFileSelDialog(This->openFileDialog, "Open File", "Load",
03449                             viewPtFileSelectedCB);
03450 }
03451 
03452 
03453 void G4OpenInventorXtExaminerViewer::viewPtFileSelectedCB(Widget w, 
03454                                              XtPointer client_data,
03455                                              XtPointer call_data)
03456 {
03457    char *file = NULL;
03458    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
03459    XmFileSelectionBoxCallbackStruct *cbs =
03460       (XmFileSelectionBoxCallbackStruct *) call_data;
03461 
03462    // Get the file
03463    if (cbs) {
03464       if (!(file = (char *) XmStringUnparse(cbs->value,
03465                                             XmFONTLIST_DEFAULT_TAG, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0,
03466                                             XmOUTPUT_ALL))) {
03467          SoDebugError::post("G4OpenInventorXtExaminerViewer::fileSelectedCB",
03468                             "Internal error during file opening");
03469          return;
03470       }
03471 
03472       This->fileIn.open(file);
03473       if (!This->fileIn.fail()) {
03474          // Opens a file without erasing it
03475          This->cleanUpAfterPrevFile();
03476          if (!This->loadViewPts()) {
03477             String dialogName = (char *) "Error Loading File";
03478             std::string msg = "Wrong or corrupted input file.";
03479             This->warningMsgDialog(msg, dialogName, NULL);
03480          } else {
03481             This->fileName = file;
03482             This->fileOut.open(This->fileName.c_str(), std::ios::in);
03483             This->fileOut.seekp(0, std::ios::end);
03484 
03485             if (!This->listsDialog)
03486                constructListsDialog(w, This, NULL); // Pop up listsDialog
03487             else
03488                This->addViewPoints();
03489 
03490             std::string newDialogName = This->fileName.substr(
03491                                                               This->fileName.rfind('/') + 1);
03492             XtVaSetValues(This->myShellDialog, XmNtitle,
03493                           (char *) newDialogName.c_str(), NULL);
03494 
03495             if (This->viewPtList.size()) {
03496                This->setViewPt();
03497                XmTextSetString(This->viewPtSelection, NULL);
03498                XtSetSensitive(This->nextViewPtButton, True);
03499                XtSetSensitive(This->prevViewPtButton, True);
03500             } else {
03501                XtSetSensitive(This->nextViewPtButton, False);
03502                XtSetSensitive(This->prevViewPtButton, False);
03503             }
03504 
03505             XtUnmanageChild(w);
03506          }
03507 
03508          This->fileIn.close();
03509       } else {
03510          String dialogName = (char *) "Nonexistent File";
03511          std::string msg = "Unable to open file.";
03512          This->warningMsgDialog(msg, dialogName, NULL);
03513       }
03514    }
03515 
03516    This->fileIn.clear();
03517    XtFree(file);
03518 }
03519 
03520 
03521 // Adds bookmarks to listsDialog.
03522 
03523 void G4OpenInventorXtExaminerViewer::addViewPoints()
03524 {
03525    int size = viewPtList.size();
03526    if (!size)
03527       return;
03528 
03529    XmString *viewPts;
03530 
03531    viewPts = (XmString *) XtMalloc(size * sizeof(XmString));
03532    for (int i = 0; i < size; i++)
03533       viewPts[i] = XmStringCreateLocalized(viewPtList[i].viewPtName);
03534 
03535    XmListAddItemsUnselected(myViewPtList, viewPts, size, 1);
03536 
03537    if (viewPts != NULL) {
03538       for (int i = 0; i < size; i++)
03539          XmStringFree(viewPts[i]);
03540       XtFree((char *) viewPts);
03541    }
03542 }
03543 
03544 
03545 // Called before loading a new viewpoint file. 
03546 // Resets member fields to default values.
03547 
03548 void G4OpenInventorXtExaminerViewer::cleanUpAfterPrevFile()
03549 {
03550    viewPtIdx = -1;
03551    viewPtList.clear();
03552    setSuperimpositionEnabled(superimposition, FALSE);
03553    scheduleRedraw();
03554    currentState = GENERAL;
03555    if (fileOut.is_open())
03556       fileOut.close();
03557    if (listsDialog) // Clear viewpoints
03558       XmListDeleteAllItems(myViewPtList);
03559 }
03560 
03561 
03562 // Generic function for displaying a warning dialog.
03563 
03564 void G4OpenInventorXtExaminerViewer::warningMsgDialog(std::string msg,
03565                                                       String dialogName,
03566                                                       XtCallbackProc cb)
03567 {
03568    Arg args[5];
03569    unsigned int n;
03570    XmString warningMsg;
03571 
03572    warningMsg = XmStringCreateLocalized((char *)msg.c_str());
03573 
03574    n = 0;
03575    XtSetArg(args[n], XmNmessageString, warningMsg);     n++;
03576    Widget warningDialog = XmCreateWarningDialog(getParentWidget(), dialogName, args, n);
03577    if (cb)
03578       XtAddCallback(warningDialog, XmNokCallback, cb, this);
03579 
03580    XmStringFree(warningMsg);
03581 
03582    XtVaSetValues (warningDialog, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, NULL);
03583    XtUnmanageChild(XtNameToWidget(warningDialog, "Help"));
03584    XtUnmanageChild(XtNameToWidget(warningDialog, "Cancel"));
03585 
03586    XtManageChild(warningDialog);
03587 }
03588 
03589 
03590 void G4OpenInventorXtExaminerViewer::newViewPtFileCB(Widget,
03591                                                      XtPointer client_data,
03592                                                      XtPointer)
03593 {
03594    G4OpenInventorXtExaminerViewer * This = 
03595       (G4OpenInventorXtExaminerViewer *) client_data;
03596    This->popUpFileSelDialog(This->newFileDialog, "New File", "Save",
03597                             createNewVPFileCB);
03598 }
03599 
03600 
03601 void G4OpenInventorXtExaminerViewer::createNewVPFileCB(Widget w, 
03602                                                        XtPointer client_data,
03603                                                        XtPointer call_data)
03604 {
03605    char *file;
03606    std::string fName;
03607    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
03608    XmFileSelectionBoxCallbackStruct *cbs =
03609       (XmFileSelectionBoxCallbackStruct *) call_data;
03610 
03611    // Get the file
03612    if (cbs) {
03613       if (!(file = (char *) XmStringUnparse(cbs->value,
03614                                             XmFONTLIST_DEFAULT_TAG, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0,
03615                                             XmOUTPUT_ALL))) {
03616          SoDebugError::post("G4OpenInventorXtExaminerViewer::createNewVPFileCB",
03617                             "Internal error during file opening");
03618          return;
03619       }
03620 
03621       This->fileName = file;
03622       fName = This->fileName.substr(This->fileName.rfind('/') + 1); // Extracts just the name of the file
03623       This->fileIn.open(file);
03624       if (This->fileIn.fail()) { // Filename does not exist
03625          This->cleanUpAfterPrevFile();
03626          This->fileOut.open(file); // Creates a new empty file
03627          XtSetSensitive(This->nextViewPtButton, False);
03628          XtSetSensitive(This->prevViewPtButton, False);
03629          if (This->listsDialog)
03630             closeListsDialogCB(w, This, NULL);
03631          constructListsDialog(w, This, NULL);
03632          XtUnmanageChild(w);
03633          if (This->returnToSaveVP) {
03634             This->returnToSaveVP = false;
03635             saveViewPtCB(NULL, This, NULL);
03636          }
03637       } else { // Filename already exists
03638          String dialogName = (char *) "Existing File";
03639          std::string msg = "'" + fName + "' already exists. Do you want to overwrite it?";
03640          This->warningMsgDialog(msg, dialogName, overwriteFileCB);
03641          This->fileIn.close();
03642       }
03643       This->fileIn.clear();
03644       XtFree(file);
03645    }
03646 }
03647 
03648 
03649 void G4OpenInventorXtExaminerViewer::overwriteFileCB(Widget, 
03650                                                      XtPointer client_data,
03651                                                      XtPointer)
03652 {
03653    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
03654    This->cleanUpAfterPrevFile();
03655    XtSetSensitive(This->nextViewPtButton, False);
03656    XtSetSensitive(This->prevViewPtButton, False);
03657 
03658    XtUnmanageChild(This->newFileDialog);
03659 
03660    This->fileOut.open(This->fileName.c_str());
03661 
03662    if (This->returnToSaveVP) {
03663       This->returnToSaveVP = false;
03664       saveViewPtCB(NULL, This, NULL);
03665    }
03666 }
03667 
03668 
03669 void G4OpenInventorXtExaminerViewer::loadRefCoordsDialogCB(Widget,
03670                                             XtPointer client_data,
03671                                             XtPointer)
03672 {
03673    G4OpenInventorXtExaminerViewer * This = 
03674       (G4OpenInventorXtExaminerViewer *)client_data;
03675    This->popUpFileSelDialog(This->loadRefCoordsDialog, "Load Ref Coords",
03676                             "Load", loadRefCoordsCB);
03677 }
03678 
03679 
03680 void G4OpenInventorXtExaminerViewer::loadRefCoordsCB(Widget w, 
03681                                                      XtPointer client_data,
03682                                                      XtPointer call_data)
03683 {
03684    char *file = NULL;
03685    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *)client_data;
03686    XmFileSelectionBoxCallbackStruct *cbs = (XmFileSelectionBoxCallbackStruct *)call_data;
03687 
03688    // Get the file
03689    if(cbs) {
03690 
03691       file = (char *)XmStringUnparse(cbs->value, XmFONTLIST_DEFAULT_TAG,
03692                                      XmCHARSET_TEXT, XmCHARSET_TEXT,
03693                                      NULL, 0, XmOUTPUT_ALL);
03694 
03695       std::ifstream ifs(file);
03696       if(ifs.is_open()){
03697          This->refParticleTrajectory.clear();
03698          float x,y,z;
03699          while(ifs >> x >> y >> z){
03700             This->refParticleTrajectory.push_back(SbVec3f(x,y,z));
03701          }
03702          ifs.close();
03703          XtUnmanageChild(w);
03704       }
03705       else{
03706          String dialogName = (char *) "Problem reading file";
03707          std::string msg = "Problem reading file";
03708          This->warningMsgDialog(msg, dialogName, NULL);
03709          return;
03710 
03711       }
03712    }
03713 
03714    return;
03715 }
03716 
03717 
03718 void G4OpenInventorXtExaminerViewer::saveRefCoordsDialogCB(Widget,
03719                                             XtPointer client_data,
03720                                             XtPointer)
03721 {
03722    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
03723 
03724    if (!This->refParticleTrajectory.size()) {
03725       String dialogName = (char *) "No Reference Trajectory";
03726       std::string msg = "You need to start a run or load a reference trajectory from a file";
03727       This->warningMsgDialog(msg, dialogName, NULL);
03728       return;
03729    }
03730 
03731    int n;
03732    Arg args[3];
03733    Widget parent, scrollWidget;
03734    parent = SoXt::getShellWidget(This->getParentWidget());
03735 
03736    if (This->saveRefCoordsDialog == NULL) {
03737 
03738       // Change the 'OK' button to whatever buttonLabel contains
03739       XmString str = XmStringCreateLocalized((char *)"Save");
03740 
03741       n = 0;
03742       XtSetArg(args[n], XmNokLabelString, str);         n++;
03743       XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE);                n++;
03744 
03745       This->saveRefCoordsDialog = XmCreateFileSelectionDialog(parent,(char *)"Save Ref Coords", args, n);
03746 
03747       XtAddCallback(This->saveRefCoordsDialog, XmNokCallback, saveRefCoordsCB, This);
03748       XtAddCallback(This->saveRefCoordsDialog, XmNcancelCallback, cancelFileSelDialogCB, This);
03749 
03750       // Adding scrolling functionality to the widget
03751       scrollWidget = XmFileSelectionBoxGetChild(This->saveRefCoordsDialog, XmDIALOG_DIR_LIST);
03752       if (scrollWidget)
03753          xmAddMouseEventHandler(scrollWidget);
03754       scrollWidget = XmFileSelectionBoxGetChild(This->saveRefCoordsDialog, XmDIALOG_LIST);
03755       if (scrollWidget)
03756          xmAddMouseEventHandler(scrollWidget);
03757 
03758       XtUnmanageChild(XmSelectionBoxGetChild(This->saveRefCoordsDialog, XmDIALOG_HELP_BUTTON));
03759       XmStringFree(str);
03760    }
03761 
03762    //TODO: Auto name?
03763 
03764    XtManageChild(This->saveRefCoordsDialog);
03765 
03766 }
03767 
03768 
03769 void G4OpenInventorXtExaminerViewer::saveRefCoordsCB(Widget w, 
03770                                                      XtPointer client_data,
03771                                                      XtPointer call_data)
03772 {
03773    char *file;
03774    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
03775    XmFileSelectionBoxCallbackStruct *cbs =
03776       (XmFileSelectionBoxCallbackStruct *) call_data;
03777 
03778    // Get the file
03779    if (cbs) {
03780 
03781       file = (char *)XmStringUnparse(cbs->value, XmFONTLIST_DEFAULT_TAG,
03782                                      XmCHARSET_TEXT, XmCHARSET_TEXT,
03783                                      NULL, 0, XmOUTPUT_ALL);
03784 
03785       std::ifstream ifile(file);
03786       if (ifile) {
03787          //File already exists
03788 
03789          Arg args[4];
03790          Widget parent = This->getParentWidget();       //gets the dialogshell of the ExaminerViewer widget
03791          Widget confirmOverwriteDialog;
03792          XmString msg;
03793 
03794          confirmOverwriteDialog = XmCreateQuestionDialog (parent, (char *)"Confirm overwrite", args, 0);
03795          msg = XmStringCreateLocalized ((char *)"File exists. Overwrite?");
03796          XtVaSetValues (confirmOverwriteDialog, XmNmessageString, msg, NULL);
03797 
03798          // If users presses OK, we want to return to this function and
03799          // save the file.  For that to work, pass it the current widget
03800          // to be able to grab the filename.
03801          XtVaSetValues (confirmOverwriteDialog, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, NULL);
03802          XtAddCallback (confirmOverwriteDialog, XmNokCallback, saveRefCoordsOverWriteCB, client_data);
03803          XtAddCallback (confirmOverwriteDialog, XmNcancelCallback, saveRefCoordsOverWriteCB, client_data);
03804 
03805          XmStringFree (msg);
03806 
03807          //The confirmOverwriteDialog will need this
03808          This->saveRefCoordsFileName = file;
03809          This->saveRefCoordsWidget = w;
03810 
03811          XtUnmanageChild(XtNameToWidget(confirmOverwriteDialog, "Help"));
03812          XtManageChild(confirmOverwriteDialog);
03813 
03814          return;
03815       }
03816       else{
03817 
03818          std::ofstream ofs(file);
03819          if(ofs.is_open()){
03820             float x,y,z;
03821             for(unsigned int i=0; i < This->refParticleTrajectory.size(); ++i){
03822                This->refParticleTrajectory[i].getValue(x,y,z);
03823                ofs << x << " " << y << " " << z << "\n";
03824             }
03825             ofs.close();
03826             XtUnmanageChild(w);
03827          }
03828          else{
03829             String dialogName = (char *) "Error opening file";
03830             std::string msg = "There was a problem trying to open the file '";
03831             msg += This->saveRefCoordsFileName;
03832             msg += "'";
03833 
03834             This->warningMsgDialog(msg, dialogName, NULL);
03835          }
03836       }
03837    }
03838 
03839    return;
03840 }
03841 
03842 
03843 void G4OpenInventorXtExaminerViewer::saveRefCoordsOverWriteCB(Widget w, 
03844                                                  XtPointer client_data,
03845                                                  XtPointer call_data)
03846 {
03847    XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;
03848    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
03849 
03850    switch (cbs->reason) {
03851    case XmCR_OK:
03852       {
03853          // Overwrite confirmed, save file and dismiss both
03854          // dialogs (file dialog and overwrite confirmation dialog)
03855          std::ofstream ofs(This->saveRefCoordsFileName.c_str());
03856          if(ofs.is_open()){
03857             float x,y,z;
03858             for(unsigned int i=0; i < This->refParticleTrajectory.size(); ++i){
03859                This->refParticleTrajectory[i].getValue(x,y,z);
03860                ofs << x << " " << y << " " << z << "\n";
03861             }
03862             ofs.close();
03863             XtUnmanageChild(w);
03864             XtUnmanageChild(This->saveRefCoordsWidget);
03865          }
03866          else{
03867             String dialogName = (char *) "Error opening file";
03868             std::string msg = "There was a problem trying to open the file '";
03869             msg += This->saveRefCoordsFileName;
03870             msg += "'";
03871 
03872             This->warningMsgDialog(msg, dialogName, NULL);
03873          }
03874          break;
03875       }
03876    case XmCR_CANCEL:
03877       {
03878          // Overwrite refused, dismiss overwrite confirmation
03879          // dialog and return to file dialog
03880 
03881          // Give focus to the text field instead of the OK button
03882          XmProcessTraversal(XtNameToWidget(This->saveRefCoordsWidget, "Text"), XmTRAVERSE_CURRENT);
03883 
03884          XtUnmanageChild(w);
03885          This->saveRefCoordsFileName.clear();
03886          This->saveRefCoordsWidget = NULL;
03887          break;
03888       }
03889    default:
03890       return;
03891    }
03892 }
03893 
03894 
03895 void G4OpenInventorXtExaminerViewer::loadSceneGraphDialogCB(Widget,
03896                                              XtPointer client_data,
03897                                              XtPointer)
03898 {
03899    G4OpenInventorXtExaminerViewer * This =
03900       (G4OpenInventorXtExaminerViewer *)client_data;
03901    This->popUpFileSelDialog(This->loadSceneGraphDialog, "Load Scene Graph",
03902                             "Load", loadSceneGraphCB);
03903    return;
03904 }
03905 
03906 
03907 void G4OpenInventorXtExaminerViewer::loadSceneGraphCB(Widget w, 
03908                                                       XtPointer client_data,
03909                                                       XtPointer call_data)
03910 {
03911    char *file = NULL;
03912    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *)client_data;
03913    XmFileSelectionBoxCallbackStruct *cbs = (XmFileSelectionBoxCallbackStruct *)call_data;
03914 
03915    if(cbs) {
03916 
03917       file = (char *)XmStringUnparse(cbs->value, XmFONTLIST_DEFAULT_TAG,
03918                                      XmCHARSET_TEXT, XmCHARSET_TEXT,
03919                                      NULL, 0, XmOUTPUT_ALL);
03920 
03921       SoInput sceneInput;
03922       if (!sceneInput.openFile(file)) {
03923          String dialogName = (char *) "Problem opening file";
03924          std::string msg = "Cannot open file ";
03925          msg += file;
03926          This->warningMsgDialog(msg, dialogName, NULL);
03927 
03928          sceneInput.closeFile();
03929          XtUnmanageChild(w);
03930       }
03931       // Read the whole file into the database
03932       This->newSceneGraph = SoDB::readAll(&sceneInput);
03933       if (This->newSceneGraph == NULL) {
03934          String dialogName = (char *) "Problem reading file";
03935          std::string msg = "Problem reading file";
03936          This->warningMsgDialog(msg, dialogName, NULL);
03937          return;
03938       }
03939 
03940       //This->newSceneGraph->ref();
03941       This->setSceneGraph(This->newSceneGraph);
03942    }
03943 
03944    return;
03945 }
03946 
03947 
03948 void G4OpenInventorXtExaminerViewer::saveSceneGraphDialogCB(Widget, 
03949                                              XtPointer client_data,
03950                                              XtPointer)
03951 {
03952    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
03953 
03954    int n;
03955    Arg args[3];
03956    Widget parent, scrollWidget;
03957    parent = SoXt::getShellWidget(This->getParentWidget());
03958 
03959    if (This->saveSceneGraphDialog == NULL) {
03960 
03961       // Change the 'OK' button to whatever buttonLabel contains
03962       XmString str = XmStringCreateLocalized((char *)"Save");
03963 
03964       n = 0;
03965       XtSetArg(args[n], XmNokLabelString, str);         n++;
03966       XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE);                n++;
03967 
03968       This->saveSceneGraphDialog = XmCreateFileSelectionDialog(parent,(char *)"Save Scene Graph", args, n);
03969 
03970       XtAddCallback(This->saveSceneGraphDialog, XmNokCallback, saveSceneGraphCB, This);
03971       XtAddCallback(This->saveSceneGraphDialog, XmNcancelCallback, cancelFileSelDialogCB, This);
03972 
03973       // Adding scrolling functionality to the widget
03974       scrollWidget = XmFileSelectionBoxGetChild(This->saveSceneGraphDialog, XmDIALOG_DIR_LIST);
03975       if (scrollWidget)
03976          xmAddMouseEventHandler(scrollWidget);
03977       scrollWidget = XmFileSelectionBoxGetChild(This->saveSceneGraphDialog, XmDIALOG_LIST);
03978       if (scrollWidget)
03979          xmAddMouseEventHandler(scrollWidget);
03980 
03981       XtUnmanageChild(XmSelectionBoxGetChild(This->saveSceneGraphDialog, XmDIALOG_HELP_BUTTON));
03982       XmStringFree(str);
03983    }
03984 
03985    //TODO: Auto name?
03986 
03987    XtManageChild(This->saveSceneGraphDialog);
03988 
03989 }
03990 
03991 
03992 
03993 void G4OpenInventorXtExaminerViewer::saveSceneGraphCB(Widget w, 
03994                                                       XtPointer client_data,
03995                                                       XtPointer call_data)
03996 {
03997    char *file;
03998    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
03999    XmFileSelectionBoxCallbackStruct *cbs =
04000       (XmFileSelectionBoxCallbackStruct *) call_data;
04001 
04002    if (cbs) {
04003 
04004       file = (char *)XmStringUnparse(cbs->value, XmFONTLIST_DEFAULT_TAG,
04005                                      XmCHARSET_TEXT, XmCHARSET_TEXT,
04006                                      NULL, 0, XmOUTPUT_ALL);
04007 
04008       std::ifstream ifile(file);
04009       if (ifile) {
04010          //File already exists
04011 
04012          Arg args[4];
04013          Widget parent = This->getParentWidget();       //gets the dialogshell of the ExaminerViewer widget
04014          Widget confirmOverwriteDialog;
04015          XmString msg;
04016 
04017          confirmOverwriteDialog = XmCreateQuestionDialog (parent, (char *)"Confirm overwrite", args, 0);
04018          msg = XmStringCreateLocalized ((char *)"File exists. Overwrite?");
04019          XtVaSetValues (confirmOverwriteDialog, XmNmessageString, msg, NULL);
04020 
04021          // If users presses OK, we want to return to this function and
04022          // save the file.  For that to work, pass it the current widget
04023          // to be able to grab the filename.
04024          XtVaSetValues (confirmOverwriteDialog, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, NULL);
04025          XtAddCallback (confirmOverwriteDialog, XmNokCallback, saveSceneGraphOverWriteCB, client_data);
04026          XtAddCallback (confirmOverwriteDialog, XmNcancelCallback, saveSceneGraphOverWriteCB, client_data);
04027 
04028          XmStringFree (msg);
04029 
04030          //The confirmOverwriteDialog will need this
04031          This->saveScenegraphFileName = file;
04032          This->saveScenegraphWidget = w;
04033 
04034          XtUnmanageChild(XtNameToWidget(confirmOverwriteDialog, "Help"));
04035          XtManageChild(confirmOverwriteDialog);
04036 
04037          return;
04038       }
04039       else{
04040 
04041          SoWriteAction writeAction;
04042          SoSeparator *root = (SoSeparator *) (This->getSceneGraph());
04043 
04044          SoOutput * out = writeAction.getOutput();
04045 
04046          if(out->openFile(file)){
04047             out->setBinary(FALSE);
04048             writeAction.apply(root);
04049             out->closeFile();
04050 
04051             XtUnmanageChild(w);
04052          }
04053          else{
04054             String dialogName = (char *) "Error opening file";
04055             std::string msg = "There was a problem trying to open the file '";
04056             msg += This->saveScenegraphFileName;
04057             msg += "'";
04058 
04059             This->warningMsgDialog(msg, dialogName, NULL);
04060          }
04061 
04062       }
04063    }
04064 
04065    return;
04066 }
04067 
04068 
04069 
04070 void G4OpenInventorXtExaminerViewer::saveSceneGraphOverWriteCB(Widget w, 
04071                                                   XtPointer client_data,
04072                                                   XtPointer call_data)
04073 {
04074    XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;
04075    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
04076 
04077    switch (cbs->reason) {
04078    case XmCR_OK:
04079       {
04080          // Overwrite confirmed, save file and dismiss both
04081          // dialogs (file dialog and overwrite confirmation dialog)
04082          SoWriteAction writeAction;
04083          SoSeparator *root = (SoSeparator *) (This->getSceneGraph());
04084 
04085          SoOutput * out = writeAction.getOutput();
04086          if(out->openFile(This->saveScenegraphFileName.c_str())){
04087             out->setBinary(FALSE);
04088             writeAction.apply(root);
04089             out->closeFile();
04090 
04091             XtUnmanageChild(w);
04092             XtUnmanageChild(This->saveScenegraphWidget);
04093             This->saveScenegraphFileName.clear();
04094             This->saveScenegraphWidget = NULL;
04095          }
04096          else{
04097             String dialogName = (char *) "Error opening file";
04098             std::string msg = "There was a problem trying to open the file '";
04099             msg += This->saveScenegraphFileName;
04100             msg += "'";
04101 
04102             This->warningMsgDialog(msg, dialogName, NULL);
04103             This->saveScenegraphFileName.clear();
04104             This->saveScenegraphWidget = NULL;
04105          }
04106          break;
04107       }
04108    case XmCR_CANCEL:
04109       {
04110          // Overwrite refused, dismiss overwrite confirmation
04111          // dialog and return to file dialog
04112 
04113          // Give focus to the text field instead of the OK button
04114          XmProcessTraversal(XtNameToWidget(This->saveScenegraphWidget, "Text"), XmTRAVERSE_CURRENT);
04115 
04116          XtUnmanageChild(w);
04117          This->saveScenegraphFileName.clear();
04118          This->saveScenegraphWidget = NULL;
04119          break;
04120       }
04121    default:
04122       return;
04123    }
04124 }
04125 
04126 
04127 // Receives the name of the bookmark clicked and searches for it in viewPtList.
04128 
04129 void G4OpenInventorXtExaminerViewer::loadBookmarkCB(Widget, 
04130                                                     XtPointer client_data,
04131                                                     XtPointer call_data)
04132 {
04133    char *vpName;
04134    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
04135    XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data;
04136 
04137    vpName = (char *) XmStringUnparse(cbs->item, XmFONTLIST_DEFAULT_TAG,
04138                                      XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL);
04139 
04140    for (int i = 0; i < (int) This->viewPtList.size(); i++) {
04141       if (!strcmp(This->viewPtList[i].viewPtName, vpName)) {
04142          This->viewPtIdx = i;
04143          break;
04144       }
04145    }
04146    XmTextSetString(This->viewPtSelection, vpName);
04147 
04148    This->writeViewPtIdx();
04149    This->setViewPt();
04150    XtFree(vpName);
04151 }
04152 
04153 
04154 
04155 void G4OpenInventorXtExaminerViewer::deleteBookmarkCB(Widget, 
04156                                                       XtPointer client_data,
04157                                                       XtPointer)
04158 {
04159    char *vpName;
04160    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
04161 
04162    vpName = XmTextGetString(This->viewPtSelection);
04163 
04164    XmString vpNameStr = XmStringCreateLocalized(vpName);
04165 
04166    if (XmListItemExists(This->myViewPtList, vpNameStr)) {
04167       XmListDeleteItem(This->myViewPtList, vpNameStr);
04168       This->deleteViewPt(vpName);
04169    }
04170 
04171    XmStringFree(vpNameStr);
04172    XmTextSetString(This->viewPtSelection, NULL);
04173    XtFree(vpName);
04174 }
04175 
04176 
04177 void G4OpenInventorXtExaminerViewer::renameBookmarkCB(Widget, 
04178                                                       XtPointer client_data,
04179                                                       XtPointer)
04180 {
04181    std::string vpNameStr;
04182    char *vpName;
04183    int *pos_list, pos_cnt;
04184    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
04185 
04186    vpName = XmTextGetString(This->viewPtSelection);
04187 
04188    if (!strlen(vpName) || !strcmp(This->curViewPtName, vpName)) {
04189       XtFree(vpName);
04190       return;
04191    }
04192 
04193    vpNameStr = vpName;
04194    XtFree(vpName);
04195    int beg = vpNameStr.find_first_not_of(' '); // Remove leading/trailing spaces
04196    int end = vpNameStr.find_last_not_of(' ');
04197    vpNameStr = vpNameStr.substr(beg, end - beg + 1);
04198    vpName = new char[vpNameStr.size() + 1];
04199    strcpy(vpName, vpNameStr.c_str());
04200 
04201    int size = This->viewPtList.size();
04202    for (int i = 0; i < size; i++) {
04203       if (!strcmp(vpName, This->viewPtList[i].viewPtName)) {
04204 
04205          String dialogName = (char *) "Existing Viewpoint";
04206          std::string msg = "'";
04207          msg += vpName;
04208          msg += "' already exists. Choose a different name";
04209 
04210          This->warningMsgDialog(msg, dialogName, NULL);
04211          return;
04212       }
04213    }
04214 
04215    XmString vpNameXmStr = XmStringCreateLocalized(vpName);
04216 
04217    if (XmListGetSelectedPos(This->myViewPtList, &pos_list, &pos_cnt)) {
04218       XmListReplaceItemsPos(This->myViewPtList, &vpNameXmStr, 1, pos_list[0]);
04219       This->renameViewPt(vpName);
04220       XtFree((char *) pos_list);
04221    }
04222 
04223    if (This->currentState == VIEWPOINT)
04224       This->scheduleRedraw();
04225 
04226    XmStringFree(vpNameXmStr);
04227 }
04228 
04229 
04230 void G4OpenInventorXtExaminerViewer::sortBookmarksCB(Widget, 
04231                                                      XtPointer client_data,
04232                                                      XtPointer)
04233 {
04234    int size;
04235    char *vpName;
04236    XmString *strList, *newStrList;
04237    std::vector<std::string> charList;
04238    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
04239 
04240    if (This->viewPtList.size() < 2)
04241       return;
04242 
04243    // Get current entries from the list
04244    XtVaGetValues(This->myViewPtList, XmNitemCount, &size, XmNitems, &strList,
04245                  NULL);
04246 
04247    for (int i = 0; i < size; i++) {
04248       vpName = (char *) XmStringUnparse(strList[i], XmFONTLIST_DEFAULT_TAG,
04249                                         XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL);
04250       charList.push_back(vpName);
04251       XtFree(vpName);
04252    }
04253 
04254    std::sort(charList.begin(), charList.end());
04255 
04256    newStrList = (XmString *) XtMalloc(size * sizeof(XmString));
04257    for (int i = 0; i < size; i++) {
04258       // viewPtIdx has to be changed to account for a different order in viewPtList
04259       if (!strcmp(charList[i].c_str(), This->curViewPtName))
04260          This->viewPtIdx = i;
04261       char *vpName2 = new char[charList[i].size() + 1];
04262       strcpy(vpName2, charList[i].c_str());
04263       newStrList[i] = XmStringCreateLocalized(vpName2);
04264       delete vpName2;
04265    }
04266 
04267    XmListDeleteAllItems(This->myViewPtList);
04268    XmListAddItemsUnselected(This->myViewPtList, newStrList, size, 1);
04269 
04270    This->sortViewPts(charList);
04271 
04272    if (newStrList != NULL) {
04273       for (int i = 0; i < size; i++)
04274          XmStringFree(newStrList[i]);
04275       XtFree((char *) newStrList);
04276    }
04277 }
04278 
04279 
04280 void G4OpenInventorXtExaminerViewer::evenOutRefParticlePts()
04281 {
04282    if(this->refParticleTrajectory.empty())
04283       return;
04284 
04285    SbVec3f p1, p2, p3, dirNow, dirNxt, dir, p2_tmp, p_start, p_corner, p_nxt;
04286    float avgDistBtwPts = 0;
04287    float totalDistBtwPts = 0;
04288    std::vector<SbVec3f> newRefParticleTrajectory;
04289    SbVec3f refPoint;
04290    int size = refParticleTrajectory.size() - 1;
04291    int numOfPts = 0;
04292    for (int i = 0; i < size; i++) {
04293       p1 = refParticleTrajectory[i];
04294       p2 = refParticleTrajectory[i + 1];
04295       if (p1 == p2)
04296          continue;
04297       numOfPts++;
04298       totalDistBtwPts += (p2 - p1).length();
04299    }
04300 
04301    avgDistBtwPts = totalDistBtwPts / numOfPts;
04302    float minDistAllowed = 0.75 * avgDistBtwPts;
04303    //   float maxDistAllowed = 1.25 * avgDistBtwPts; // Pts tend to be close not far
04304 
04305    float x, y, z;
04306    int i = 0, j = 0;
04307    while (i < size) {
04308       p1 = refParticleTrajectory[i];
04309       p2 = refParticleTrajectory[i + 1];
04310 
04311       refPoint = p1;
04312       p1.getValue(x, y, z);
04313 
04314       newRefParticleTrajectory.push_back(refPoint);
04315 
04316       j = i;
04317       while ((p2 - p1).length() < minDistAllowed && j < (size - 1)) {
04318          j++;
04319 
04320          p1 = refParticleTrajectory[j];
04321          p2 = refParticleTrajectory[j + 1];
04322       }
04323       if (j != i)
04324          i = j + 1;
04325       else
04326          i++;
04327    }
04328 
04329    refParticleTrajectory.clear();
04330    refParticleTrajectory = newRefParticleTrajectory;
04331 }
04332 
04333 
04334 // Called when the viewer is closed; closes all open widgets.
04335 
04336 void G4OpenInventorXtExaminerViewer::closeMainWindowCB(Widget, 
04337                                                        XtPointer client_data,
04338                                                        XtPointer)
04339 {
04340    G4OpenInventorXtExaminerViewer * This =
04341       (G4OpenInventorXtExaminerViewer *) client_data;
04342 
04343    if (This->openFileDialog)
04344       XtUnmanageChild(This->openFileDialog);
04345 
04346    if (This->newFileDialog)
04347       XtUnmanageChild(This->newFileDialog);
04348 
04349    if (This->listsDialog)
04350       closeListsDialogCB(NULL, This, NULL);
04351 }
04352 
04353 
04354 void G4OpenInventorXtExaminerViewer::saveCurCamera()
04355 {
04356    SoCamera *cam = getCamera();
04357    camB4Animation.viewportMapping = cam->viewportMapping.getValue();
04358    camB4Animation.position = cam->position.getValue();
04359    camB4Animation.orientation = cam->orientation.getValue();
04360    camB4Animation.aspectRatio = cam->aspectRatio.getValue();
04361    camB4Animation.nearDistance = cam->nearDistance.getValue();
04362    camB4Animation.farDistance = cam->farDistance.getValue();
04363    camB4Animation.focalDistance = cam->focalDistance.getValue();
04364 
04365    if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
04366       camB4Animation.height =
04367          ((SoPerspectiveCamera *) cam)->heightAngle.getValue();
04368       camB4Animation.camType = PERSPECTIVE;
04369    } else if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) {
04370       camB4Animation.height =
04371          ((SoOrthographicCamera *) cam)->height.getValue();
04372       camB4Animation.camType = ORTHOGRAPHIC;
04373    }
04374 }
04375 
04376 
04377 void G4OpenInventorXtExaminerViewer::restoreCamera()
04378 {
04379    SoCamera *cam = getCamera();
04380 
04381    cam->viewportMapping = camB4Animation.viewportMapping;
04382    cam->position = camB4Animation.position;
04383    cam->orientation = camB4Animation.orientation;
04384    cam->aspectRatio = camB4Animation.aspectRatio;
04385    cam->nearDistance = camB4Animation.nearDistance;
04386    cam->farDistance = camB4Animation.farDistance;
04387    cam->focalDistance = camB4Animation.focalDistance;
04388 
04389    if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
04390       if (camB4Animation.camType == ORTHOGRAPHIC) {
04391          toggleCameraType();
04392          cam = getCamera();
04393          ((SoOrthographicCamera *) cam)->height.setValue(
04394                                                          camB4Animation.height);
04395       } else
04396          ((SoPerspectiveCamera *) cam)->heightAngle.setValue(
04397                                                              camB4Animation.height);
04398    } else if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) {
04399       if (camB4Animation.camType == PERSPECTIVE) {
04400          toggleCameraType();
04401          cam = getCamera();
04402          ((SoPerspectiveCamera *) cam)->heightAngle.setValue(
04403                                                              camB4Animation.height);
04404       } else
04405          ((SoOrthographicCamera *) cam)->height.setValue(
04406                                                          camB4Animation.height);
04407    }
04408 }
04409 
04410 
04411 void G4OpenInventorXtExaminerViewer::animateSensorRotationCB(void *data, 
04412                                                              SoSensor *sensor)
04413 {
04414    SbTime curTime = SbTime::getTimeOfDay();
04415    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) data;
04416    SoTimerSensor *s = (SoTimerSensor *) sensor;
04417 
04418    float t = float((curTime - s->getBaseTime()).getValue())
04419       / This->animateBtwPtsPeriod;
04420 
04421    if ((t > 1.0f) || (t + s->getInterval().getValue() > 1.0f))
04422       t = 1.0f;
04423    SbBool end = (t == 1.0f);
04424 
04425    if (end) {
04426       This->animateSensorRotation->unschedule();
04427       if(This->rotCnt){
04428          // rotations left
04429          This->rotateCamera();
04430       }
04431       else {
04432          // rotation over
04433          This->currentState = This->prevState;
04434          return;
04435       }
04436    }
04437 
04438 }
04439 
04440 
04441 // Called repeatedly during reference particle animation
04442 
04443 void G4OpenInventorXtExaminerViewer::animateSensorCB(void *data, 
04444                                                      SoSensor *sensor)
04445 {
04446    SbTime curTime = SbTime::getTimeOfDay();
04447    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) data;
04448    SoCamera *cam = This->getCamera();
04449    SoTimerSensor *s = (SoTimerSensor *) sensor;
04450 
04451    float t = float((curTime - s->getBaseTime()).getValue())
04452       / This->animateBtwPtsPeriod;
04453 
04454    if ((t > 1.0f) || (t + s->getInterval().getValue() > 1.0f))
04455       t = 1.0f;
04456    SbBool end = (t == 1.0f);
04457 
04458    cam->orientation = SbRotation::slerp(This->camStartOrient, This->camEndOrient, t);
04459    cam->position = This->camStartPos + (This->camEndPos - This->camStartPos) * t;
04460 
04461    if (end) {
04462       This->animateSensor->unschedule();
04463 
04464       if (This->currentState == ANIMATION) {
04465          if (This->refParticleIdx < (int) (This->refParticleTrajectory.size() - 1))
04466             This->animateRefParticle();
04467          else {
04468             This->animateBtwPtsPeriod = MIN_SPEED;
04469             This->speedStep = START_STEP;
04470          }
04471       }
04472       if (This->currentState == REVERSED_ANIMATION) {
04473          if (This->refParticleIdx >= 1)
04474             This->animateRefParticle();
04475          else {
04476             This->animateBtwPtsPeriod = MIN_SPEED;
04477             This->speedStep = START_STEP;
04478          }
04479       }
04480    }
04481 }
04482 
04483 
04484 void G4OpenInventorXtExaminerViewer::setStartingPtForAnimation()
04485 {
04486    if (SoXtExaminerViewer::isAnimating())
04487       stopAnimating();
04488 
04489    SbRotation rot;
04490    SbVec3f p1, p2, p2_tmp, camUpV, camD, camD_tmp, leftRightAxis;
04491    float x1, y1, z1, x2, y2, z2;
04492 
04493    if (currentState == ANIMATION) {
04494       p1 = refParticleTrajectory[refParticleIdx];
04495       p2 = refParticleTrajectory[++(refParticleIdx)];
04496    } else if (currentState == REVERSED_ANIMATION) {
04497       p2 = refParticleTrajectory[refParticleIdx];
04498       p1 = refParticleTrajectory[--(refParticleIdx)];
04499    } else if (currentState == PAUSED_ANIMATION) {
04500       if (refParticleIdx < (int) refParticleTrajectory.size()) {
04501          p1 = refParticleTrajectory[refParticleIdx];
04502          p2 = refParticleTrajectory[refParticleIdx + 1];
04503       } else {
04504          p1 = refParticleTrajectory[refParticleIdx - 1];
04505          p2 = refParticleTrajectory[refParticleIdx];
04506       }
04507    }
04508    p1.getValue(x1, y1, z1);
04509    p2.getValue(x2, y2, z2);
04510 
04511    camD = p2 - p1;
04512    camD.normalize();
04513 
04514    p2_tmp.setValue(x2, y1, z2);
04515    camD_tmp = p2_tmp - p1;
04516    camD_tmp.normalize();
04517 
04518    camUpV.setValue(0, 1, 0);
04519    rot.setValue(camD_tmp, camD);
04520    rot.multVec(camUpV, camUpV);
04521 
04522    leftRightAxis = camD.cross(camUpV);
04523 
04524    myCam->position = p1;
04525    myCam->pointAt(p2, camUpV);
04526 
04527    // Update camera position
04528    p1 = p1 + (up_down * camUpV) + (left_right * leftRightAxis);
04529    myCam->position = p1;
04530 }
04531 
04532 
04533 void G4OpenInventorXtExaminerViewer::gotoRefPathStart()
04534 {
04535    G4OpenInventorXtExaminerViewer::gotoRefPathStartCB(NULL, (void *)this, 
04536                                                       NULL);
04537 }
04538 
04539 
04540 void G4OpenInventorXtExaminerViewer::gotoRefPathStartCB(Widget, 
04541                                                         XtPointer client_data, 
04542                                                         XtPointer)
04543 {
04544    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
04545 
04546    if (!This->refParticleTrajectory.size()) {
04547       String dialogName = (char *) "No Reference Trajectory";
04548       std::string msg = "You need to start a run or load a reference trajectory from a file";
04549       This->warningMsgDialog(msg, dialogName, NULL);
04550       return;
04551    }
04552 
04553    if (This->currentState == ROTATING)
04554       return;
04555    if (This->currentState == ANIMATION || This->currentState == REVERSED_ANIMATION
04556        || This->currentState == PAUSED_ANIMATION) {
04557       if (This->animateSensor->isScheduled())
04558          This->animateSensor->unschedule();
04559       This->setSuperimpositionEnabled(This->superimposition, FALSE);
04560       This->maxSpeed = 0.0f;
04561       This->scheduleRedraw();
04562    } else {
04563       This->saveCurCamera();
04564       This->prevState = This->currentState;
04565       This->prevRefIdx = This->refParticleIdx;
04566    }
04567 
04568    if (This->SoXtExaminerViewer::isAnimating())
04569       This->stopAnimating();
04570 
04571    This->up_down = 0;
04572    This->left_right = 0;
04573    This->step = 1;
04574 
04575    This->refParticleIdx = 0;
04576    This->currentState = BEAMLINE;
04577    This->setSuperimpositionEnabled(This->superimposition, TRUE);
04578    This->axisSwitch->whichChild.setValue(SO_SWITCH_NONE);
04579    This->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE);
04580    This->animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE);
04581    This->scheduleRedraw();
04582 
04583    // FWJ Disabled: this is set in moveCamera()
04584    // Zoom in
04585    //   SoCamera *cam = This->getCamera();
04586    //   cam->focalDistance = 0.1f;
04587 
04588    This->prevParticleDir = SbVec3f(0,0,0);
04589 
04590    //Default zoom
04591    SbVec3f p1 = This->refParticleTrajectory[0];
04592    SbVec3f pN = This->refParticleTrajectory[This->refParticleTrajectory.size() - 1];
04593    This->distance = (pN - p1).length() / 10;
04594 
04595    This->moveCamera(This->distance, true);
04596 }
04597 
04598 
04599 void G4OpenInventorXtExaminerViewer::invertRefPathCB(Widget,
04600                                                      XtPointer client_data,
04601                                                      XtPointer)
04602 {
04603    G4OpenInventorXtExaminerViewer * This =
04604       (G4OpenInventorXtExaminerViewer *) client_data;
04605    This->invertRefPath();
04606 }
04607 
04608 
04609 void G4OpenInventorXtExaminerViewer::invertRefPath()
04610 {
04611    std::reverse(this->refParticleTrajectory.begin(),
04612                 this->refParticleTrajectory.end());
04613    this->setReferencePathZPos();
04614    this->sortElements();
04615 }
04616 
04617 
04618 void G4OpenInventorXtExaminerViewer::animateRefParticleCB(Widget, 
04619                                            XtPointer client_data,
04620                                            XtPointer)
04621 {
04622    G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
04623 
04624    if (!This->refParticleTrajectory.size()) {
04625       This->returnToAnim = true;
04626       String dialogName = (char *) "No Reference Trajectory";
04627       std::string msg = "You need to start a run or load a reference trajectory from a file";
04628       This->warningMsgDialog(msg, dialogName, NULL);
04629       return;
04630    }
04631 
04632    if (!This->refParticleTrajectory.size())
04633       return;
04634 
04636    This->setSuperimpositionEnabled(This->superimposition, TRUE);
04637    This->maxSpeed = SPEED_INDICATOR_STEP;
04638    This->axisSwitch->whichChild.setValue(SO_SWITCH_ALL);
04639    This->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_ALL);
04640    This->animSpeedSwitch->whichChild.setValue(SO_SWITCH_ALL);
04641    This->scheduleRedraw();
04643 
04644    SoCamera *cam = This->getCamera();
04645    //   SbVec3f camDirOld, camDirNew, camDirNew_tmp, camUpVec, P0, P1, P1_tmp;
04646 
04647    if (This->currentState == ANIMATION || This->currentState == REVERSED_ANIMATION
04648        || This->currentState == ROTATING)
04649       return;
04650 
04651    if (This->currentState != PAUSED_ANIMATION) {
04652 
04653       This->saveCurCamera();
04654       This->prevState = This->currentState;
04655       This->prevRefIdx = This->refParticleIdx;
04656 
04657       if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) {
04658          This->toggleCameraType();
04659          cam = This->getCamera();
04660       }
04661 
04662       This->refParticleIdx = 0; // Set the camera to the starting point of the animation
04663       This->animateBtwPtsPeriod = MIN_SPEED;
04664       This->speedStep = START_STEP;
04665       This->left_right = This->up_down = 0;
04666 
04667       cam->focalDistance = 0.1f;
04668       ((SoPerspectiveCamera *) cam)->heightAngle = 0.50f;
04669    }
04670 
04671    This->currentState = ANIMATION;
04672    This->setStartingPtForAnimation();
04673 
04674    cam->position = (This->myCam)->position.getValue();
04675    cam->orientation = (This->myCam)->orientation.getValue();
04676    This->animateRefParticle(); // Animate the camera
04677 }
04678 
04679 
04680 void G4OpenInventorXtExaminerViewer::animateRefParticle()
04681 {
04682    SoCamera *cam = getCamera();
04683 
04684    camStartPos = cam->position.getValue();
04685    camStartOrient = cam->orientation.getValue();
04686 
04687    if (currentState != BEAMLINE)
04688       setStartingPtForAnimation();
04689 
04690    camEndPos = myCam->position.getValue();
04691    camEndOrient = myCam->orientation.getValue();
04692 
04693    if (animateSensor->isScheduled())
04694       animateSensor->unschedule();
04695 
04696    animateSensor->setBaseTime(SbTime::getTimeOfDay());
04697    animateSensor->setInterval(SbTime(0.02));
04698 
04699    animateSensor->schedule();
04700 }
04701 
04702 
04703 void G4OpenInventorXtExaminerViewer::addEscapeCallback(
04704                          void (*callback)(void *), void * object)
04705 {
04706    this->escapeCallback = callback;
04707    this->examinerObject = object;
04708 }
04709 
04710 
04711 void G4OpenInventorXtExaminerViewer::sceneChangeCB(void *userData, SoSensor *)
04712 {
04713    G4OpenInventorXtExaminerViewer* This =
04714       (G4OpenInventorXtExaminerViewer*)userData;
04715    if(This->newEvents){
04716       This->findAndSetRefPath();
04717       This->newEvents = false;
04718    }
04719 }
04720 
04721 
04722 HookEventProcState::HookEventProcState(G4OpenInventorXtExaminerViewer* vwr)
04723 {
04724    this->viewer = vwr;
04725 }
04726 
04727 
04728 HookEventProcState::~HookEventProcState()
04729 {;}
04730 
04731 
04732 G4bool HookEventProcState::Notify(G4ApplicationState requiredState)
04733 {
04734    if(requiredState == G4State_EventProc){
04735       this->viewer->newEvents = true;
04736    }
04737    return true;
04738 }

Generated on Mon May 27 17:49:12 2013 for Geant4 by  doxygen 1.4.7