Revision dc23f9fcef6b528a41995f8ce10463d5330581e6 authored by Fons Rademakers on 27 October 2012, 21:18:24 UTC, committed by Fons Rademakers on 27 October 2012, 21:18:24 UTC
git-svn-id: http://root.cern.ch/svn/root/tags/v5-34-03@46856 27541ba8-7e3a-0410-8455-c3a389f83636
Dialogs.C
//
// This file contains the class InputDialog.
// An InputDialog object prompts for an input string using a simple
// dialog box. The InputDialog class is also a good example of how
// to use the ROOT GUI classes via the interpreter. Since interpreted
// classes can not call virtual functions via base class pointers, all
// GUI objects are used by composition instead of by inheritance.
//
// This file contains also some utility functions that use
// the InputDialog class to either get a string, integer or
// floating point number. There are also two functions showing
// how to use the file open and save dialogs. The utility functions are:
//
// const char *OpenFileDialog()
// const char *SaveFileDialog()
// const char *GetStringDialog(const char *prompt, const char *defval)
// Int_t GetIntegerDialog(const char *prompt, Int_t defval)
// Float_t GetFloatDialog(const char *prompt, Float_t defval)
//
// To use the InputDialog class and the utility functions you just
// have to load the Dialogs.C file as follows:
// .L Dialogs.C
//
// Now you can use them like:
// {
// const char *file = OpenFileDialog();
// Int_t run = GetIntegerDialog("Give run number:", 0);
// Int_t event = GetIntegerDialog("Give event number:", 0);
// printf("analyse run %d, event %d from file %s\n", run ,event, file);
// }
//
///////////////////////////////////////////////////////////////////////////
// //
// Input Dialog Widget //
// //
///////////////////////////////////////////////////////////////////////////
class InputDialog {
private:
TGTransientFrame *fDialog; // transient frame, main dialog window
TGTextEntry *fTE; // text entry widget containing
TList *fWidgets; // keep track of widgets to be deleted in dtor
char *fRetStr; // address to store return string
public:
InputDialog(const char *prompt, const char *defval, char *retstr);
~InputDialog();
void ProcessMessage(Long_t msg, Long_t parm1, Long_t parm2);
};
InputDialog::~InputDialog()
{
// Cleanup dialog.
fWidgets->Delete();
delete fWidgets;
delete fTE;
delete fDialog;
}
InputDialog::InputDialog(const char *prompt, const char *defval, char *retstr)
{
// Create simple input dialog.
fWidgets = new TList;
TGWindow *main = gClient->GetRoot();
fDialog = new TGTransientFrame(main, main, 10, 10);
// command to be executed by buttons and text entry widget
char cmd[128];
sprintf(cmd, "{long r__ptr=0x%lx; ((InputDialog*)r__ptr)->ProcessMessage($MSG,$PARM1,$PARM2);}", (Long_t)this);
// create prompt label and textentry widget
TGLabel *label = new TGLabel(fDialog, prompt);
fWidgets->Add(label);
TGTextBuffer *tbuf = new TGTextBuffer(256); //will be deleted by TGtextEntry
tbuf->AddText(0, defval);
fTE = new TGTextEntry(fDialog, tbuf);
fTE->Resize(260, fTE->GetDefaultHeight());
fTE->SetCommand(cmd);
TGLayoutHints *l1 = new TGLayoutHints(kLHintsTop | kLHintsLeft, 5, 5, 5, 0);
TGLayoutHints *l2 = new TGLayoutHints(kLHintsTop | kLHintsLeft, 5, 5, 5, 5);
fWidgets->Add(l1);
fWidgets->Add(l2);
fDialog->AddFrame(label, l1);
fDialog->AddFrame(fTE, l2);
// create frame and layout hints for Ok and Cancel buttons
TGHorizontalFrame *hf = new TGHorizontalFrame(fDialog, 60, 20, kFixedWidth);
TGLayoutHints *l3 = new TGLayoutHints(kLHintsCenterY | kLHintsExpandX, 5, 5, 0, 0);
// put hf as last in list to be deleted
fWidgets->Add(l3);
// create OK and Cancel buttons in their own frame (hf)
UInt_t nb = 0, width = 0, height = 0;
TGTextButton *b;
b = new TGTextButton(hf, "&Ok", cmd, 1);
fWidgets->Add(b);
b->Associate(fDialog);
hf->AddFrame(b, l3);
height = b->GetDefaultHeight();
width = TMath::Max(width, b->GetDefaultWidth()); ++nb;
b = new TGTextButton(hf, "&Cancel", cmd, 2);
fWidgets->Add(b);
b->Associate(fDialog);
hf->AddFrame(b, l3);
height = b->GetDefaultHeight();
width = TMath::Max(width, b->GetDefaultWidth()); ++nb;
// place button frame (hf) at the bottom
TGLayoutHints *l4 = new TGLayoutHints(kLHintsBottom | kLHintsCenterX, 0, 0, 5, 5);
fWidgets->Add(l4);
fWidgets->Add(hf);
fDialog->AddFrame(hf, l4);
// keep buttons centered and with the same width
hf->Resize((width + 20) * nb, height);
// set dialog title
fDialog->SetWindowName("Get Input");
// map all widgets and calculate size of dialog
fDialog->MapSubwindows();
width = fDialog->GetDefaultWidth();
height = fDialog->GetDefaultHeight();
fDialog->Resize(width, height);
// position relative to the parent window (which is the root window)
Window_t wdum;
int ax, ay;
gVirtualX->TranslateCoordinates(main->GetId(), main->GetId(),
(((TGFrame *) main)->GetWidth() - width) >> 1,
(((TGFrame *) main)->GetHeight() - height) >> 1,
ax, ay, wdum);
fDialog->Move(ax, ay);
fDialog->SetWMPosition(ax, ay);
// make the message box non-resizable
fDialog->SetWMSize(width, height);
fDialog->SetWMSizeHints(width, height, width, height, 0, 0);
fDialog->SetMWMHints(kMWMDecorAll | kMWMDecorResizeH | kMWMDecorMaximize |
kMWMDecorMinimize | kMWMDecorMenu,
kMWMFuncAll | kMWMFuncResize | kMWMFuncMaximize |
kMWMFuncMinimize,
kMWMInputModeless);
// popup dialog and wait till user replies
fDialog->MapWindow();
fRetStr = retstr;
gClient->WaitFor(fDialog);
}
void InputDialog::ProcessMessage(Long_t msg, Long_t parm1, Long_t parm2)
{
// Handle button and text enter events
switch (GET_MSG(msg)) {
case kC_COMMAND:
switch (GET_SUBMSG(msg)) {
case kCM_BUTTON:
switch (parm1) {
case 1:
// here copy the string from text buffer to return variable
strcpy(fRetStr, fTE->GetBuffer()->GetString());
delete this;
break;
case 2:
fRetStr[0] = 0;
delete this;
break;
}
default:
break;
}
break;
case kC_TEXTENTRY:
switch (GET_SUBMSG(msg)) {
case kTE_ENTER:
// here copy the string from text buffer to return variable
strcpy(fRetStr, fTE->GetBuffer()->GetString());
delete this;
break;
default:
break;
}
break;
default:
break;
}
}
//--- Utility Functions --------------------------------------------------------
const char *OpenFileDialog()
{
// Prompt for file to be opened. Depending on navigation in
// dialog the current working directory can be changed.
// The returned file name is always with respect to the
// current directory.
const char *gOpenAsTypes[] = {
"Macro files", "*.C",
"ROOT files", "*.root",
"PostScript", "*.ps",
"Encapsulated PostScript", "*.eps",
"Gif files", "*.gif",
"All files", "*",
0, 0
};
static TGFileInfo fi;
fi.fFileTypes = gOpenAsTypes;
new TGFileDialog(gClient->GetRoot(), gClient->GetRoot(), kFDOpen, &fi);
return fi.fFilename;
}
const char *SaveFileDialog()
{
// Prompt for file to be saved. Depending on navigation in
// dialog the current working directory can be changed.
// The returned file name is always with respect to the
// current directory.
const char *gSaveAsTypes[] = {
"Macro files", "*.C",
"ROOT files", "*.root",
"PostScript", "*.ps",
"Encapsulated PostScript", "*.eps",
"Gif files", "*.gif",
"All files", "*",
0, 0
};
static TGFileInfo fi;
fi.fFileTypes = gSaveAsTypes;
new TGFileDialog(gClient->GetRoot(), gClient->GetRoot(), kFDSave, &fi);
return fi.fFilename;
}
const char *GetStringDialog(const char *prompt, const char *defval)
{
// Prompt for string. The typed in string is returned.
static char answer[128];
new InputDialog(prompt, defval, answer);
return answer;
}
Int_t GetIntegerDialog(const char *prompt, Int_t defval)
{
// Prompt for integer. The typed in integer is returned.
static char answer[32];
char defv[32];
sprintf(defv, "%d", defval);
new InputDialog(prompt, defv, answer);
return atoi(answer);
}
Float_t GetFloatDialog(const char *prompt, Float_t defval)
{
// Prompt for float. The typed in float is returned.
static char answer[32];
char defv[32];
sprintf(defv, "%f", defval);
new InputDialog(prompt, defv, answer);
return atof(answer);
}
Computing file changes ...