/***********************************************************************/ /* Open Visualization Data Explorer */ /* (C) Copyright IBM Corp. 1989,1999 */ /* ALL RIGHTS RESERVED */ /* This code licensed under the */ /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ /***********************************************************************/ #include #include "Strings.h" #include "DXApplication.h" #include "QuestionDialogManager.h" #include "SaveImageDialog.h" #include "ImageNode.h" #include "ErrorDialogManager.h" #include "WarningDialogManager.h" #include "QuestionDialogManager.h" #include "XmUtility.h" #include "ImageFormatCommand.h" #include "ToggleButtonInterface.h" #include "ButtonInterface.h" #include "ImageFileDialog.h" #include "ImageFormat.h" #ifndef DXD_DO_NOT_REQ_UNISTD_H #include #endif #include #include #include #include #include #include #include #include #include #include #include "../widgets/Number.h" boolean SaveImageDialog::ClassInitialized = FALSE; String SaveImageDialog::DefaultResources[] = { ".dialogTitle: Save Image", "*saveCurrentOption.shadowThickness: 0", "*saveContinuousOption.shadowThickness: 0", "*saveCurrentOption.labelString: Save Current", "*saveContinuousOption.labelString: Continuous Saving", "*fileSelectOption.labelString: Select File...", NULL }; SaveImageDialog::SaveImageDialog(Widget parent,ImageNode *node, CommandScope* commandScope) : ImageFormatDialog("saveImageDialog", parent, node, commandScope) { this->saveContinuousOption = NUL(ToggleButtonInterface*); this->saveCurrentOption = NUL(ToggleButtonInterface*); this->fileSelectOption = NUL(ButtonInterface*); this->sid_dirty = 0; this->fsb = NUL(ImageFileDialog*); this->file = NUL(char*); this->saveCurrentCmd = new ImageFormatCommand ("saveCmd", commandScope, TRUE, this, ImageFormatCommand::SaveCurrent); this->saveContinuousCmd = new ImageFormatCommand ("saveCmd", commandScope, FALSE, this, ImageFormatCommand::SaveContinuous); this->fileSelectCmd = new ImageFormatCommand ("selectFile", commandScope, FALSE, this, ImageFormatCommand::SelectFile); if (!SaveImageDialog::ClassInitialized) { SaveImageDialog::ClassInitialized = TRUE; this->installDefaultResources (theApplication->getRootWidget()); } } void SaveImageDialog::installDefaultResources (Widget baseWidget) { this->setDefaultResources (baseWidget, SaveImageDialog::DefaultResources); this->ImageFormatDialog::installDefaultResources (baseWidget); } SaveImageDialog::~SaveImageDialog() { if (this->fileSelectOption) delete this->fileSelectOption; if (this->saveCurrentOption) delete this->saveCurrentOption; if (this->saveContinuousOption) delete this->saveContinuousOption; if (this->fileSelectCmd) delete this->fileSelectCmd; if (this->saveCurrentCmd) delete this->saveCurrentCmd; if (this->saveContinuousCmd) delete this->saveContinuousCmd; if (this->fsb) delete this->fsb; if (this->file) delete this->file; } Widget SaveImageDialog::createControls (Widget parent) { Widget body = XtVaCreateManagedWidget ("saveImageBody", xmFormWidgetClass, parent, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNleftOffset, 2, XmNrightOffset, 2, NULL); XmString xmstr = XmStringCreateLtoR ("Output file name:", "small_bold"); XtVaCreateManagedWidget ("nameLabel", xmLabelWidgetClass, body, XmNlabelString, xmstr, XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, XmNleftOffset, 4, XmNtopOffset, 0, NULL); XmStringFree (xmstr); this->file_name = XtVaCreateManagedWidget("fileName", xmTextWidgetClass, body, XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, XmNleftOffset, 4, XmNtopOffset, 18, XmNrightAttachment, XmATTACH_FORM, XmNrightOffset, 105, NULL); XtAddCallback (this->file_name, XmNmodifyVerifyCallback, (XtCallbackProc) SaveImageDialog_ModifyCB, (XtPointer)this); this->fileSelectOption = new ButtonInterface (body, "fileSelectOption", this->fileSelectCmd); XtVaSetValues (this->fileSelectOption->getRootWidget(), XmNrightAttachment, XmATTACH_FORM, XmNrightOffset, 5, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, this->file_name, XmNtopOffset, 4, NULL); this->saveCurrentOption = new ToggleButtonInterface(body, "saveCurrentOption", this->saveCurrentCmd, FALSE); XtVaSetValues (this->saveCurrentOption->getRootWidget(), XmNleftAttachment, XmATTACH_FORM, XmNleftOffset, 10, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, this->file_name, XmNtopOffset, 10, NULL); this->saveContinuousOption = new ToggleButtonInterface(body, "saveContinuousOption", this->saveContinuousCmd, FALSE); XtVaSetValues (this->saveContinuousOption->getRootWidget(), XmNrightAttachment, XmATTACH_FORM, XmNrightOffset, 10, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, this->file_name, XmNtopOffset, 10, NULL); return body; } void SaveImageDialog::restoreCallback() { this->sid_dirty = 0; if (!this->node->isRecordFileConnected()) this->node->unsetRecordFile (FALSE); if (!this->node->isRecordEnableConnected()) this->node->unsetRecordEnable(FALSE); this->saveCurrentOption->setState(FALSE, TRUE); this->saveContinuousOption->setState(FALSE, TRUE); this->ImageFormatDialog::restoreCallback(); } boolean SaveImageDialog::okCallback(Dialog *dialog) { boolean should_send = FALSE; this->ImageFormatDialog::okCallback(dialog); const char *fname = this->getOutputFile(); // // Check for file existence and query the user for overwriting if necessary. // If we're on unix, then don't check for the file unless it starts with '/ // because the exec is writing the file and it's cwd will probably not be // the same as ours. // if ((!fname) || (!fname[0]) || (IsBlankString(fname))) { WarningMessage ("A file name is required."); return FALSE; } int response = QuestionDialogManager::OK; char abspath = '/'; char *full_filename = NUL(char*); #if !defined(DXD_WIN) if (fname[0] == '"') abspath = fname[1]; else abspath = fname[0]; #endif if ((abspath == '/') && (this->saveCurrentOption->getState())) { const char *ext = this->choice->fileExtension(); full_filename = new char[strlen(fname) + strlen(ext) + 1]; if (fname[0] == '"') strcpy (full_filename, &fname[1]); else strcpy (full_filename, fname); int quote_spot = strlen(full_filename) - 1; if (full_filename[quote_spot] == '"') full_filename[quote_spot] = '\0'; if (!strstr (full_filename, ext)) strcat (full_filename, ext); # ifdef DXD_WIN # define STATFILE(a,b) _stat(a,b) # define STATDECL _stat # else # define STATFILE(a,b) stat(a,b) # define STATDECL stat # endif struct STATDECL buffer; if (STATFILE(full_filename, &buffer) == 0) { Widget parent = XtParent(this->getRootWidget()); char *title = "Save Confirmation"; if (this->choice->supportsAppend()) { response = theQuestionDialogManager->userQuery( parent, "Append to existing file?", title, "Append", "Overwrite", "Cancel", 3 ); } else { response = theQuestionDialogManager->userQuery( parent, "Overwrite existing file?", title, "Overwrite", "Cancel", NULL, 2 ); } } } # define SAVE_CAN_PROCEED 1 # define CANCEL_SAVE 2 # define ERASE_THEN_PROCEED 3 int action = 0; switch (response) { case QuestionDialogManager::OK: // mod-writeimage will erase the file if it doesn't support appending. // mod-writeimage will append to the file if it does support appending. action = SAVE_CAN_PROCEED; break; case QuestionDialogManager::Cancel: if (this->choice->supportsAppend()) action = ERASE_THEN_PROCEED; else action = CANCEL_SAVE; break; case QuestionDialogManager::Help: if (this->choice->supportsAppend()) action = CANCEL_SAVE; else ASSERT(0); break; } ASSERT(action); switch (action) { case CANCEL_SAVE: return FALSE; break; case ERASE_THEN_PROCEED: ASSERT ((full_filename) && (full_filename[0])); this->choice->eraseOutputFile(full_filename); case SAVE_CAN_PROCEED: break; } if (full_filename) delete full_filename; if (!this->node->isRecordFileConnected()) { if (this->sid_dirty & SaveImageDialog::DirtyFilename) { this->node->setRecordFile (fname, FALSE); should_send = TRUE; } } this->sid_dirty&= ~SaveImageDialog::DirtyFilename; if (!this->node->isRecordEnableConnected()) { if (this->sid_dirty & SaveImageDialog::DirtyContinuous) { if (this->saveContinuousOption->getState()) this->node->setRecordEnable(TRUE, FALSE); else this->node->setRecordEnable(FALSE, FALSE); should_send = TRUE; } } this->sid_dirty&= ~SaveImageDialog::DirtyContinuous; if (this->saveCurrentOption->getState()) { this->currentImage(); this->saveCurrentOption->setState (FALSE, TRUE); } this->sid_dirty&= ~SaveImageDialog::DirtyCurrent; if (should_send) this->getNode()->sendValues(TRUE); return FALSE; } // // Control greying out of options due to data-driving. Certain toggle button // values imply certain others so set them too. e.g. push rerender implies // both size toggle pushed and resolution toggle pushed. // void SaveImageDialog::setCommandActivation() { // // Record enable / continuous saving // int recenab; this->node->getRecordEnable(recenab); boolean enab = (boolean)recenab; if (this->node->isRecordEnableConnected()) { this->saveContinuousCmd->deactivate(); this->saveContinuousOption->setState (enab, TRUE); this->sid_dirty&= ~SaveImageDialog::DirtyContinuous; } else { this->saveContinuousCmd->activate(); if ((this->sid_dirty & SaveImageDialog::DirtyContinuous) == 0) this->saveContinuousOption->setState (enab, TRUE); } // // Record file // const char *value = NUL(char*); this->node->getRecordFile (value); if (this->node->isRecordFileConnected()) { this->setFilename(value); this->sid_dirty&= ~SaveImageDialog::DirtyFilename; this->fileSelectCmd->deactivate(); if (this->fsb) this->fsb->unmanage(); } else { int mask = SaveImageDialog::DirtyFilename; int dirt = (this->sid_dirty&mask); if (dirt == 0) this->setFilename(value); if (this->fsb) { if (this->fsb->isManaged()) this->fileSelectCmd->deactivate(); else this->fileSelectCmd->activate(); } else { this->fileSelectCmd->activate(); } } XtSetSensitive (this->file_name, this->fileSelectCmd->isActive()); //this->setTextSensitive (this->file_name, this->fileSelectCmd->isActive()); this->ImageFormatDialog::setCommandActivation(); } void SaveImageDialog::setFilename(const char* filename, boolean skip_callbacks) { if (this->file) delete this->file; this->file = DuplicateString(filename); if (!this->file_name) return ; if (skip_callbacks) { XtRemoveCallback (this->file_name, XmNmodifyVerifyCallback, (XtCallbackProc)SaveImageDialog_ModifyCB, (XtPointer)this); } if (!this->file) XmTextSetString (this->file_name, ""); else XmTextSetString (this->file_name, this->file); if (skip_callbacks) { XtAddCallback (this->file_name, XmNmodifyVerifyCallback, (XtCallbackProc)SaveImageDialog_ModifyCB, (XtPointer)this); } } const char *SaveImageDialog::getOutputFile() { if (this->file_name) { if (this->file) delete this->file; char *cp = XmTextGetString(this->file_name); this->file = DuplicateString(cp); XtFree(cp); } return this->file; } boolean SaveImageDialog::postFileSelectionDialog() { if (!this->fsb) this->fsb = new ImageFileDialog (this->getRootWidget(), this); this->fsb->post(); XSync (XtDisplay(this->getRootWidget()), False); this->setCommandActivation(); return TRUE; } boolean SaveImageDialog::dirtyCurrent() { this->setCommandActivation(); return TRUE; } extern "C" { void SaveImageDialog_ModifyCB (Widget , XtPointer clientData, XtPointer) { SaveImageDialog* sid = (SaveImageDialog*)clientData; ASSERT(sid); sid->sid_dirty|= SaveImageDialog::DirtyFilename; } } // end extern C