// Test program for ROOT native GUI classes // exactly like $ROOTSYS/test/guitest.cxx but using the new signal and slots // communication mechanism. It is now possible to run this entire // test program in the interpreter. Do either: // .x guitest.C // .x guitest.C++ // Authors: Zhibo Richard Zhang #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 #include #include #include #include #include #include #include #include #include #define GEN_HISTS 16 #define GEN_CANVAS 3 //Canvas divisions #define ONED 1 #define TWOD 2 #define NEARBY 3 #define CYT_REG_IDLE 6 #define CYT_REG_SET 7 #define CYT_REG_CAN 8 enum ETestCommandIdentifiers { M_FILE_OPEN, M_FILE_SAVE, M_FILE_SAVEAS, M_FILE_PRINT, M_FILE_PRINTSETUP, M_FILE_EXIT, M_TEST_DLG, M_TEST_MSGBOX, M_TEST_SLIDER, M_TEST_SHUTTER, M_TEST_DIRLIST, M_TEST_FILELIST, M_TEST_PROGRESS, M_TEST_NUMBERENTRY, M_TEST_FONTDIALOG, M_TEST_NEWMENU, M_VIEW_ENBL_DOCK, M_VIEW_ENBL_HIDE, M_VIEW_DOCK, M_VIEW_UNDOCK, M_HELP_CONTENTS, M_HELP_SEARCH, M_HELP_ABOUT, M_CASCADE_1, M_CASCADE_2, M_CASCADE_3, M_NEW_REMOVEMENU, VId1, HId1, VId2, HId2, VSId1, HSId1, VSId2, HSId2 }; Int_t mb_button_id[13] = { kMBYes, kMBNo, kMBOk, kMBApply, kMBRetry, kMBIgnore, kMBCancel, kMBClose, kMBYesAll, kMBNoAll, kMBNewer, kMBAppend, kMBDismiss}; EMsgBoxIcon mb_icon[4] = { kMBIconStop, kMBIconQuestion, kMBIconExclamation, kMBIconAsterisk }; const char *filetypes[] = { "All files", "*", "ROOT files", "*.root", "ROOT macros", "*.C", "Text files", "*.[tT][xX][tT]", 0, 0 }; struct shutterData_t { const char *pixmap_name; const char *tip_text; Int_t id; TGButton *button; }; shutterData_t histo_data[] = { { "h1_s.xpm", "TH1", 1001, 0 }, { "h2_s.xpm", "TH2", 1002, 0 }, { "h3_s.xpm", "TH3", 1003, 0 }, { "profile_s.xpm", "TProfile", 1004, 0 }, { 0, 0, 0, 0 } }; shutterData_t function_data[] = { { "f1_s.xpm", "TF1", 2001, 0 }, { "f2_s.xpm", "TF2", 2002, 0 }, { 0, 0, 0, 0 } }; shutterData_t tree_data[] = { { "ntuple_s.xpm", "TNtuple", 3001, 0 }, { "tree_s.xpm", "TTree", 3002, 0 }, { "chain_s.xpm", "TChain", 3003, 0 }, { 0, 0, 0, 0 } }; const char *editortxt1 = "This is the ROOT text edit widget TGTextEdit. It is not intended as\n" "a full developers editor, but it is relatively complete and can ideally\n" "be used to edit scripts or to present users editable config files, etc.\n\n" "The text edit widget supports standard emacs style ctrl-key navigation\n" "in addition to the arrow keys. By default the widget has under the right\n" "mouse button a popup menu giving access to several built-in functions.\n\n" "Cut, copy and paste between different editor windows and any other\n" "standard text handling application is supported.\n\n" "Text can be selected with the mouse while holding the left button\n" "or with the arrow keys while holding the shift key pressed. Use the\n" "middle mouse button to paste text at the current mouse location." ; const char *editortxt2 = "Mice with scroll-ball are properly supported.\n\n" "This are the currently defined key bindings:\n" "Left Arrow\n" " Move the cursor one character leftwards.\n" " Scroll when cursor is out of frame.\n" "Right Arrow\n" " Move the cursor one character rightwards.\n" " Scroll when cursor is out of frame.\n" "Backspace\n" " Deletes the character on the left side of the text cursor and moves the\n" " cursor one position to the left. If a text has been marked by the user" ; const char *editortxt3 = " (e.g. by clicking and dragging) the cursor will be put at the beginning\n" " of the marked text and the marked text will be removed.\n" "Home\n" " Moves the text cursor to the left end of the line. If mark is TRUE text\n" " will be marked towards the first position, if not any marked text will\n" " be unmarked if the cursor is moved.\n" "End\n" " Moves the text cursor to the right end of the line. If mark is TRUE text\n" " will be marked towards the last position, if not any marked text will\n" " be unmarked if the cursor is moved.\n" "Delete" ; const char *editortxt4 = " Deletes the character on the right side of the text cursor. If a text\n" " has been marked by the user (e.g. by clicking and dragging) the cursor\n" " will be put at the beginning of the marked text and the marked text will\n" " be removed.\n" "Shift - Left Arrow\n" " Mark text one character leftwards.\n" "Shift - Right Arrow\n" " Mark text one character rightwards.\n" "Control-A\n" " Select the whole text.\n" "Control-B\n" " Move the cursor one character leftwards." ; const char *editortxt5 = "Control-C\n" " Copy the marked text to the clipboard.\n" "Control-D\n" " Delete the character to the right of the cursor.\n" "Control-E\n" " Move the cursor to the end of the line.\n" "Control-F\n" " Start Search Dialog.\n" "Control-H\n" " Delete the character to the left of the cursor.\n" "Control-K\n" " Delete marked text if any or delete all\n" " characters to the right of the cursor.\n" "Control-L\n" " Start GoTo Line Dialog" ; const char *editortxt6 = "Control-U\n" " Delete all characters on the line.\n" "Control-V\n" " Paste the clipboard text into line edit.\n" "Control-X\n" " Cut the marked text, copy to clipboard.\n" "Control-Y\n" " Paste the clipboard text into line edit.\n" "Control-Z\n" " Undo action.\n\n" "All other keys with valid ASCII codes insert themselves into the line."; class TestDialog { RQ_OBJECT("TestDialog") private: TGMainFrame *fMain; TGCompositeFrame *fFrame1, *fF1, *fF2, *fF3, *fF4, *fF5; TGGroupFrame *fF6, *fF7; TGButton *fOkButton, *fCancelButton, *fStartB, *fStopB, *fUpdate1DB; TGButton *fBtn1, *fBtn2, *fChk1, *fChk2, *fRad1, *fRad2; TGPictureButton *fPicBut1; TGCheckButton *fCheck1; TGCheckButton *fCheckMulti; TGListBox *fListBox; TGComboBox *fCombo; TGTab *fTab; TGTextEntry *fTxt1, *fTxt2; TGLayoutHints *fL1, *fL2, *fL3, *fL4; TGLayoutHints *fMenuBarLayout, *fMenuBarItemLayout; TRootEmbeddedCanvas *fEc1, *fEc2, *fEc3; Int_t fFirstEntry; Int_t fLastEntry; Bool_t fFillHistos; // TH1F *fHpx; TH2F *fHpxpy; TGPopupMenu *fMenuFile, *fMenuHelp; TGMenuBar *fMenuBar; // TCanvas *c1, *c2, *c3; //Palette Colorbar Pixel_t bwhite, bblack, bblue,bred,byellow,bpurple,bgray,bgreen; void FillHistos(); public: TestDialog(const TGWindow *p, UInt_t w, UInt_t h, UInt_t options = kVerticalFrame); virtual ~TestDialog(); // slots void DoClose(); void CloseWindow(); void DoOK(); void DoCancel(); void DoTab(Int_t id); //Events handler void HandleButtons(Int_t id = -1); void HandleEmbeddedCanvas(Int_t event, Int_t x, Int_t y, TObject *sel); void HandleMenu(Int_t id); void HandlePopup() { printf("menu popped up\n"); } void HandlePopdown() { printf("menu popped down\n"); } void SetUpPalette(); //Region Variables // TCutG *Region[GEN_HISTS]; std::vector XVertex; std::vector YVertex; int CanvasDim[GEN_HISTS]; int iRegionState; int iCanvas; // TCutG *TempRegion; int iTemp; int iPoints; int iReg; // The order # of region. int ActRegion; // Current active region bool fMouseUp; bool DragMoveFlag; double DragPointX, DragPointY; TCanvas *fCanvas[GEN_CANVAS]; TText *pFrstText; double m_dTextPosX; double m_dTextPosY; TString m_TStrFrstText; TObject *m_sel; int m_iXBins; int m_iYBins; }; TestDialog::TestDialog(const TGWindow *p, UInt_t w, UInt_t h, UInt_t options) { // Create a dialog window. A dialog window pops up with respect to its // "main" window. fMain = new TGMainFrame(p, w, h); // fMain = new TGTransientFrame(p, main, w, h, options); // fMain->Connect("CloseWindow()", "TestDialog", this, "DoClose()"); // fMain->DontCallClose(); // to avoid double deletions. // use hierarchical cleaning fMain->SetCleanup(kDeepCleanup); //Palette SetUpPalette(); fMain->SetBackgroundColor(bwhite); //********************************************************************** //**************Initialize parameters for Region Selection ************* //********************************************************************** CanvasDim[0] = TWOD; CanvasDim[1] = TWOD; CanvasDim[2] = TWOD; iRegionState = CYT_REG_IDLE; iCanvas = 1; // Range: 1~3 // TempRegion = 0; // memset(Region, 0, sizeof(Region)); memset(fCanvas, 0, sizeof(fCanvas)); iTemp = 0; iPoints = 0; iReg = 0; ActRegion = 0; fMouseUp = false; DragPointX = 0; DragPointY = 0; m_sel = 0; DragMoveFlag = false; //Set up bins for x and y axis m_iXBins = 128; m_iYBins = 128; //--------- Create Menu fMenuFile = new TGPopupMenu(p); //gClient->GetRoot()); fMenuFile->AddEntry("&Open...", M_FILE_OPEN); fMenuFile->AddEntry("&Save", M_FILE_SAVE); fMenuFile->AddEntry("S&ave as...", M_FILE_SAVEAS); fMenuFile->AddEntry("&Close", -1); fMenuFile->AddSeparator(); fMenuFile->AddEntry("&Print", M_FILE_PRINT); fMenuFile->AddSeparator(); fMenuFile->AddEntry("E&xit", M_FILE_EXIT); fMenuHelp = new TGPopupMenu(p); fMenuHelp->AddEntry("&Contents", M_HELP_CONTENTS); fMenuHelp->AddEntry("&Search...", M_HELP_SEARCH); fMenuHelp->AddSeparator(); fMenuHelp->AddEntry("&About", M_HELP_ABOUT); // Menu button messages are handled by the main frame (i.e. "this") // HandleMenu() method. fMenuFile->Connect("Activated(Int_t)", "TestDialog", this, "HandleMenu(Int_t)"); fMenuFile->Connect("PoppedUp()", "TestDialog", this, "HandlePopup()"); fMenuFile->Connect("PoppedDown()", "TestDialog", this, "HandlePopdown()"); fMenuHelp->Connect("Activated(Int_t)", "TestDialog", this, "HandleMenu(Int_t)"); fMenuBarLayout = new TGLayoutHints(kLHintsTop | kLHintsExpandX); fMenuBarItemLayout = new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0); fMenuBar = new TGMenuBar(fMain, 1, 1, kHorizontalFrame); fMenuBar->SetBackgroundColor(bwhite); fMenuBar->AddPopup("&File", fMenuFile, fMenuBarItemLayout); fMenuBar->AddPopup("&Help", fMenuHelp, fMenuBarItemLayout); fMain->AddFrame(fMenuBar, fMenuBarLayout); //--------- create Tab widget and some composite frames for Tab testing fTab = new TGTab(fMain, 600, 600); // fTab->Connect("Selected(Int_t)", "TestDialog", this, "DoTab(Int_t)"); fL3 = new TGLayoutHints(kLHintsTop | kLHintsLeft, 2, 2, 2, 2); TGCompositeFrame *tf = fTab->AddTab("Tab 1"); // = fFTop tf->SetBackgroundColor(bwhite); //-------------- embedded canvas demo fFillHistos = kFALSE; fHpxpy = 0; //fF3 is for control buttons fF3 = new TGCompositeFrame(tf, 60, 20, kHorizontalFrame); fStartB = new TGTextButton(fF3, "Start &Filling Hists", 40); fStopB = new TGTextButton(fF3, "&Stop Filling Hists", 41); fStartB->Connect("Clicked()", "TestDialog", this, "HandleButtons()"); fStopB->Connect("Clicked()", "TestDialog", this, "HandleButtons()"); fF3->AddFrame(fStartB, fL3); fF3->AddFrame(fStopB, fL3); fF3->SetBackgroundColor(bwhite); //fF5 is for embedded canvas fF5 = new TGCompositeFrame(tf, 200, 100, kHorizontalFrame); // = fFTrend fF5->SetBackgroundColor(bwhite); fL4 = new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX | kLHintsExpandY, 5, 5, 5, 5); fEc1 = new TRootEmbeddedCanvas("ec1", fF5, 500, 500); fF5->AddFrame(fEc1, fL4); tf->AddFrame(fF3, fL3); tf->AddFrame(fF5, fL4); //The 1st Canvas iCanvas = 0; fCanvas[iCanvas] = fEc1->GetCanvas(); fCanvas[iCanvas]->SetBorderMode(0); fCanvas[iCanvas]->SetBit(kNoContextMenu); fCanvas[iCanvas]->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)", "TestDialog", this, "HandleEmbeddedCanvas(Int_t,Int_t,Int_t,TObject*)"); fCanvas[iCanvas]->cd(); pFrstText = new TText(); pFrstText->SetNDC(kTRUE); m_dTextPosX = 0.1; m_dTextPosY = 0.96; pFrstText->SetText(m_dTextPosX, m_dTextPosY, " "); pFrstText->SetTextColor(1); pFrstText->SetTextSize(0.035); pFrstText->SetBit(kCannotPick); //Lock the statistics pFrstText->Draw(); fCanvas[iCanvas]->Modified(); fCanvas[iCanvas]->Update(); TGLayoutHints *fL5 = new TGLayoutHints(kLHintsBottom | kLHintsExpandX | kLHintsExpandY, 2, 2, 5, 1); fMain->AddFrame(fTab, fL5); fMain->MapSubwindows(); fMain->Resize(); // position relative to the parent's window //fMain->CenterOnParent(); fMain->SetWindowName("Dialog"); fMain->MapWindow(); //gClient->WaitFor(fMain); // otherwise canvas contextmenu does not work } TestDialog::~TestDialog() { // Delete test dialog widgets. fMain->DeleteWindow(); // deletes fMain if(TempRegion) TempRegion->Delete(); TempRegion = 0; for(int i=0; iDelete(); fCanvas[i] = 0; } } for(int i=0; iDelete(); Region[i] = 0; } } } void TestDialog::HandleMenu(Int_t id) { // Handle menu items. switch (id) { case M_FILE_OPEN: { static TString dir("."); TGFileInfo fi; fi.fFileTypes = filetypes; fi.fIniDir = StrDup(dir); new TGFileDialog(gClient->GetRoot(), fMain, kFDOpen, &fi); dir = fi.fIniDir; } break; case M_FILE_SAVE: printf("M_FILE_SAVE\n"); break; case M_FILE_PRINT: printf("M_FILE_PRINT\n"); printf("Hiding itself, select \"Print Setup...\" to enable again\n"); fMenuFile->HideEntry(M_FILE_PRINT); break; case M_FILE_PRINTSETUP: printf("M_FILE_PRINTSETUP\n"); printf("Enabling \"Print\"\n"); fMenuFile->EnableEntry(M_FILE_PRINT); break; case M_FILE_EXIT: CloseWindow(); // terminate theApp no need to use SendCloseMessage() break; case M_TEST_DLG: new TestDialog(gClient->GetRoot(), fMain, 400, 200); break; case M_TEST_MSGBOX: new TestMsgBox(gClient->GetRoot(), fMain, 400, 200); break; case M_TEST_SLIDER: new TestSliders(gClient->GetRoot(), fMain, 400, 200); break; case M_TEST_SHUTTER: new TestShutter(gClient->GetRoot(), fMain, 400, 200); break; case M_TEST_DIRLIST: new TestDirList(gClient->GetRoot(), fMain, 400, 200); break; case M_TEST_FILELIST: new TestFileList(gClient->GetRoot(), fMain, 400, 200); break; case M_TEST_PROGRESS: new TestProgress(gClient->GetRoot(), fMain, 600, 300); break; case M_TEST_NUMBERENTRY: new EntryTestDlg(gClient->GetRoot(), fMain); break; case M_TEST_FONTDIALOG: { TGFontDialog::FontProp_t prop; new TGFontDialog(gClient->GetRoot(), fMain, &prop); if (prop.fName != "") printf("Selected font: %s, size %d, italic %s, bold %s, color 0x%lx, align %u\n", prop.fName.Data(), prop.fSize, prop.fItalic ? "yes" : "no", prop.fBold ? "yes" : "no", prop.fColor, prop.fAlign); } break; case M_TEST_NEWMENU: { if (fMenuTest->IsEntryChecked(M_TEST_NEWMENU)) { HandleMenu(M_NEW_REMOVEMENU); return; } fMenuTest->CheckEntry(M_TEST_NEWMENU); TGPopupMenu *p = fMenuBar->GetPopup("Test"); fMenuBar->AddPopup("New 1", fMenuNew1, fMenuBarItemLayout, p); p = fMenuBar->GetPopup("Help"); fMenuBar->AddPopup("New 2", fMenuNew2, fMenuBarItemLayout, p); fMenuBar->MapSubwindows(); fMenuBar->Layout(); TGMenuEntry *e = fMenuTest->GetEntry("Add New Menus"); fMenuTest->AddEntry("Remove New Menus", M_NEW_REMOVEMENU, 0, 0, e); } break; case M_NEW_REMOVEMENU: { fMenuBar->RemovePopup("New 1"); fMenuBar->RemovePopup("New 2"); fMenuBar->Layout(); fMenuTest->DeleteEntry(M_NEW_REMOVEMENU); fMenuTest->UnCheckEntry(M_TEST_NEWMENU); } break; case M_VIEW_ENBL_DOCK: fMenuDock->EnableUndock(!fMenuDock->EnableUndock()); if (fMenuDock->EnableUndock()) { fMenuView->CheckEntry(M_VIEW_ENBL_DOCK); fMenuView->EnableEntry(M_VIEW_UNDOCK); } else { fMenuView->UnCheckEntry(M_VIEW_ENBL_DOCK); fMenuView->DisableEntry(M_VIEW_UNDOCK); } break; case M_VIEW_ENBL_HIDE: fMenuDock->EnableHide(!fMenuDock->EnableHide()); if (fMenuDock->EnableHide()) { fMenuView->CheckEntry(M_VIEW_ENBL_HIDE); } else { fMenuView->UnCheckEntry(M_VIEW_ENBL_HIDE); } break; case M_VIEW_DOCK: fMenuDock->DockContainer(); fMenuView->EnableEntry(M_VIEW_UNDOCK); fMenuView->DisableEntry(M_VIEW_DOCK); break; case M_VIEW_UNDOCK: fMenuDock->UndockContainer(); fMenuView->EnableEntry(M_VIEW_DOCK); fMenuView->DisableEntry(M_VIEW_UNDOCK); break; default: printf("Menu item %d selected\n", id); break; } } void TestDialog::SetUpPalette() { gClient->GetColorByName("white",bwhite); gClient->GetColorByName("blue",bblue); gClient->GetColorByName("red",bred); gClient->GetColorByName("black",bblack); gClient->GetColorByName("green",bgreen); gClient->GetColorByName("yellow",byellow); gClient->GetColorByName("purple",bpurple); gClient->GetColorByName("gray",bgray); } void TestDialog::FillHistos() { // Fill histograms till user clicks "Stop Filling" button. static int cnt; double dCount = 0.0; int iXBinMax = 0, iYBinMax = 0; if (!fHpxpy) { fHpxpy = new TH2F("hpxpy","",m_iXBins,-4,4,m_iYBins,-4,4); fHpxpy->SetStats(0); fHpxpy->SetXTitle("X"); fHpxpy->SetYTitle("Y"); cnt = 0; } const int kUPDATE = 1000; float px, py; while (fFillHistos) { gRandom->Rannor(px,py); //px and py will be two gaussian random numbers fHpxpy->Fill(px,py); cnt++; if (!(cnt % kUPDATE)) { if (cnt == kUPDATE) { fCanvas[0]->cd(); fHpxpy->Draw("COL"); m_TStrFrstText.Form("Plot"); pFrstText->SetText(m_dTextPosX, m_dTextPosY, m_TStrFrstText); pFrstText->Draw(); } iXBinMax = fHpxpy->GetXaxis()->GetLast(); iYBinMax = fHpxpy->GetYaxis()->GetLast(); dCount = fHpxpy->Integral(1, iXBinMax, 1, iYBinMax); fCanvas[0]->Modified(); fCanvas[0]->Update(); gSystem->ProcessEvents(); // handle GUI events } } } void TestDialog::DoClose() { printf("\nTerminating dialog: via window manager\n"); if (fFillHistos) { fFillHistos = kFALSE; TTimer::SingleShot(150, "TestDialog", this, "CloseWindow()"); } else CloseWindow(); // Close the Ged editor if it was activated. if (TVirtualPadEditor::GetPadEditor(kFALSE) != 0) TVirtualPadEditor::Terminate(); } void TestDialog::CloseWindow() { // Called when window is closed via the window manager. delete this; } void TestDialog::DoOK() { fFillHistos = kFALSE; printf("\nTerminating dialog: OK pressed\n"); // Add protection against double-clicks fOkButton->SetState(kButtonDisabled); fCancelButton->SetState(kButtonDisabled); // Send a close message to the main frame. This will trigger the // emission of a CloseWindow() signal, which will then call // TestDialog::CloseWindow(). Calling directly CloseWindow() will cause // a segv since the OK button is still accessed after the DoOK() method. // This works since the close message is handled synchronous (via // message going to/from X server). //fMain->SendCloseMessage(); // The same effect can be obtained by using a singleshot timer: TTimer::SingleShot(150, "TestDialog", this, "CloseWindow()"); // Close the Ged editor if it was activated. if (TVirtualPadEditor::GetPadEditor(kFALSE) != 0) TVirtualPadEditor::Terminate(); } void TestDialog::DoCancel() { fFillHistos = kFALSE; printf("\nTerminating dialog: Cancel pressed\n"); // Add protection against double-clicks fOkButton->SetState(kButtonDisabled); fCancelButton->SetState(kButtonDisabled); TTimer::SingleShot(150, "TestDialog", this, "CloseWindow()"); // Close the Ged editor if it was activated. if (TVirtualPadEditor::GetPadEditor(kFALSE) != 0) TVirtualPadEditor::Terminate(); } void TestDialog::HandleButtons(Int_t id) { // Handle different buttons. if (id == -1) { TGButton *btn = (TGButton *) gTQSender; id = btn->WidgetId(); } printf("DoButton: id = %d\n", id); char tmp[20]; static int newtab = 0; int iLoc = 0; //Location # of Canvas switch (id) { case 40: // start histogram filling fFillHistos = kTRUE; FillHistos(); break; case 41: // stop histogram filling fFillHistos = kFALSE; // FirstRegion(iLoc); break; default: break; } } void TestDialog::DoTab(Int_t id) { printf("Tab item %d activated\n", id); } void TestDialog::HandleEmbeddedCanvas(Int_t event, Int_t x, Int_t y, TObject *sel) { // Handle events in the left embedded canvas. double dX=0.0, dY=0.0; m_sel = sel; } void samplegui() { new TestDialog(gClient->GetRoot(), 1678, 1676); } //---- Main program ------------------------------------------------------------ #ifdef STANDALONE int main(int argc, char **argv) { TApplication theApp("App", &argc, argv); if (gROOT->IsBatch()) { fprintf(stderr, "%s: cannot run in batch mode\n", argv[0]); return 1; } guitest(); theApp.Run(); return 0; } #endif