/** ****************************************************************** * * Module Name : SVPEdit.cpp * * Author/Date : C.B. Lirakis / 10-Jul-05 * * Description : Edit single SVPs * * Restrictions/Limitations : * * Change Descriptions : * * Classification : Unclassified * * References : * * * RCS header info. * ---------------- * $RCSfile: SVPDialog.cpp,v $ * $Author: clirakis $ * $Date: 15 Jul 2005 09:28:52 $ * $Locker: clirakis $ * $Name: $ * $Revision: 1.11 $ * * $Log: /usr/local/iss60/library/iss60/RTDLib/SVPEdit.cpv $ Rev 1.11 15 Jul 2005 09:28:52 clirakis Added in toolbar and broke up construction of the various pieces into individual functions for ease of reading. Rev 1.10 14 Jul 2005 13:52:20 clirakis Getting ready to install Toolbar for zoom etc. Rev 1.8 13 Jul 2005 15:58:28 clirakis SAVE button now works. Rev 1.7 13 Jul 2005 15:23:24 clirakis There was a problem of displaying the profile 'list' due to a signal crossover between SVPEdit and SVPDialog. So the SVPDialog canvas got painted over the SVPEdit canvas. Checking the edit status prevents this. Rev 1.6 13 Jul 2005 14:27:16 clirakis Fixed some of the problems associated with the changing of colors in the edit dialog. Enabled reset button. Cancel works. Also apply works now. Rev 1.5 13 Jul 2005 07:13:02 clirakis Modified to display current with black line and switch back to original color when new SVP is selected as current. Rev 1.4 12 Jul 2005 18:40:18 clirakis Enabled the edit functions, also display point values in status bar when close or moving. Rev 1.3 12 Jul 2005 15:55:50 clirakis Made SVPGraph class with all the proper mechanisms for signaling points selected and line selected. Rev 1.1 11 Jul 2005 14:31:28 clirakis Checking in small changes before making a major change. Rev 1.0 10 Jul 2005 09:58:44 clirakis Initial revision. * * ******************************************************************* */ #ifndef lint /// RCS Information static char rcsid[]="$Header: /usr/local/iss60/library/iss60/RTDLib/SVPEdit.cpv 1.11 15 Jul 2005 09:28:52 clirakis $"; #endif // System includes. #include using namespace std; #include #include #include #include /// Root Includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // TGPrintDialog #include /// Local Includes. #include "SVPEdit.hh" #include "TEditor.hh" #include "RTDErrors.hh" #include "gsf.h" #include "macros.h" #include "read_svp.h" #include "dsp_sty.h" #include "mb_units.h" #include "SaveSonde.h" /* * Enumerations for menu and other buttons. */ enum SVPCommandIdentifiers { M_FILE_SAVE = 100, M_FILE_SAVEAS, M_FILE_EDIT, M_FILE_PRINT, M_ZOOM_SELECTED, M_ZOOM_MINUS, M_ZOOM_POINTER, M_HELP_ABOUT, }; static const char *HelpText1 = "This dialog allows the user to visualize the Sound Velocity Profile (SVP)\n" "saved to disk from the Sonde system.\n"; static const char *HelpText2 = "Most functionality is under the \"File\" menu option.\n" "Selecting the \"Load\" option creates a file selection dialog that\n" "allows the user to select a SVP data file.Upon successful file load,\n" "the data are graphically presented.\n\n" "The user may zoom in on the display by moving the mouse pointer over either\n" "the depth or speed axis (Y or X), pushing the left mouse button and \n" "making a drag selection. Placing the cursor over a data\n" "point and pressing the left selection button allows the user to graphically\n" "edit the data.\n\n "; static const char *HelpText3 = "The \"SAVE\" option on the menu will then replace the \n" "existing file with the newly edited points.\n\n" "The \"Save As \" option allows the user to save the data in an alternate \n" "file name with an alternate directory path, or to save the display as\n" "a GIF or postscript image.\n\n" "The \"Edit\" selection allows the user to use a text editor to view the \n" "data.\n\n The \"Print\" option allows the user to send the current display\n" "to the default printer.\n"; static const char *SVSaveTypes[] = { "SVP files", "sv*", "PostScript", "*.ps", "Encapsulated PostScript", "*.eps", "PDF", "*.pdf", "SVG", "*.svg", "Gif files", "*.gif", 0, 0 }; const char *xpm_names[] = { "save.xpm", "", "printer.xpm", "", "zoom_selected.xpm", "zoom_minus.xpm", "pointer.xpm", 0 }; /* * ToolBarData fields. * pixmap TipText stay_down ID TGButton */ ToolBarData_t tb_data[] = { { "", "Save SVP file", kFALSE, M_FILE_SAVE, NULL }, { "", 0, 0, -1, NULL }, { "", "Print" , 0, -1, NULL }, { "", 0, 0, -1, NULL }, { "", "Zoom Selected", kTRUE, M_ZOOM_SELECTED, NULL }, { "", "UnZoom", 0, M_ZOOM_MINUS, NULL }, { "", "Pointer", kTRUE, M_ZOOM_POINTER, NULL }, { "", NULL, 0, 0, NULL } }; /** ****************************************************************** * * Function Name : SVPEdit constructor * * Description : Using root T_Graphics primatives, build * a dialog for the user to select, display and * edit a sound velocity profile. * * Inputs : Standard root dialog arguments. * * Returns : fully constructed dialog * * Error Conditions : * * Unit Tested on: 30-Jul-04 * * Unit Tested by: CBL * * ******************************************************************* */ SVPEdit::SVPEdit(const TGWindow *p, UInt_t w, UInt_t h, TSVP *tsvp) : TGTransientFrame( 0, p, w, h) { SelectedSVP = tsvp; // Used to store GUI elements that need to be deleted in the destructor. fCleanup = new TList(); fCleanup->SetOwner(); // Layout menu here. CreateMenuBar(); /* * Base Frame is complete with menubar at the top. * Put a Toolbar up now. */ CreateToolBar(); CreateButtons(); CreateStatusBar(); /* * Add the frame where we will do the drawing etc. */ TGLayoutHints *fL3 = new TGLayoutHints(kLHintsBottom | kLHintsExpandX | kLHintsExpandY, 2, 2, 0, 0); fGraphicsFrame = new SVPDrawingArea( this, 60, 20); this->AddFrame( fGraphicsFrame, fL3); fCleanup->Add(fGraphicsFrame); fGraphicsFrame->Resize(); /* * Done making the graphics frame and canvas. */ this->MapSubwindows(); this->Resize(); #if TODO // position relative to the parent's window Window_t wdum; int ax, ay; gVirtualX->TranslateCoordinates ( p->GetId(), this->GetParent()->GetId(), (Int_t)(((TGFrame *) main)->GetWidth() - this->GetWidth())>> 1, (Int_t)(((TGFrame *) main)->GetHeight() - this->GetHeight())>> 1, ax, ay, wdum); this->Move(ax, ay); #endif this->SetWindowName("SVP Edit"); this->MapWindow(); char msg[1024]; /* * Set this loaded svp as the current one. */ memset(msg, 0, sizeof(msg)); SelectedSVP = tsvp; SelectedSVP->SetEditable(); // Just sets a flag. sprintf(msg, "SVP to Edit: %s", SelectedSVP->GetFileName()->Data()); fStatusBar->SetText( msg, 0); /* * Have to be very careful here * Otherwise we can get hosed. * Need to set which is the selected and what default color * we will use. */ SelectedSVP->SetEdit(kTRUE); SelectedSVP->Draw("ALP", kGreen); /* * When we do the draw above, the editable is set to * false, we need to set it to true again. */ fGraphicsFrame->SetEditable(kTRUE); fGraphicsFrame->Update(); /* * Connect SVPEdit's Distance to Primitive * function with that of the signal from SVPGraph. * this way we can display the points * as we operate on them. */ SelectedSVP->GetTG()->Connect("DistancetoPrimitive(Int_t, Int_t)", "SVPEdit", this, "DistancetoPrimitive(Int_t, Int_t)"); } /** ****************************************************************** * * Function Name : SVPEdit Destructor * * Description : delete anything that is dynamically allocated. * * Inputs : none * * Returns : none * * Error Conditions : none * * Unit Tested on: 30-Jul-04 * * Unit Tested by: CBL * * ******************************************************************* */ SVPEdit::~SVPEdit() { SelectedSVP->GetTG()->Disconnect(); fCleanup->Clear(); delete fCleanup; this->DontCallClose(); } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: 13-Jul-05 * * Unit Tested by: CBL * * ******************************************************************* */ void SVPEdit::CreateMenuBar() { // Create menubar and popup menus. The hint objects are used to place // and group the different menu widgets with respect to eachother. fMenuBarLayout = new TGLayoutHints(kLHintsTop|kLHintsLeft|kLHintsExpandX, 0, 0, 1, 1); fCleanup->Add(fMenuBarLayout); fMenuBarItemLayout = new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0); fCleanup->Add(fMenuBarItemLayout); fMenuBarHelpLayout = new TGLayoutHints(kLHintsTop | kLHintsRight); fCleanup->Add(fMenuBarHelpLayout); // First menu, named file, and only has exit associated with it. // Standard File Menu fMenuFile = new TGPopupMenu(gClient->GetRoot()); fCleanup->Add(fMenuFile); fMenuFile->AddEntry("S&ave" , M_FILE_SAVE); fMenuFile->AddEntry("SaveA&s", M_FILE_SAVEAS); fMenuFile->AddEntry("E&dit" , M_FILE_EDIT); fMenuFile->AddEntry("P&rint" , M_FILE_PRINT); // Help menu fMenuHelp = new TGPopupMenu(gClient->GetRoot()); fCleanup->Add(fMenuHelp); fMenuHelp->AddSeparator(); fMenuHelp->AddEntry("&About" , M_HELP_ABOUT); fMenuBar = new TGMenuBar(this, 1, 1, kHorizontalFrame); fCleanup->Add(fMenuBar); fMenuBar->AddPopup("&File", fMenuFile, fMenuBarItemLayout); fMenuBar->AddPopup("&Help", fMenuHelp, fMenuBarHelpLayout); // Connect the callbacks for the menu items. fMenuFile->Connect("Activated(Int_t)", "SVPEdit", this, "HandleMenu(Int_t)"); fMenuHelp->Connect("Activated(Int_t)", "SVPEdit", this, "HandleMenu(Int_t)"); this->AddFrame(fMenuBar, fMenuBarLayout); } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: 13-Jul-05 * * Unit Tested by: CBL * * ******************************************************************* */ void SVPEdit::CreateButtons() { /* * Make a new frame which is horizontal for the buttons. */ fFrame1 = new TGHorizontalFrame(this, 60, 20, kFixedWidth); fCleanup->Add(fFrame1); fUnZoom = new TGTextButton(fFrame1, "&UnZoom", 4); fUnZoom->Connect("Clicked()", "SVPEdit", this, "UnZoom()"); fReset = new TGTextButton(fFrame1, "&Reset" , 5); fReset->Connect("Clicked()", "SVPEdit", this, "ResetPoints()"); fOkButton = new TGTextButton(fFrame1, "&Save", 2); fOkButton->Connect("Clicked()", "SVPEdit", this, "DoSave()"); fCloseButton = new TGTextButton(fFrame1, "&Cancel", 3); fCloseButton->Connect("Clicked()", "SVPEdit", this, "DoClose()"); // fL1 is for the buttons. fL1 = new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 2, 2, 2, 2); fCleanup->Add(fL1); /* * Layout for button frame */ fL2 = new TGLayoutHints(kLHintsBottom | kLHintsRight, 2, 2, 5, 5); fCleanup->Add(fL2); // Add the apply button. fFrame1->AddFrame(fUnZoom , fL1); fFrame1->AddFrame(fReset , fL1); fFrame1->AddFrame(fOkButton , fL1); fFrame1->AddFrame(fCloseButton , fL1); // Finally, resize and realize the frame. fFrame1->Resize(250, fOkButton->GetDefaultHeight()); this->AddFrame(fFrame1, fL2); } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: 13-Jul-05 * * Unit Tested by: CBL * * ******************************************************************* */ void SVPEdit::CreateStatusBar() { TGLayoutHints *statusLayout = new TGLayoutHints(kLHintsBottom| kLHintsExpandX, 0, 0, 5, 0); /* * Finally add a status bar at the bottom. * parts is the breakup of the 3 subdivisions of the * status bar. */ Int_t parts[] = {60, 35, 5}; fStatusBar = new TGStatusBar( this, 50, 10, kHorizontalFrame); fCleanup->Add(fStatusBar); fStatusBar->SetParts(parts, 3); this->AddFrame( fStatusBar, statusLayout); fStatusBar->SetText("Waiting to load an SVP.",0); } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: 13-Jul-05 * * Unit Tested by: CBL * * ******************************************************************* */ void SVPEdit::CreateToolBar() { TGButton *tb; TString Path; if(gSystem->Getenv("ROOTSYS") != NULL) { Path = gSystem->Getenv("ROOTSYS"); } else { Path = "./"; } Path+="/icons/"; int spacing = 8; fToolBar = new TGToolBar(this, 60, 20, kHorizontalFrame | kRaisedFrame); fCleanup->Add(fToolBar); for (int i = 0; xpm_names[i]; i++) { TString iconname(Path); iconname += xpm_names[i]; tb_data[i].fPixmap = iconname.Data(); if (strlen(xpm_names[i]) == 0) { spacing = 8; continue; } fToolBar->AddButton(this, &tb_data[i], spacing); spacing = 0; } tb = fToolBar->GetButton(M_ZOOM_POINTER); tb->SetState(kButtonDown); AddFrame(fToolBar, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 0, 0, 0, 0)); fToolBar->Connect("Pressed(Int_t)", "SVPEdit", this, "HandleToolBar(Int_t)"); } /** ****************************************************************** * * Function Name : CloseWindow * * Description : Pretty simple, delete this. * * Inputs : none * * Returns : none * * Error Conditions : none * * Unit Tested on: 30-Jul-04 * * Unit Tested by: CBL * * ******************************************************************* */ void SVPEdit::CloseWindow() { // Called when window is closed via the window manager. delete this; } /** ****************************************************************** * * Function Name : DoSave * * Description : The Save button is cycled through here * Check to see if an edit has been completed * if so, then we have to save the file etc. * * Inputs : none * * Returns : none * * Error Conditions : * * Unit Tested on: * * Unit Tested by: CBL * * ******************************************************************* */ void SVPEdit::DoSave() { int save_ret; /* ToDo SaveSVP( dir, CurrentFileName, true ); */ SelectedSVP->SaveSVP(NULL, NULL, true); new TGMsgBox( gClient->GetRoot(), this, "Note!", "Saved Modified SVP", kMBIconExclamation, kMBOk , &save_ret); } /** ****************************************************************** * * Function Name : DoClose * * Description : Close this dialog by sending a close message * Since this is the way the Cancel is executed * also revert to the orignal data. We are * Editing the same copy of the data that * is used by the display. * Inputs : none * * Returns : none * * Error Conditions : none * * Unit Tested on: 13-Jul-05 * * Unit Tested by: CBL * * ******************************************************************* */ void SVPEdit::DoClose() { SelectedSVP->SVPEditComplete(kFALSE); this->SendCloseMessage(); } /** ****************************************************************** * * Function Name : HandleMenu * * Description : Handle menu items for this dialog. * * Inputs : ID for menu event. * * Returns : none * * Error Conditions : none * * Unit Tested on: 30-Jul-04 * * Unit Tested by: CBL * * ******************************************************************* */ void SVPEdit::HandleMenu(Int_t id) { TRootHelpDialog *trh; // Handle menu items. switch (id) { case M_FILE_SAVE: DoSave(); this->SendCloseMessage(); break; case M_FILE_SAVEAS: DoSaveAs(); break; case M_FILE_EDIT: // View Only at this time. ViewPoints(); break; case M_FILE_PRINT: #if TODO /* * Put this is the preference */ new TGPrintDialog ( gClient->GetRoot(), this, 400,300, printName, PrintPrg, &rc); if (rc == kTRUE) { // Print! printf("All is well!\n"); } #endif // Only saves to PS file, not quite what I want. // gStyle->SetPaperSize(kUSLetter); fGraphicsFrame->PrintCanvas(); break; case M_HELP_ABOUT: trh = new TRootHelpDialog ( this,"SVPEdit Help", 600, 400); trh->SetText(HelpText1); trh->AddText(HelpText2); trh->AddText(HelpText3); trh->Popup(); break; default: printf("Menu item %d selected\n", id); break; } } /** ****************************************************************** * * Function Name : DoSaveAs * * Description : Handle the Save menu option by bringing up a file * selection dialog. * * Inputs : none * * Returns : none * * Error Conditions : * * Unit Tested on: * * Unit Tested by: CBL * * ******************************************************************* */ void SVPEdit::DoSaveAs() { int i, rc; TGFileInfo fi; char *p, FullFile[512], msg[256]; int nchar, save_ret; fi.fFileTypes = SVSaveTypes; new TGFileDialog( gClient->GetRoot(), this, kFDSave, &fi); if (fi.fFilename == NULL) { // No action to be taken! return; } // Save our last directory. printf(" Save as: %s %s\n",fi.fIniDir, fi.fFilename); // Ok then, switch on what to do based on the file type selected. if (strlen(fi.fFilename) > 0) { //Determine the prefix. p = strrchr(fi.fFilename,(int)'/'); p++; i = strncmp(p,"sv",2); if (!i) { rc = SelectedSVP->SaveSVP(fi.fIniDir+1, fi.fFilename, false); switch (rc) { case 0: // All is well, continue. break; case -1: new TGMsgBox( gClient->GetRoot(), this, "Save Error!", "NULL path provided!", kMBIconExclamation, kMBOk , &save_ret); break; case -2: new TGMsgBox( gClient->GetRoot(), this, "Save Error!", "NULL filename provided!", kMBIconExclamation, kMBOk , &save_ret); break; case -3: new TGMsgBox( gClient->GetRoot(), this, "Save Error!", "File name provided is of zero length.", kMBIconExclamation, kMBOk , &save_ret); break; case -4: // Query if the user wants to overwrite otherwise exit. new TGMsgBox( gClient->GetRoot(), this, "Save Error!", "File already exists, overwrite?", kMBIconExclamation, kMBYes|kMBNo , &save_ret); if (save_ret == 1) { SelectedSVP->SaveSVP(fi.fIniDir+1, fi.fFilename, false); } break; case -5: sprintf(msg, "Error opening SVP file: %s for output", fi.fFilename); new TGMsgBox( gClient->GetRoot(), this, "Save Error!", msg, kMBIconStop); break; } } else { memset(FullFile, 0, sizeof(FullFile)); nchar = sizeof(FullFile); strncpy( FullFile, fi.fIniDir+1, nchar); nchar -= strlen(FullFile); strncat( FullFile, "/", nchar); nchar--; strncat( FullFile, fi.fFilename, nchar); fGraphicsFrame->CanvasSaveAs(FullFile); } } } /** ****************************************************************** * * Function Name : HandleToolBar * * Description : Handle toolbar items for this dialog. * * Inputs : ID for menu event. * * Returns : none * * Error Conditions : none * * Unit Tested on: 30-Jul-04 * * Unit Tested by: CBL * * ******************************************************************* */ void SVPEdit::HandleToolBar(Int_t id) { TGButton *tb; // printf("Handle Tool Bar id = %d\n", id); switch (id) { case M_ZOOM_SELECTED: gPad->SetEditable(kFALSE); tb = fToolBar->GetButton(M_ZOOM_POINTER); tb->SetState(kButtonUp); break; case M_ZOOM_MINUS: tb = fToolBar->GetButton(M_ZOOM_SELECTED); break; case M_ZOOM_POINTER: tb = fToolBar->GetButton(M_ZOOM_SELECTED); tb->SetState(kButtonUp); gPad->SetEditable(kTRUE); break; } } /** ****************************************************************** * * Function Name : DistancetoPrimitive * * Description : You will see in the constructor that this is * connected up to the SVPGraph Distance to * Primitive signal. IF the mouse is just * moving, AND the distance is small (<10) * then we determine which point in the graph * px and py is near and update the status bar * with this text. IF the point is selected * and moving (d<0) then we use the * current mouse coordinates. * * Inputs : Distance to the primitive , q - not currently used. * * Returns : 0 always * * Error Conditions : NONE * * Unit Tested on: 13-Jul-05 * * Unit Tested by: CBL * * ******************************************************************* */ Int_t SVPEdit::DistancetoPrimitive(Int_t d, Int_t q) { Double_t *x, *y; char msg[32]; SVPGraph *svpg = SelectedSVP->GetTG(); // printf("SVPEdit Distance to Primative\n"); // if ((d<10) || (svpg->PointInMotion() == kTRUE)) if (d<10) { Int_t ipoint = svpg->GetSelectedPoint(); if (d<0) { sprintf(msg,"Point %d Speed:%6.2f Depth %6.2f", ipoint, svpg->GetWorldX(), svpg->GetWorldY()); } else { x = svpg->GetX(); y = svpg->GetY(); sprintf(msg, "Point %d Speed:%6.2f Depth: %6.1f", ipoint, x[ipoint], y[ipoint]); } //printf("Result = %s\n", msg); fStatusBar->SetText(msg,1); } return 0; } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: 13-Jul-05 * * Unit Tested by: CBL * * ******************************************************************* */ void SVPEdit::ResetPoints() { SelectedSVP->FillGraph(); SelectedSVP->Draw("ALP", kGreen); fGraphicsFrame->Update(); } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: 13-Jul-05 * * Unit Tested by: CBL * * ******************************************************************* */ void SVPEdit::ViewPoints() { TEditor *ed; Double_t *x, *y; Int_t N, i; char *msg, tmp[32]; ed = new TEditor( this, "Edit Points", 200, 600); N = SelectedSVP->GetTG()->GetN(); x = SelectedSVP->GetTG()->GetX(); y = SelectedSVP->GetTG()->GetY(); /* * Allocate space for all points. * use 32 characters per line. */ msg = (char *) calloc(32*N, sizeof(char)); sprintf(msg, "Depth SoundSpeed\n"); if (msg) { for (i=0;iLoadBuffer(msg); ed->Popup(); /* * Can connect up * ok button to signal * and reparse the buffer into arrays. */ printf("View Points\n"); } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: * * Unit Tested by: CBL * * ******************************************************************* */ void SVPEdit::UnZoom() { SelectedSVP->GetTG()->UnZoom(); } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: * * Unit Tested by: CBL * * ******************************************************************* */ TSVP::TSVP(const char *path, const char *filename) { gsfSVP *profile; int rc = 1; FILE *fd; char msg[256]; Header = NULL; LastError = RTD_OK; Path = Filename = NULL; tg = NULL; IsSonde = false; sample = been_sampled = false; MyColor = 0; IsCurrent = kFALSE; profile = (gsfSVP *) calloc (1, sizeof(gsfSVP)); if (profile == NULL) { LastError = SVP_MEMORY_ALLOCATION_FAIL; return; } GSFprofile = profile; /* * Use SVP utility library to load the SVP. */ while (rc) { memset(profile, 0, sizeof(gsfSVP)); if (!sample) { rc = Read_SVP((char *)filename, profile, &format); } else { rc = ReadSample_SVP((char *)filename, profile, &format); } if (sample) { sample = false; /* this will only occur once per entry if required */ been_sampled = true; } if (rc) { LastError = rc; return; } #if TODO /********************************************************************* The remainder of this 'While' loop was added to allow the temporary display of an SVP that contains too many data points. If this error condition occurs the operator is given a chance to downsample the number of cast values to a number under the maximum allowed. This processing is valid only for the Seabird at this point. *********************************************************************/ if (rc == SVP_TOO_MANY_DATA_POINTS) { SVP_TEMP.info[0].file_format = format; SVP_TEMP.info[0].svp.observation_time = profile.observation_time; SVP_TEMP.info[0].svp.application_time = profile.application_time; SVP_TEMP.info[0].svp.latitude = profile.latitude; SVP_TEMP.info[0].svp.longitude = profile.longitude; SVP_TEMP.info[0].svp.number_points = profile.number_points; SVP_TEMP.info[0].svp.depth = (double *) malloc (profile.number_points * sizeof(double)); if (SVP_TEMP.info[0].svp.depth == (double *) NULL) { sprintf(ErrorStr, "Error allocating memory"); new TGMsgBox( gClient->GetRoot(), this, "Load Error!", ErrorStr, kMBIconStop); return; } SVP_TEMP.info[0].svp.sound_speed = (double *) malloc (profile.number_points * sizeof(double)); if (SVP_TEMP.info[0].svp.sound_speed == (double *) NULL) { sprintf(ErrorStr, "Error allocating memory"); new TGMsgBox( gClient->GetRoot(), this, "Load Error!", ErrorStr, kMBIconStop); return; } switch (DisplayDepthStyle_dsp_sty.value->value) { case (US_SURVEY_FEET): depth_conversion = METERS_TO_US_FEET; SVP_TEMP.info[0].units = US_SURVEY_FEET; break; case (METERS): depth_conversion = 1.0; SVP_TEMP.info[0].units = METERS; break; case (US_SURVEY_FATHOMS): depth_conversion = METERS_TO_US_FATHOMS; SVP_TEMP.info[0].units = US_SURVEY_FATHOMS; break; default: depth_conversion = 1.0; SVP_TEMP.info[0].units = METERS; break; } for (i=0; iSetName(p); return; } /** ****************************************************************** * * Function Name : TSVP Destructor * * Description : Cleans up after any objects we have allocated * during the process of creation. * * Inputs : none * * Returns : none * * Error Conditions : none * * Unit Tested on: 9-Jul-05 * * Unit Tested by: CBL * * ******************************************************************* */ TSVP::~TSVP() { printf("Destroy TSVP\n"); gsfSVP *profile = (gsfSVP *)GSFprofile; if (GSFprofile != NULL) { free(profile->depth); free(profile->sound_speed); free(profile); } delete Header; delete Path; delete Filename; delete tg; } /** ****************************************************************** * * Function Name : SaveSVP * * Description : Using the path and filename provided, * save a read a space delmited SVP file. * * Inputs : Path - Path where the user has specified the file to reside. * filename - File name of the desired SVP. * * Returns : true on success, false on failure. * * Error Conditions : An error occurs on one of the following instances: * 0 - OK. * -1 - The path provided is NULL * -2 - The filename provided is NULL * -3 - The string length of the filename is zero * -4 - The file exists * -5 - Could not open file in write mode. * * Unit Tested on: 9-Jul-05 * * Unit Tested by: CBL * * ******************************************************************* */ int TSVP::SaveSVP(const char *path, const char *filename, bool MoveAndRename) { char FileSelection[512], CurrentFileName[512]; FILE *fd; int n, rc; memset(FileSelection , 0, sizeof(FileSelection)); memset(CurrentFileName, 0, sizeof(CurrentFileName)); /* * Make a full copy of the path plus filename for open. */ if (MoveAndRename) { snprintf( CurrentFileName, sizeof(CurrentFileName), "%s/%s", Path->Data(), Filename->Data()); strncpy( FileSelection, CurrentFileName, sizeof(FileSelection)); n = sizeof(FileSelection) - strlen(FileSelection); strncat(FileSelection,"~",n); rename (CurrentFileName, FileSelection); strncpy( FileSelection, CurrentFileName, sizeof(FileSelection)); } else { /* * In the event the does not select a file or something * really wacky happens, just don't do anything and * close the dialog. */ if (path == NULL) return -1; if (filename == NULL) return -2; if (strlen(filename) == 0) return -3; sprintf(FileSelection,"%s/%s", path, filename); fd = fopen(FileSelection,"r"); if (fd) { fclose(fd); // Ooops the file already exists. return -4; } } /* * Make sure we get the points from the graph * and back out any transformations we have done. */ FillGSFProfile(); rc=SaveISS_SVP(FileSelection, (gsfSVP *)GSFprofile, Header->Data()); return 0; } /** ****************************************************************** * * Function Name : Draw * * Description : Actually do the draw on the current selected surface. * If a color is specified, use that color. * If not then check to see if the line is set * as current where we increase the width to 3 * and set the color to Black. * * * Inputs : option to use for draw (passed directly to root library call.) * Color to use for drawing line. * * Returns : none * * Error Conditions : none * * Unit Tested on: 13-Jul-05 * * Unit Tested by: CBL * * ******************************************************************* */ void TSVP::Draw(Option_t* chopt, Color_t ColorToUse) { // printf("%s ",tg->GetName()); if (tg) { /* * Allow us to draw in the current pad. */ gPad->SetEditable(kTRUE); if (ColorToUse > 0) { tg->SetLineWidth(1); tg->SetLineColor(ColorToUse); } else { if (EditInProgress == kTRUE) { tg->SetLineWidth(1); tg->SetLineColor(kGreen); } else if (IsCurrent == kTRUE) { tg->SetLineColor(kBlack); tg->SetLineWidth(3); } else { tg->SetLineWidth(1); tg->SetLineColor(MyColor); } } tg->Draw(chopt); /* * And not when we are done. */ gPad->SetEditable(kFALSE); } } /** ****************************************************************** * * Function Name :FillGSFProfile() * * Description : Take the points from the tgraph and * fill the profile also, backout any display scaling/transformation * factors we put in. * * Inputs : None * * Returns : None * * Error Conditions : None * * Unit Tested on: 09-Jul-05 * * Unit Tested by: CBL * * ******************************************************************* */ int TSVP::FillGSFProfile() { Double_t *x, *y; Int_t N, i; Double_t depth_conversion; gsfSVP *profile = (gsfSVP *) GSFprofile; /* * Output is in meters, gotta undo what we did * going in. */ switch (DisplayDepthStyle_dsp_sty.value) { case (US_SURVEY_FEET): depth_conversion = METERS_TO_US_FEET; break; case (METERS): depth_conversion = 1.0; break; case (US_SURVEY_FATHOMS): depth_conversion = METERS_TO_US_FATHOMS; break; default: depth_conversion = 1.0; break; } // Get the vectors from the TGraph object and fill the profile. x = tg->GetX(); y = tg->GetY(); N = tg->GetN(); if (N == profile->number_points) { // Life is good, we don't have to resize anything for (i=0; inumber_points; i++) { profile->depth[i] = -1.0 * y[i]/ depth_conversion; profile->sound_speed[i] = x[i]; } } else { // Gotta reallocate the memory associated with the profile. profile->number_points = N; /* Make sure the caller has memory allocated for the gsf svp array's */ free(profile->depth); profile->depth = (double *) calloc((profile->number_points + 2), sizeof(double)); if (profile->depth == (double *) NULL) { return (SONDE_MEMORY_ALLOCATION_FAILED); } free(profile->sound_speed); profile->sound_speed = (double *) calloc((profile->number_points + 2), sizeof(double)); if (profile->sound_speed == (double *) NULL) { return (SONDE_MEMORY_ALLOCATION_FAILED); } } return RTD_OK; } /** ****************************************************************** * * Function Name : FillGraph() * * Description : Given that we have loaded the SVP into * the GSFprofile structure then create (or not) the tgraph object * and fill it. If the TGraph object pre-exists, get the * vectors associated with it and fill them. * * Inputs : none * * Returns : 0 on success, * * Error Conditions : Couldn't allocate memory. * * Unit Tested on: 09-Jul-05 * * Unit Tested by: CBL * * ******************************************************************* */ int TSVP::FillGraph() { Double_t *x, *y; Int_t N, i; Double_t depth_conversion; gsfSVP *profile = (gsfSVP *) GSFprofile; switch (DisplayDepthStyle_dsp_sty.value) { case (US_SURVEY_FEET): depth_conversion = METERS_TO_US_FEET; units = US_SURVEY_FEET; break; case (METERS): depth_conversion = 1.0; units = METERS; break; case (US_SURVEY_FATHOMS): depth_conversion = METERS_TO_US_FATHOMS; units = US_SURVEY_FATHOMS; break; default: depth_conversion = 1.0; units = METERS; break; } if (tg != NULL) { // Otherwise get the vectors from the TGraph object and reset them. x = tg->GetX(); y = tg->GetY(); N = tg->GetN(); if (N == profile->number_points) { // Life is good, we don't have to resize anything for (i=0; inumber_points; i++) { y[i] = -1.0 * profile->depth[i] * depth_conversion; x[i] = profile->sound_speed[i]; } return RTD_OK; } else { // Gotta recreate everything. delete tg; tg = NULL; } } if (tg == NULL) { // We have to create everything x = new Double_t[profile->number_points]; if (x == NULL) { LastError = SVP_MEMORY_ALLOCATION_FAIL; return LastError; } y = new Double_t[profile->number_points]; if (y == NULL) { LastError = SVP_MEMORY_ALLOCATION_FAIL; return LastError; } memset(x, 0, profile->number_points*sizeof(Double_t)); memset(y, 0, profile->number_points*sizeof(Double_t)); for (i=0; inumber_points; i++) { y[i] = -1.0 * profile->depth[i] * depth_conversion; x[i] = profile->sound_speed[i]; } // At this point we have both the graph points and the profile tg = new SVPGraph(profile->number_points, x, y); tg->SetEditable(kFALSE); /* * We no longer need the vectors, delete them. */ delete[] x; delete[] y; /* * Set the default style values. */ tg->SetMarkerStyle(7); tg->SetLineColor(2); TH1F *hbs = tg->GetHistogram(); if (IsSonde) { tg->SetTitle(*Header); } else { tg->SetTitle("SVP"); } /* * Make sure that for some reason that the histogram is not null. * It would be bad to try and set attributes on a null pointer. */ if (hbs) { hbs->SetXTitle("Sound Speed (M/S)"); hbs->SetYTitle("Depth (M)"); hbs->SetLabelSize(0.03,"X"); hbs->SetLabelSize(0.03,"Y"); hbs->SetTitleSize(0.04,"X"); hbs->SetTitleSize(0.04,"Y"); } } return RTD_OK; } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: * * Unit Tested by: CBL * * ******************************************************************* */ void TSVP::SetCurrent(Bool_t flag) { IsCurrent = flag; if (IsCurrent) { tg->SetLineWidth(3); tg->SetLineColor(kBlack); } else { tg->SetLineWidth(1); tg->SetLineColor(MyColor); } } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : Reset - If set to true, then move the points from the * graph into the profile (unedited copy) * If set to false, then refill the graph elements * with the (unedited) profile points. * * Returns : none * * Error Conditions : none * * Unit Tested on: 13-Jul-05 * * Unit Tested by: CBL * * ******************************************************************* */ void TSVP::SVPEditComplete(Bool_t Reset) { SetEdit(kFALSE); /** * Don't allow any more edits. */ tg->SetEditable(kFALSE); /* * Return the qualities of this line to one that is selected. */ SetCurrent(kTRUE); /* * If reset is kTRUE then the data loaded in the profile strucure * is recopied into the TGraph structure. * * If kFALSE then the profile is overwritten by the data in the * TGraph structure. */ if (Reset==kTRUE) { FillGSFProfile(); } else { FillGraph(); } } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: * * Unit Tested by: CBL * * ******************************************************************* */ SVPGraph::SVPGraph(Int_t n, const Double_t* x, const Double_t* y) : TGraph(n, x, y) { X = Y = 0.0; Ipoint = 99999; HasBeenEditedAndNotSaved = kFALSE; } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: * * Unit Tested by: CBL * * ******************************************************************* */ Int_t SVPGraph::DistancetoPrimitive(Int_t px, Int_t py) { Int_t rc = TGraph::DistancetoPrimitive( px, py); //printf("%d\n", rc); if (rc<9999) { screen.SetX(px); screen.SetY(py); X = gPad->XtoPad(px); Y = gPad->XtoPad(py); if (rc<10) { Ipoint = PointFromXY(px,py); //printf("Point = %d\n", Ipoint); } } Emit("DistancetoPrimitive(Int_t, Int_t)", rc); return rc; } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: * * Unit Tested by: CBL * * ******************************************************************* */ void SVPGraph::ExecuteEvent(Int_t event, Int_t px, Int_t py) { /* * This is only called when the mouse pointer is * very close to the graph object. */ //printf("SVPGraph Execute event\n"); switch (event) { case kButton1Down: // Put code from TGraph here and modify it. //printf("Selected %s\n", GetName()); if (gPad->IsEditable() == kTRUE) { printf("Editable\n"); IsSelected(this); } else { printf("Not Editable\n"); } break; case kMouseMotion: break; case kButton1Motion: screen.SetX(px); screen.SetY(py); X = gPad->XtoPad(px); Y = gPad->XtoPad(py); Emit("DistancetoPrimitive(Int_t, Int_t)", -1); HasBeenEditedAndNotSaved = kTRUE; break; case kButton1Up: break; } TGraph::ExecuteEvent(event, px, py); } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: * * Unit Tested by: CBL * * ******************************************************************* */ void SVPGraph::IsSelected(SVPGraph *v) { Emit("IsSelected(SVPGraph *)", (Int_t) v); } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: * * Unit Tested by: CBL * * ******************************************************************* */ Int_t SVPGraph::PointFromXY(Int_t px, Int_t py) { Int_t i, pxp, pyp, d; Int_t dmin, rc; rc = 9999; dmin = 99999999; for (i=0;iXtoAbsPixel(gPad->XtoPad(fX[i])); pyp = gPad->YtoAbsPixel(gPad->YtoPad(fY[i])); d = TMath::Abs(pxp-px) + TMath::Abs(pyp-py); if(dGetXaxis())) { axis->UnZoom(); } if ((axis = hbs->GetYaxis())) { axis->UnZoom(); } if ((axis = hbs->GetZaxis())) { axis->UnZoom(); } } } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: * * Unit Tested by: CBL * * ******************************************************************* */ SVPDrawingArea ::SVPDrawingArea (const TGWindow* p , UInt_t w, UInt_t h) : TGCompositeFrame( p, w, h, kChildFrame, GetDefaultFrameBackground()) { // We can change the pixel background in the composite frame. // but later. /* * The remaining space I want to be a frame. * Inside this frame I will embed a canvas for * drawing the profile. */ fEmbeddedCanvas = new TRootEmbeddedCanvas("ec1", this, 600, 600); fL1 = new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX | kLHintsExpandY, 5, 5, 5, 5); AddFrame( fEmbeddedCanvas, fL1); // Finally put a graph to plot on in this frame. TCanvas *c1 = fEmbeddedCanvas->GetCanvas(); c1->SetBorderMode(0); #if 0 /* * Set NoContextMenu iff * a) You don't want the user to fool with the axis * styles, un-zoom... * b) You don't want to be able to edit the points on the graph. * This is a property of TObject */ c1->SetBit(kNoContextMenu); #endif c1->SetFillColor(0); c1->SetGrid(); c1->cd(); fEmbeddedCanvas->Resize(); } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: * * Unit Tested by: CBL * * ******************************************************************* */ SVPDrawingArea ::~SVPDrawingArea() { delete fEmbeddedCanvas; delete fL1; } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: * * Unit Tested by: CBL * * ******************************************************************* */ void SVPDrawingArea ::Update() { fEmbeddedCanvas->GetCanvas()->Update(); } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: * * Unit Tested by: CBL * * ******************************************************************* */ void SVPDrawingArea ::PrintCanvas() { fEmbeddedCanvas->GetCanvas()->Print(); } /** ****************************************************************** * * Function Name : * * Description : * * Inputs : * * Returns : * * Error Conditions : * * Unit Tested on: * * Unit Tested by: CBL * * ******************************************************************* */ void SVPDrawingArea::CanvasSaveAs(char *filename) { fEmbeddedCanvas->GetCanvas()->SaveAs(filename); } Bool_t SVPDrawingArea::HandleButton(Event_t*) { printf("Button Event\n"); return kTRUE; } Bool_t SVPDrawingArea::HandleMotion(Event_t*) { printf("motion event\n"); return kTRUE; }