TGSplitFrame.cxx

Go to the documentation of this file.
00001 // @(#)root/gui:$Id: TGSplitFrame.cxx 35622 2010-09-23 08:29:15Z bellenot $
00002 // Author: Bertrand Bellenot 23/01/2008
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "TGFrame.h"
00013 #include "TGLayout.h"
00014 #include "TGMenu.h"
00015 #include "TGSplitter.h"
00016 #include "TGSplitFrame.h"
00017 #include "TGInputDialog.h"
00018 #include "TGResourcePool.h"
00019 #include "TRootContextMenu.h"
00020 #include "TClassMenuItem.h"
00021 #include "TContextMenu.h"
00022 #include "TString.h"
00023 #include "TClass.h"
00024 #include "TList.h"
00025 #include "Riostream.h"
00026 
00027 ClassImp(TGSplitTool)
00028 ClassImp(TGSplitFrame)
00029 
00030 //______________________________________________________________________________
00031 TGSplitTool::TGSplitTool(const TGWindow *p, const TGFrame *f)
00032    : TGCompositeFrame(p, 10, 10, kHorizontalFrame | kRaisedFrame | kFixedSize)
00033 {
00034    // Create a split frame tool tip. P is the tool tips parent window (normally
00035    // fClient->GetRoot() and f is the frame to which the tool tip is associated.
00036 
00037    SetWindowAttributes_t attr;
00038    attr.fMask             = kWAOverrideRedirect | kWASaveUnder;
00039    attr.fOverrideRedirect = kTRUE;
00040    attr.fSaveUnder        = kTRUE;
00041 
00042    gVirtualX->ChangeWindowAttributes(fId, &attr);
00043    SetBackgroundColor(fClient->GetResourcePool()->GetTipBgndColor());
00044 
00045    fRectGC.SetFillStyle(kFillSolid);
00046    fRectGC.SetForeground(0x99ff99);
00047    
00048    TClass *cl = TClass::GetClass("TGSplitFrame");
00049    cl->MakeCustomMenuList();
00050    TList *ml = cl->GetMenuList();
00051    ((TClassMenuItem *)ml->At(1))->SetTitle("Cleanup Frame");
00052    ((TClassMenuItem *)ml->At(2))->SetTitle("Close and Collapse");
00053    ((TClassMenuItem *)ml->At(3))->SetTitle("Undock Frame");
00054    ((TClassMenuItem *)ml->At(4))->SetTitle("Dock Frame Back");
00055    ((TClassMenuItem *)ml->At(5))->SetTitle("Switch to Main");
00056    ((TClassMenuItem *)ml->At(6))->SetTitle("Horizontally Split...");
00057    ((TClassMenuItem *)ml->At(7))->SetTitle("Vertically Split...");
00058    fContextMenu = new TContextMenu("SplitFrameContextMenu", "Actions");
00059    fMap.SetOwner(kTRUE);
00060    fMap.SetOwnerValue(kFALSE);
00061    MapSubwindows();
00062    Resize(f->GetWidth()/10, f->GetHeight()/10);
00063    AddInput(kButtonPressMask | kButtonReleaseMask | kPointerMotionMask);
00064 
00065    fWindow = f;
00066    fX = fY = -1;
00067 }
00068 
00069 //______________________________________________________________________________
00070 TGSplitTool::~TGSplitTool()
00071 {
00072    // TGSplitTool destructor.
00073 
00074    delete fContextMenu;
00075 }
00076 
00077 //______________________________________________________________________________
00078 void TGSplitTool::AddRectangle(TGFrame *frame, Int_t x, Int_t y, Int_t w, Int_t h)
00079 {
00080    // Add a rectangle representation of a split frame in the map, together 
00081    // with the frame itself.
00082 
00083    TGRectMap *rect = new TGRectMap(x, y, w, h); 
00084    fMap.Add(rect, frame);
00085 }
00086 
00087 //______________________________________________________________________________
00088 void TGSplitTool::DoRedraw()
00089 {
00090    // Redraw split frame tool.
00091 
00092    TGRectMap *rect;
00093    TMapIter next(&fMap);
00094    while ((rect = (TGRectMap*)next())) {
00095       gVirtualX->FillRectangle(fId, GetBckgndGC()(), rect->fX, 
00096                                rect->fY, rect->fW, rect->fH);
00097       gVirtualX->DrawRectangle(fId, GetBlackGC()(), rect->fX, rect->fY, 
00098                                rect->fW, rect->fH);
00099    }
00100    DrawBorder();
00101 }
00102 
00103 //______________________________________________________________________________
00104 void TGSplitTool::DrawBorder()
00105 {
00106    // Draw border of tool window.
00107 
00108    gVirtualX->DrawLine(fId, GetShadowGC()(), 0, 0, fWidth-2, 0);
00109    gVirtualX->DrawLine(fId, GetShadowGC()(), 0, 0, 0, fHeight-2);
00110    gVirtualX->DrawLine(fId, GetBlackGC()(),  0, fHeight-1, fWidth-1, fHeight-1);
00111    gVirtualX->DrawLine(fId, GetBlackGC()(),  fWidth-1, fHeight-1, fWidth-1, 0);
00112 }
00113 
00114 //______________________________________________________________________________
00115 Bool_t TGSplitTool::HandleButton(Event_t *event)
00116 {
00117    // Handle mouse click events in the tool.
00118 
00119    if (event->fType != kButtonPress)
00120       return kTRUE;
00121    Int_t px = 0, py = 0;
00122    Window_t wtarget;
00123    TGRectMap *rect;
00124    TGSplitFrame *frm = 0;
00125    TMapIter next(&fMap);
00126    while ((rect = (TGRectMap*)next())) {
00127       if (rect->Contains(event->fX, event->fY)) {
00128          frm = (TGSplitFrame *)fMap.GetValue((const TObject *)rect);
00129          gVirtualX->TranslateCoordinates(event->fWindow,
00130                                          gClient->GetDefaultRoot()->GetId(), 
00131                                          event->fX, event->fY, px, py, wtarget);
00132          fContextMenu->Popup(px, py, frm);
00133          // connect PoppedDown signal to close the tool window 
00134          // when the menu is closed
00135          TRootContextMenu *menu = ((TRootContextMenu *)fContextMenu->GetContextMenuImp());
00136          ((TGPopupMenu *)menu)->Connect("PoppedDown()", "TGSplitTool", this, "Hide()");
00137          return kTRUE;
00138       }
00139    }
00140    Hide();
00141    return kTRUE;
00142 }
00143 
00144 //______________________________________________________________________________
00145 Bool_t TGSplitTool::HandleMotion(Event_t *event)
00146 {
00147    // handle mouse motion events
00148 
00149    static TGRectMap *rect = 0, *oldrect = 0;
00150    TMapIter next(&fMap);
00151    while ((rect = (TGRectMap*)next())) {
00152       if (rect->Contains(event->fX, event->fY)) {
00153          // if inside a rectangle, highlight it
00154          if (rect != oldrect) {
00155             if (oldrect) {
00156                gVirtualX->FillRectangle(fId, GetBckgndGC()(), oldrect->fX, 
00157                                         oldrect->fY, oldrect->fW, oldrect->fH);
00158                gVirtualX->DrawRectangle(fId, GetBlackGC()(), oldrect->fX, oldrect->fY, 
00159                                         oldrect->fW, oldrect->fH);
00160             }
00161             gVirtualX->FillRectangle(fId, fRectGC(), rect->fX, rect->fY, rect->fW, 
00162                                      rect->fH);
00163             gVirtualX->DrawRectangle(fId, GetBlackGC()(), rect->fX, rect->fY, 
00164                                      rect->fW, rect->fH);
00165             oldrect = rect;
00166          }
00167          return kTRUE;
00168       }
00169    }
00170    if (oldrect) {
00171       gVirtualX->FillRectangle(fId, GetBckgndGC()(), oldrect->fX, 
00172                                oldrect->fY, oldrect->fW, oldrect->fH);
00173       gVirtualX->DrawRectangle(fId, GetBlackGC()(), oldrect->fX, oldrect->fY, 
00174                                oldrect->fW, oldrect->fH);
00175    }
00176    return kTRUE;
00177 }
00178 //______________________________________________________________________________
00179 void TGSplitTool::Hide()
00180 {
00181    // Hide tool window. Use this method to hide the tool in a client class.
00182 
00183    gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);  // ungrab pointer
00184    fMap.Delete();
00185    UnmapWindow();
00186 }
00187 
00188 //______________________________________________________________________________
00189 void TGSplitTool::Reset()
00190 {
00191    // Reset tool tip popup delay timer. Use this method to activate tool tip
00192    // in a client class.
00193 
00194    fMap.Delete();
00195 }
00196 
00197 //______________________________________________________________________________
00198 void TGSplitTool::SetPosition(Int_t x, Int_t y)
00199 {
00200    // Set popup position within specified frame (as specified in the ctor).
00201    // To get back default behaviour (in the middle just below the designated
00202    // frame) set position to -1,-1.
00203 
00204    fX = x;
00205    fY = y;
00206 
00207    if (fX < -1)
00208       fX = 0;
00209    if (fY < -1)
00210       fY = 0;
00211 
00212    if (fWindow) {
00213       if (fX > (Int_t) fWindow->GetWidth())
00214          fX = fWindow->GetWidth();
00215       if (fY > (Int_t) fWindow->GetHeight())
00216          fY = fWindow->GetHeight();
00217    }
00218 }
00219 
00220 //______________________________________________________________________________
00221 void TGSplitTool::Show(Int_t x, Int_t y)
00222 {
00223    // Show tool window.
00224 
00225    Move(x, y);
00226    MapWindow();
00227    RaiseWindow();
00228 
00229    // last argument kFALSE forces all specified events to this window
00230    gVirtualX->GrabPointer(fId, kButtonPressMask | kPointerMotionMask, kNone, 
00231                           fClient->GetResourcePool()->GetGrabCursor(), 
00232                           kTRUE, kFALSE);
00233    Long_t args[2];
00234    args[0] = x;
00235    args[1] = y;
00236 }
00237 
00238 //______________________________________________________________________________
00239 TGSplitFrame::TGSplitFrame(const TGWindow *p, UInt_t w, UInt_t h,
00240         UInt_t options) : TGCompositeFrame(p, w, h, options), 
00241         fFrame(0), fSplitter(0), fFirst(0), fSecond(0)
00242 {
00243    // Default constructor.
00244 
00245    fSplitTool = new TGSplitTool(gClient->GetDefaultRoot(), this);
00246    fHRatio = fWRatio = 0.0;
00247    fUndocked = 0;
00248    AddInput(kStructureNotifyMask);
00249    SetCleanup(kLocalCleanup);
00250 }
00251 
00252 //______________________________________________________________________________
00253 TGSplitFrame::~TGSplitFrame()
00254 {
00255    // Destructor. Make cleanup.
00256    
00257    delete fSplitTool;
00258    Cleanup();
00259 }
00260 
00261 //______________________________________________________________________________
00262 void TGSplitFrame::AddFrame(TGFrame *f, TGLayoutHints *l)
00263 {
00264    // Add a frame in the split frame using layout hints l.
00265 
00266    TGCompositeFrame::AddFrame(f, l);
00267    fFrame = f;
00268 }
00269 
00270 //______________________________________________________________________________
00271 void TGSplitFrame::RemoveFrame(TGFrame *f)
00272 {
00273    // Add a frame in the split frame using layout hints l.
00274 
00275    TGCompositeFrame::RemoveFrame(f);
00276    if (f == fFrame)
00277       fFrame = 0;
00278 }
00279 
00280 //______________________________________________________________________________
00281 void TGSplitFrame::Cleanup()
00282 {
00283    // Recursively cleanup child frames.
00284 
00285    TGCompositeFrame::Cleanup();
00286    fFirst = 0;
00287    fSecond = 0;
00288    fSplitter = 0;
00289    fUndocked = 0;
00290 }
00291 
00292 //______________________________________________________________________________
00293 TGSplitFrame *TGSplitFrame::GetTopFrame()
00294 {
00295    // Return the top level split frame.
00296 
00297    TGSplitFrame *top = this;
00298    TGWindow *w = (TGWindow *)GetParent();
00299    TGSplitFrame *p = dynamic_cast<TGSplitFrame *>(w);
00300    while (p) {
00301       top = p;
00302       w = (TGWindow *)p->GetParent();
00303       p = dynamic_cast<TGSplitFrame *>(w);
00304    }
00305    return top;
00306 }
00307 
00308 //______________________________________________________________________________
00309 void TGSplitFrame::Close()
00310 {
00311    // Close (unmap and remove from the list of frames) the frame contained in
00312    // this split frame.
00313 
00314    if (fFrame) {
00315       fFrame->UnmapWindow();
00316       RemoveFrame(fFrame);
00317    }
00318    fFrame = 0;
00319 }
00320 
00321 //______________________________________________________________________________
00322 void TGSplitFrame::CloseAndCollapse()
00323 {
00324    // Close (unmap, remove from the list of frames and destroy) the frame 
00325    // contained in this split frame. Then unsplit the parent frame.
00326 
00327    if (!fSplitter || !fFirst || !fSecond) {
00328       TGSplitFrame *parent = (TGSplitFrame *)GetParent();
00329       if (parent->GetFirst() && parent->GetSecond()) {
00330          if (parent->GetFirst()  == this)
00331             parent->UnSplit("first");
00332          else if (parent->GetSecond() == this)
00333             parent->UnSplit("second");
00334       }
00335    }
00336 }
00337 //______________________________________________________________________________
00338 void TGSplitFrame::Docked(TGFrame* frame)
00339 {
00340    // Emit Undocked() signal.
00341 
00342    Emit("Docked(TGFrame*)", (Long_t)frame);
00343 }
00344 
00345 //______________________________________________________________________________
00346 void TGSplitFrame::ExtractFrame()
00347 {
00348    // Extract the frame contained in this split frame an reparent it in a 
00349    // transient frame. Keep a pointer on the transient frame to be able to
00350    // swallow the child frame back to this.
00351 
00352    if (fFrame) {
00353       fFrame->UnmapWindow();
00354       fUndocked = new TGTransientFrame(gClient->GetDefaultRoot(), GetMainFrame(), 800, 600);
00355       fFrame->ReparentWindow(fUndocked);
00356       fUndocked->AddFrame(fFrame, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
00357       // Layout...
00358       fUndocked->MapSubwindows();
00359       fUndocked->Layout();
00360       fUndocked->MapWindow();
00361       RemoveFrame(fFrame);
00362       fUndocked->Connect("CloseWindow()", "TGSplitFrame", this, "SwallowBack()");
00363       Undocked(fFrame);
00364    }
00365 }
00366 
00367 //______________________________________________________________________________
00368 Bool_t TGSplitFrame::HandleConfigureNotify(Event_t *)
00369 {
00370    // Handles resize events for this frame.
00371    // This is needed to keep as much as possible the sizes ratio between
00372    // all subframes.
00373 
00374    if (!fFirst) {
00375       // case of resizing a frame with the splitter (and not from parent)
00376       TGWindow *w = (TGWindow *)GetParent();
00377       TGSplitFrame *p = dynamic_cast<TGSplitFrame *>(w);
00378       if (p) {
00379          if (p->GetFirst()) {
00380             // set the correct ratio for this child
00381             Float_t hratio = (Float_t)p->GetFirst()->GetHeight() / (Float_t)p->GetHeight();
00382             Float_t wratio = (Float_t)p->GetFirst()->GetWidth() / (Float_t)p->GetWidth();
00383             p->SetHRatio(hratio);
00384             p->SetWRatio(wratio);
00385          }
00386       }
00387       return kTRUE;
00388    }
00389    // case of resize event comes from the parent (i.e. by rezing TGMainFrame)
00390    if ((fHRatio > 0.0) && (fWRatio > 0.0)) {
00391       Float_t h = fHRatio * (Float_t)GetHeight();
00392       fFirst->SetHeight((UInt_t)h);
00393       Float_t w = fWRatio * (Float_t)GetWidth();
00394       fFirst->SetWidth((UInt_t)w);
00395    }
00396    // memorize the actual ratio for next resize event
00397    fHRatio = (Float_t)fFirst->GetHeight() / (Float_t)GetHeight();
00398    fWRatio = (Float_t)fFirst->GetWidth() / (Float_t)GetWidth();
00399    fClient->NeedRedraw(this);
00400    if (!gVirtualX->InheritsFrom("TGX11"))
00401       Layout();
00402    return kTRUE;
00403 }
00404 
00405 //______________________________________________________________________________
00406 void TGSplitFrame::HSplit(UInt_t h)
00407 {
00408    // Horizontally split the frame.
00409 
00410    // return if already splitted
00411    if ((fSplitter != 0) || (fFirst != 0) || (fSecond != 0) || (fFrame != 0))
00412       return;
00413    UInt_t height = (h > 0) ? h : fHeight/2;
00414    // set correct option (vertical frame)
00415    ChangeOptions((GetOptions() & ~kHorizontalFrame) | kVerticalFrame);
00416    // create first split frame with fixed height - required for the splitter
00417    fFirst = new TGSplitFrame(this, fWidth, height, kSunkenFrame | kFixedHeight);
00418    // create second split frame
00419    fSecond = new TGSplitFrame(this, fWidth, height, kSunkenFrame);
00420    // create horizontal splitter
00421    fSplitter = new TGHSplitter(this, 4, 4);
00422    // set the splitter's frame to the first one
00423    fSplitter->SetFrame(fFirst, kTRUE);
00424    fSplitter->Connect("ProcessedEvent(Event_t*)", "TGSplitFrame", this, 
00425                       "OnSplitterClicked(Event_t*)");
00426    // add all frames
00427    TGCompositeFrame::AddFrame(fFirst, new TGLayoutHints(kLHintsExpandX));
00428    TGCompositeFrame::AddFrame(fSplitter, new TGLayoutHints(kLHintsLeft | 
00429                               kLHintsTop | kLHintsExpandX));
00430    TGCompositeFrame::AddFrame(fSecond, new TGLayoutHints(kLHintsExpandX | 
00431                               kLHintsExpandY));
00432 }
00433 
00434 //______________________________________________________________________________
00435 void TGSplitFrame::VSplit(UInt_t w)
00436 {
00437    // Vertically split the frame.
00438 
00439    // return if already splitted
00440    if ((fSplitter != 0) || (fFirst != 0) || (fSecond != 0) || (fFrame != 0))
00441       return;
00442    UInt_t width = (w > 0) ? w : fWidth/2;
00443    // set correct option (horizontal frame)
00444    ChangeOptions((GetOptions() & ~kVerticalFrame) | kHorizontalFrame);
00445    // create first split frame with fixed width - required for the splitter
00446    fFirst = new TGSplitFrame(this, width, fHeight, kSunkenFrame | kFixedWidth);
00447    // create second split frame
00448    fSecond = new TGSplitFrame(this, width, fHeight, kSunkenFrame);
00449    // create vertical splitter
00450    fSplitter = new TGVSplitter(this, 4, 4);
00451    // set the splitter's frame to the first one
00452    fSplitter->SetFrame(fFirst, kTRUE);
00453    fSplitter->Connect("ProcessedEvent(Event_t*)", "TGSplitFrame", this, 
00454                       "OnSplitterClicked(Event_t*)");
00455    // add all frames
00456    TGCompositeFrame::AddFrame(fFirst, new TGLayoutHints(kLHintsExpandY));
00457    TGCompositeFrame::AddFrame(fSplitter, new TGLayoutHints(kLHintsLeft | 
00458                               kLHintsTop | kLHintsExpandY));
00459    TGCompositeFrame::AddFrame(fSecond, new TGLayoutHints(kLHintsExpandX | 
00460                               kLHintsExpandY));
00461 }
00462 
00463 //______________________________________________________________________________
00464 void TGSplitFrame::MapToSPlitTool(TGSplitFrame *top)
00465 {
00466    // Map this split frame in the small overview tooltip.
00467 
00468    Int_t px = 0, py = 0;
00469    Int_t rx = 0, ry = 0;
00470    Int_t cx, cy, cw, ch;
00471    Window_t wtarget;
00472    if (!fFirst && !fSecond) {
00473       TGSplitFrame *parent = dynamic_cast<TGSplitFrame *>((TGFrame *)fParent);
00474       if (parent && parent->fSecond == this) {
00475          if (parent->GetOptions() & kVerticalFrame)
00476             ry = parent->GetFirst()->GetHeight();
00477          if (parent->GetOptions() & kHorizontalFrame)
00478             rx = parent->GetFirst()->GetWidth();
00479       }
00480       gVirtualX->TranslateCoordinates(GetId(), top->GetId(), 
00481                                       fX, fY, px, py, wtarget);
00482       cx = ((px-rx)/10)+2;
00483       cy = ((py-ry)/10)+2;
00484       cw = (fWidth/10)-4;
00485       ch = (fHeight/10)-4;
00486       top->GetSplitTool()->AddRectangle(this, cx, cy, cw, ch);
00487       return;
00488    }
00489    if (fFirst)
00490       fFirst->MapToSPlitTool(top);
00491    if (fSecond)
00492       fSecond->MapToSPlitTool(top);
00493 }
00494 
00495 //______________________________________________________________________________
00496 void TGSplitFrame::OnSplitterClicked(Event_t *event)
00497 {
00498    // Handle mouse click events on the splitter.
00499 
00500    Int_t    px = 0, py = 0;
00501    Window_t wtarget;
00502    if (event->fType != kButtonPress)
00503       return;
00504    if (event->fCode != kButton3)
00505       return;
00506    gVirtualX->TranslateCoordinates(event->fWindow,
00507                                    gClient->GetDefaultRoot()->GetId(), 
00508                                    event->fX, event->fY, px, py, wtarget);
00509    TGSplitFrame *top = GetTopFrame();
00510    top->GetSplitTool()->Reset();
00511    top->GetSplitTool()->Resize(1+top->GetWidth()/10, 1+top->GetHeight()/10);
00512    top->MapToSPlitTool(top);
00513    top->GetSplitTool()->Show(px, py);
00514 }
00515 
00516 //______________________________________________________________________________
00517 void TGSplitFrame::SplitHor()
00518 {
00519    // Horizontally split the frame, and if it contains a child frame, ask 
00520    // the user where to keep it (top or bottom). This is the method used 
00521    // via the context menu.
00522 
00523    char side[200];
00524    snprintf(side, 200, "top");
00525    if (fFrame) {
00526       new TGInputDialog(gClient->GetRoot(), GetTopFrame(),
00527                "In which side the actual frame has to be kept (top / bottom)", 
00528                side, side);
00529       if ( strcmp(side, "") == 0 )  // Cancel button was pressed
00530          return;
00531    }
00532    SplitHorizontal(side);
00533 }
00534 
00535 //______________________________________________________________________________
00536 void TGSplitFrame::SplitHorizontal(const char *side)
00537 {
00538    // Horizontally split the frame, and if it contains a child frame, ask 
00539    // the user where to keep it (top or bottom). This method is the actual
00540    // implementation.
00541 
00542    if (fFrame) {
00543       TGFrame *frame = fFrame;
00544       frame->UnmapWindow();
00545       frame->ReparentWindow(gClient->GetDefaultRoot());
00546       RemoveFrame(fFrame);
00547       HSplit();
00548       if (!strcmp(side, "top")) {
00549          frame->ReparentWindow(GetFirst());
00550          GetFirst()->AddFrame(frame, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
00551       }
00552       else if (!strcmp(side, "bottom")) {
00553          frame->ReparentWindow(GetSecond());
00554          GetSecond()->AddFrame(frame, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
00555       }
00556    }
00557    else {
00558       HSplit();
00559    }
00560    MapSubwindows();
00561    Layout();
00562 }
00563 
00564 //______________________________________________________________________________
00565 void TGSplitFrame::SplitVer()
00566 {
00567    // Vertically split the frame, and if it contains a child frame, ask 
00568    // the user where to keep it (left or right). This is the method used 
00569    // via the context menu.
00570 
00571    char side[200];
00572    snprintf(side, 200, "left");
00573    if (fFrame) {
00574       new TGInputDialog(gClient->GetRoot(), GetTopFrame(),
00575                "In which side the actual frame has to be kept (left / right)", 
00576                side, side);
00577       if ( strcmp(side, "") == 0 )  // Cancel button was pressed
00578          return;
00579    }
00580    SplitVertical(side);
00581 }
00582 
00583 //______________________________________________________________________________
00584 void TGSplitFrame::SplitVertical(const char *side)
00585 {
00586    // Vertically split the frame, and if it contains a child frame, ask 
00587    // the user where to keep it (left or right). This method is the actual
00588    // implementation.
00589 
00590    if (fFrame) {
00591       TGFrame *frame = fFrame;
00592       frame->UnmapWindow();
00593       frame->ReparentWindow(gClient->GetDefaultRoot());
00594       RemoveFrame(fFrame);
00595       VSplit();
00596       if (!strcmp(side, "left")) {
00597          frame->ReparentWindow(GetFirst());
00598          GetFirst()->AddFrame(frame, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
00599       }
00600       else if (!strcmp(side, "right")) {
00601          frame->ReparentWindow(GetSecond());
00602          GetSecond()->AddFrame(frame, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
00603       }
00604    }
00605    else {
00606       VSplit();
00607    }
00608    MapSubwindows();
00609    Layout();
00610 }
00611 
00612 //______________________________________________________________________________
00613 void TGSplitFrame::SwallowBack()
00614 {
00615    // Swallow back the child frame previously extracted, and close its
00616    // parent (transient frame).
00617 
00618    if (!fUndocked) {
00619       fUndocked = dynamic_cast<TGTransientFrame *>((TQObject*)gTQSender);
00620    }
00621    if (fUndocked) {
00622       TGFrameElement *el = dynamic_cast<TGFrameElement*>(fUndocked->GetList()->First());
00623       if (!el || !el->fFrame) return;
00624       TGSplitFrame *frame = (TGSplitFrame *)el->fFrame;
00625       frame->UnmapWindow();
00626       fUndocked->RemoveFrame(frame);
00627       frame->ReparentWindow(this);
00628       AddFrame(frame, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
00629       // Layout...
00630       MapSubwindows();
00631       Layout();
00632       fUndocked->CloseWindow();
00633       fUndocked = 0;
00634       Docked(frame);
00635    }
00636 }
00637 
00638 //______________________________________________________________________________
00639 void TGSplitFrame::SwitchFrames(TGFrame *frame, TGCompositeFrame *dest,
00640                                 TGFrame *prev)
00641 {
00642    // Switch (exchange) two frames.
00643    // frame is the source, dest is the destination (the new parent)
00644    // prev is the frame that has to be exchanged with the source 
00645    // (the one actually in the destination)
00646 
00647    // get parent of the source (its container)
00648    TGCompositeFrame *parent = (TGCompositeFrame *)frame->GetParent();
00649 
00650    // unmap the window (to avoid flickering)
00651    prev->UnmapWindow();
00652    // remove it from the destination frame
00653    dest->RemoveFrame(prev);
00654    // temporary reparent it to root (desktop window)
00655    prev->ReparentWindow(gClient->GetDefaultRoot());
00656 
00657    // now unmap the source window (still to avoid flickering)
00658    frame->UnmapWindow();
00659    // remove it from its parent (its container)
00660    parent->RemoveFrame(frame);
00661    // reparent it to the target location
00662    frame->ReparentWindow(dest);
00663    // add it to its new parent (for layout managment)
00664    dest->AddFrame(frame, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
00665    // Layout...
00666    frame->Resize(dest->GetDefaultSize());
00667    dest->MapSubwindows();
00668    dest->Layout();
00669 
00670    // now put back the previous one in the previous source parent
00671    // reparent to the previous source container
00672    prev->ReparentWindow(parent);
00673    // add it to the frame (for layout managment)
00674    parent->AddFrame(prev, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
00675    // Layout...
00676    prev->Resize(parent->GetDefaultSize());
00677    parent->MapSubwindows();
00678    parent->Layout();
00679 }
00680 
00681 //______________________________________________________________________________
00682 void TGSplitFrame::SwitchToMain()
00683 {
00684    // Switch the actual embedded frame to the main (first) split frame.
00685 
00686    TGFrame *source = fFrame;
00687    TGSplitFrame *dest = GetTopFrame()->GetFirst();
00688    TGFrame *prev = (TGFrame *)(dest->GetFrame());
00689    if ((source != prev) && (source != dest))
00690       SwitchFrames(source, dest, prev);
00691 }
00692 
00693 //______________________________________________________________________________
00694 void TGSplitFrame::Undocked(TGFrame* frame)
00695 {
00696    // Emit Undocked() signal.
00697 
00698    Emit("Undocked(TGFrame*)", (Long_t)frame);
00699 }
00700 
00701 //______________________________________________________________________________
00702 void TGSplitFrame::UnSplit(const char *which)
00703 {
00704    // Close (unmap and remove from the list of frames) the frame contained in
00705    // this split frame.
00706 
00707    TGCompositeFrame *keepframe = 0;
00708    TGSplitFrame *kframe = 0, *dframe = 0;
00709    if (!strcmp(which, "first")) {
00710       dframe = GetFirst();
00711       kframe = GetSecond();
00712    }
00713    else if (!strcmp(which, "second")) {
00714       dframe = GetSecond();
00715       kframe = GetFirst();
00716    }
00717    if (!kframe || !dframe)
00718       return;
00719    keepframe = (TGCompositeFrame *)kframe->GetFrame();
00720    if (keepframe) {
00721       keepframe->UnmapWindow();
00722       keepframe->ReparentWindow(gClient->GetDefaultRoot());
00723       kframe->RemoveFrame(keepframe);
00724    }
00725    Cleanup();
00726    if (keepframe) {
00727       keepframe->ReparentWindow(this);
00728       AddFrame(keepframe, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
00729    }
00730    MapSubwindows();
00731    Layout();
00732 }
00733 
00734 //______________________________________________________________________________
00735 void TGSplitFrame::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
00736 {
00737    // Save a splittable frame as a C++ statement(s) on output stream out.
00738 
00739    if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);
00740 
00741    out << endl << "   // splittable frame" << endl;
00742    out << "   TGSplitFrame *";
00743    out << GetName() << " = new TGSplitFrame(" << fParent->GetName()
00744        << "," << GetWidth() << "," << GetHeight();
00745 
00746    if (fBackground == GetDefaultFrameBackground()) {
00747       if (!GetOptions()) {
00748          out << ");" << endl;
00749       } else {
00750          out << "," << GetOptionString() <<");" << endl;
00751       }
00752    } else {
00753       out << "," << GetOptionString() << ",ucolor);" << endl;
00754    }
00755    if (option && strstr(option, "keep_names"))
00756       out << "   " << GetName() << "->SetName(\"" << GetName() << "\");" << endl;
00757 
00758    // setting layout manager if it differs from the main frame type
00759    TGLayoutManager * lm = GetLayoutManager();
00760    if ((GetOptions() & kHorizontalFrame) &&
00761        (lm->InheritsFrom(TGHorizontalLayout::Class()))) {
00762       ;
00763    } else if ((GetOptions() & kVerticalFrame) &&
00764               (lm->InheritsFrom(TGVerticalLayout::Class()))) {
00765       ;
00766    } else {
00767       out << "   " << GetName() <<"->SetLayoutManager(";
00768       lm->SavePrimitive(out, option);
00769       out << ");"<< endl;
00770    }
00771 
00772    SavePrimitiveSubframes(out, option);
00773 }

Generated on Tue Jul 5 14:22:03 2011 for ROOT_528-00b_version by  doxygen 1.5.1