27 ClassImp(TGSplitTool);
28 ClassImp(TGSplitFrame);
34 TGSplitTool::TGSplitTool(
const TGWindow *p,
const TGFrame *f)
35 : TGCompositeFrame(p, 10, 10, kHorizontalFrame | kRaisedFrame | kFixedSize)
37 SetWindowAttributes_t attr;
38 attr.fMask = kWAOverrideRedirect | kWASaveUnder;
39 attr.fOverrideRedirect = kTRUE;
40 attr.fSaveUnder = kTRUE;
42 gVirtualX->ChangeWindowAttributes(fId, &attr);
43 SetBackgroundColor(fClient->GetResourcePool()->GetTipBgndColor());
45 fRectGC.SetFillStyle(kFillSolid);
46 fRectGC.SetForeground(0x99ff99);
48 TClass *cl = TClass::GetClass(
"TGSplitFrame");
49 cl->MakeCustomMenuList();
50 TList *ml = cl->GetMenuList();
51 ((TClassMenuItem *)ml->At(1))->SetTitle(
"Cleanup Frame");
52 ((TClassMenuItem *)ml->At(2))->SetTitle(
"Close and Collapse");
53 ((TClassMenuItem *)ml->At(3))->SetTitle(
"Undock Frame");
54 ((TClassMenuItem *)ml->At(4))->SetTitle(
"Dock Frame Back");
55 ((TClassMenuItem *)ml->At(5))->SetTitle(
"Switch to Main");
56 ((TClassMenuItem *)ml->At(6))->SetTitle(
"Horizontally Split...");
57 ((TClassMenuItem *)ml->At(7))->SetTitle(
"Vertically Split...");
58 fContextMenu =
new TContextMenu(
"SplitFrameContextMenu",
"Actions");
60 fMap.SetOwnerValue(kFALSE);
62 if (f) Resize(f->GetWidth()/10, f->GetHeight()/10);
63 AddInput(kButtonPressMask | kButtonReleaseMask | kPointerMotionMask);
72 TGSplitTool::~TGSplitTool()
81 void TGSplitTool::AddRectangle(TGFrame *frame, Int_t x, Int_t y, Int_t w, Int_t h)
83 TGRectMap *rect =
new TGRectMap(x, y, w, h);
84 fMap.Add(rect, frame);
90 void TGSplitTool::DoRedraw()
94 while ((rect = (TGRectMap*)next())) {
95 gVirtualX->FillRectangle(fId, GetBckgndGC()(), rect->fX,
96 rect->fY, rect->fW, rect->fH);
97 gVirtualX->DrawRectangle(fId, GetBlackGC()(), rect->fX, rect->fY,
106 void TGSplitTool::DrawBorder()
108 gVirtualX->DrawLine(fId, GetShadowGC()(), 0, 0, fWidth-2, 0);
109 gVirtualX->DrawLine(fId, GetShadowGC()(), 0, 0, 0, fHeight-2);
110 gVirtualX->DrawLine(fId, GetBlackGC()(), 0, fHeight-1, fWidth-1, fHeight-1);
111 gVirtualX->DrawLine(fId, GetBlackGC()(), fWidth-1, fHeight-1, fWidth-1, 0);
117 Bool_t TGSplitTool::HandleButton(Event_t *event)
119 if (event->fType != kButtonPress)
121 Int_t px = 0, py = 0;
124 TGSplitFrame *frm = 0;
125 TMapIter next(&fMap);
126 while ((rect = (TGRectMap*)next())) {
127 if (rect->Contains(event->fX, event->fY)) {
128 frm = (TGSplitFrame *)fMap.GetValue((
const TObject *)rect);
129 gVirtualX->TranslateCoordinates(event->fWindow,
130 gClient->GetDefaultRoot()->GetId(),
131 event->fX,
event->fY, px, py, wtarget);
132 fContextMenu->Popup(px, py, frm);
135 TRootContextMenu *menu = ((TRootContextMenu *)fContextMenu->GetContextMenuImp());
136 ((TGPopupMenu *)menu)->Connect(
"PoppedDown()",
"TGSplitTool",
this,
"Hide()");
147 Bool_t TGSplitTool::HandleMotion(Event_t *event)
149 static TGRectMap *rect = 0, *oldrect = 0;
150 TMapIter next(&fMap);
151 while ((rect = (TGRectMap*)next())) {
152 if (rect->Contains(event->fX, event->fY)) {
154 if (rect != oldrect) {
156 gVirtualX->FillRectangle(fId, GetBckgndGC()(), oldrect->fX,
157 oldrect->fY, oldrect->fW, oldrect->fH);
158 gVirtualX->DrawRectangle(fId, GetBlackGC()(), oldrect->fX, oldrect->fY,
159 oldrect->fW, oldrect->fH);
161 gVirtualX->FillRectangle(fId, fRectGC(), rect->fX, rect->fY, rect->fW,
163 gVirtualX->DrawRectangle(fId, GetBlackGC()(), rect->fX, rect->fY,
171 gVirtualX->FillRectangle(fId, GetBckgndGC()(), oldrect->fX,
172 oldrect->fY, oldrect->fW, oldrect->fH);
173 gVirtualX->DrawRectangle(fId, GetBlackGC()(), oldrect->fX, oldrect->fY,
174 oldrect->fW, oldrect->fH);
181 void TGSplitTool::Hide()
183 gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
192 void TGSplitTool::Reset()
202 void TGSplitTool::SetPosition(Int_t x, Int_t y)
213 if (fX > (Int_t) fWindow->GetWidth())
214 fX = fWindow->GetWidth();
215 if (fY > (Int_t) fWindow->GetHeight())
216 fY = fWindow->GetHeight();
223 void TGSplitTool::Show(Int_t x, Int_t y)
230 gVirtualX->GrabPointer(fId, kButtonPressMask | kPointerMotionMask, kNone,
231 fClient->GetResourcePool()->GetGrabCursor(),
241 TGSplitFrame::TGSplitFrame(
const TGWindow *p, UInt_t w, UInt_t h,
242 UInt_t options) : TGCompositeFrame(p, w, h, options),
243 fFrame(0), fSplitter(0), fFirst(0), fSecond(0)
245 fSplitTool =
new TGSplitTool(gClient->GetDefaultRoot(),
this);
246 fHRatio = fWRatio = 0.0;
248 AddInput(kStructureNotifyMask);
249 SetCleanup(kLocalCleanup);
255 TGSplitFrame::~TGSplitFrame()
264 void TGSplitFrame::AddFrame(TGFrame *f, TGLayoutHints *l)
266 TGCompositeFrame::AddFrame(f, l);
273 void TGSplitFrame::RemoveFrame(TGFrame *f)
275 TGCompositeFrame::RemoveFrame(f);
283 void TGSplitFrame::Cleanup()
285 TGCompositeFrame::Cleanup();
295 TGSplitFrame *TGSplitFrame::GetTopFrame()
297 TGSplitFrame *top =
this;
298 TGWindow *w = (TGWindow *)GetParent();
299 TGSplitFrame *p =
dynamic_cast<TGSplitFrame *
>(w);
302 w = (TGWindow *)p->GetParent();
303 p =
dynamic_cast<TGSplitFrame *
>(w);
312 void TGSplitFrame::Close()
315 fFrame->UnmapWindow();
325 void TGSplitFrame::CloseAndCollapse()
327 if (!fSplitter || !fFirst || !fSecond) {
328 TGSplitFrame *parent = (TGSplitFrame *)GetParent();
329 if (parent->GetFirst() && parent->GetSecond()) {
330 if (parent->GetFirst() ==
this)
331 parent->UnSplit(
"first");
332 else if (parent->GetSecond() ==
this)
333 parent->UnSplit(
"second");
340 void TGSplitFrame::Docked(TGFrame* frame)
342 Emit(
"Docked(TGFrame*)", (Long_t)frame);
350 void TGSplitFrame::ExtractFrame()
353 fFrame->UnmapWindow();
354 fUndocked =
new TGTransientFrame(gClient->GetDefaultRoot(), GetMainFrame(), 800, 600);
355 fFrame->ReparentWindow(fUndocked);
356 fUndocked->AddFrame(fFrame,
new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
358 fUndocked->MapSubwindows();
360 fUndocked->MapWindow();
362 fUndocked->Connect(
"CloseWindow()",
"TGSplitFrame",
this,
"SwallowBack()");
372 Bool_t TGSplitFrame::HandleConfigureNotify(Event_t *)
376 TGWindow *w = (TGWindow *)GetParent();
377 TGSplitFrame *p =
dynamic_cast<TGSplitFrame *
>(w);
381 Float_t hratio = (Float_t)p->GetFirst()->GetHeight() / (Float_t)p->GetHeight();
382 Float_t wratio = (Float_t)p->GetFirst()->GetWidth() / (Float_t)p->GetWidth();
383 p->SetHRatio(hratio);
384 p->SetWRatio(wratio);
390 if ((fHRatio > 0.0) && (fWRatio > 0.0)) {
391 Float_t h = fHRatio * (Float_t)GetHeight();
392 fFirst->SetHeight((UInt_t)h);
393 Float_t w = fWRatio * (Float_t)GetWidth();
394 fFirst->SetWidth((UInt_t)w);
397 fHRatio = (Float_t)fFirst->GetHeight() / (Float_t)GetHeight();
398 fWRatio = (Float_t)fFirst->GetWidth() / (Float_t)GetWidth();
399 fClient->NeedRedraw(
this);
400 if (!gVirtualX->InheritsFrom(
"TGX11"))
408 void TGSplitFrame::HSplit(UInt_t h)
411 if ((fSplitter != 0) || (fFirst != 0) || (fSecond != 0) || (fFrame != 0))
413 UInt_t height = (h > 0) ? h : fHeight/2;
415 ChangeOptions((GetOptions() & ~kHorizontalFrame) | kVerticalFrame);
417 fFirst =
new TGSplitFrame(
this, fWidth, height, kSunkenFrame | kFixedHeight);
419 fSecond =
new TGSplitFrame(
this, fWidth, height, kSunkenFrame);
421 fSplitter =
new TGHSplitter(
this, 4, 4);
423 fSplitter->SetFrame(fFirst, kTRUE);
424 fSplitter->Connect(
"ProcessedEvent(Event_t*)",
"TGSplitFrame",
this,
425 "OnSplitterClicked(Event_t*)");
427 TGCompositeFrame::AddFrame(fFirst,
new TGLayoutHints(kLHintsExpandX));
428 TGCompositeFrame::AddFrame(fSplitter,
new TGLayoutHints(kLHintsLeft |
429 kLHintsTop | kLHintsExpandX));
430 TGCompositeFrame::AddFrame(fSecond,
new TGLayoutHints(kLHintsExpandX |
437 void TGSplitFrame::VSplit(UInt_t w)
440 if ((fSplitter != 0) || (fFirst != 0) || (fSecond != 0) || (fFrame != 0))
442 UInt_t width = (w > 0) ? w : fWidth/2;
444 ChangeOptions((GetOptions() & ~kVerticalFrame) | kHorizontalFrame);
446 fFirst =
new TGSplitFrame(
this, width, fHeight, kSunkenFrame | kFixedWidth);
448 fSecond =
new TGSplitFrame(
this, width, fHeight, kSunkenFrame);
450 fSplitter =
new TGVSplitter(
this, 4, 4);
452 fSplitter->SetFrame(fFirst, kTRUE);
453 fSplitter->Connect(
"ProcessedEvent(Event_t*)",
"TGSplitFrame",
this,
454 "OnSplitterClicked(Event_t*)");
456 TGCompositeFrame::AddFrame(fFirst,
new TGLayoutHints(kLHintsExpandY));
457 TGCompositeFrame::AddFrame(fSplitter,
new TGLayoutHints(kLHintsLeft |
458 kLHintsTop | kLHintsExpandY));
459 TGCompositeFrame::AddFrame(fSecond,
new TGLayoutHints(kLHintsExpandX |
466 void TGSplitFrame::MapToSPlitTool(TGSplitFrame *top)
468 Int_t px = 0, py = 0;
469 Int_t rx = 0, ry = 0;
470 Int_t cx, cy, cw, ch;
472 if (!fFirst && !fSecond) {
473 TGSplitFrame *parent =
dynamic_cast<TGSplitFrame *
>((TGFrame *)fParent);
474 if (parent && parent->fSecond ==
this) {
475 if (parent->GetOptions() & kVerticalFrame)
476 ry = parent->GetFirst()->GetHeight();
477 if (parent->GetOptions() & kHorizontalFrame)
478 rx = parent->GetFirst()->GetWidth();
480 gVirtualX->TranslateCoordinates(GetId(), top->GetId(),
481 fX, fY, px, py, wtarget);
486 top->GetSplitTool()->AddRectangle(
this, cx, cy, cw, ch);
490 fFirst->MapToSPlitTool(top);
492 fSecond->MapToSPlitTool(top);
498 void TGSplitFrame::OnSplitterClicked(Event_t *event)
500 Int_t px = 0, py = 0;
502 if (event->fType != kButtonPress)
504 if (event->fCode != kButton3)
506 gVirtualX->TranslateCoordinates(event->fWindow,
507 gClient->GetDefaultRoot()->GetId(),
508 event->fX,
event->fY, px, py, wtarget);
509 TGSplitFrame *top = GetTopFrame();
510 top->GetSplitTool()->Reset();
511 top->GetSplitTool()->Resize(1+top->GetWidth()/10, 1+top->GetHeight()/10);
512 top->MapToSPlitTool(top);
513 top->GetSplitTool()->Show(px, py);
521 void TGSplitFrame::SplitHor()
524 snprintf(side, 200,
"top");
526 new TGInputDialog(gClient->GetRoot(), GetTopFrame(),
527 "In which side the actual frame has to be kept (top / bottom)",
529 if ( strcmp(side,
"") == 0 )
532 SplitHorizontal(side);
540 void TGSplitFrame::SplitHorizontal(
const char *side)
543 TGFrame *frame = fFrame;
544 frame->UnmapWindow();
545 frame->ReparentWindow(gClient->GetDefaultRoot());
548 if (!strcmp(side,
"top")) {
549 frame->ReparentWindow(GetFirst());
550 GetFirst()->AddFrame(frame,
new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
552 else if (!strcmp(side,
"bottom")) {
553 frame->ReparentWindow(GetSecond());
554 GetSecond()->AddFrame(frame,
new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
569 void TGSplitFrame::SplitVer()
572 snprintf(side, 200,
"left");
574 new TGInputDialog(gClient->GetRoot(), GetTopFrame(),
575 "In which side the actual frame has to be kept (left / right)",
577 if ( strcmp(side,
"") == 0 )
588 void TGSplitFrame::SplitVertical(
const char *side)
591 TGFrame *frame = fFrame;
592 frame->UnmapWindow();
593 frame->ReparentWindow(gClient->GetDefaultRoot());
596 if (!strcmp(side,
"left")) {
597 frame->ReparentWindow(GetFirst());
598 GetFirst()->AddFrame(frame,
new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
600 else if (!strcmp(side,
"right")) {
601 frame->ReparentWindow(GetSecond());
602 GetSecond()->AddFrame(frame,
new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
616 void TGSplitFrame::SwallowBack()
619 fUndocked =
dynamic_cast<TGTransientFrame *
>((TQObject*)gTQSender);
622 TGFrameElement *el =
dynamic_cast<TGFrameElement*
>(fUndocked->GetList()->First());
623 if (!el || !el->fFrame)
return;
624 TGSplitFrame *frame = (TGSplitFrame *)el->fFrame;
625 frame->UnmapWindow();
626 fUndocked->RemoveFrame(frame);
627 frame->ReparentWindow(
this);
628 AddFrame(frame,
new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
632 fUndocked->CloseWindow();
644 void TGSplitFrame::SwitchFrames(TGFrame *frame, TGCompositeFrame *dest,
648 TGCompositeFrame *parent = (TGCompositeFrame *)frame->GetParent();
653 dest->RemoveFrame(prev);
655 prev->ReparentWindow(gClient->GetDefaultRoot());
658 frame->UnmapWindow();
660 parent->RemoveFrame(frame);
662 frame->ReparentWindow(dest);
664 dest->AddFrame(frame,
new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
666 frame->Resize(dest->GetDefaultSize());
667 dest->MapSubwindows();
672 prev->ReparentWindow(parent);
674 parent->AddFrame(prev,
new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
676 prev->Resize(parent->GetDefaultSize());
677 parent->MapSubwindows();
684 void TGSplitFrame::SwitchToMain()
686 TGFrame *source = fFrame;
687 TGSplitFrame *dest = GetTopFrame()->GetFirst();
688 TGFrame *prev = (TGFrame *)(dest->GetFrame());
689 if ((source != prev) && (source != dest))
690 SwitchFrames(source, dest, prev);
696 void TGSplitFrame::Undocked(TGFrame* frame)
698 Emit(
"Undocked(TGFrame*)", (Long_t)frame);
705 void TGSplitFrame::UnSplit(
const char *which)
707 TGCompositeFrame *keepframe = 0;
708 TGSplitFrame *kframe = 0, *dframe = 0;
709 if (!strcmp(which,
"first")) {
711 kframe = GetSecond();
713 else if (!strcmp(which,
"second")) {
714 dframe = GetSecond();
717 if (!kframe || !dframe)
719 keepframe = (TGCompositeFrame *)kframe->GetFrame();
721 keepframe->UnmapWindow();
722 keepframe->ReparentWindow(gClient->GetDefaultRoot());
723 kframe->RemoveFrame(keepframe);
727 keepframe->ReparentWindow(
this);
728 AddFrame(keepframe,
new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
737 void TGSplitFrame::SavePrimitive(std::ostream &out, Option_t *option )
739 if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);
741 out << std::endl <<
" // splittable frame" << std::endl;
742 out <<
" TGSplitFrame *";
743 out << GetName() <<
" = new TGSplitFrame(" << fParent->GetName()
744 <<
"," << GetWidth() <<
"," << GetHeight();
746 if (fBackground == GetDefaultFrameBackground()) {
748 out <<
");" << std::endl;
750 out <<
"," << GetOptionString() <<
");" << std::endl;
753 out <<
"," << GetOptionString() <<
",ucolor);" << std::endl;
755 if (option && strstr(option,
"keep_names"))
756 out <<
" " << GetName() <<
"->SetName(\"" << GetName() <<
"\");" << std::endl;
761 TGLayoutManager * lm = GetLayoutManager();
762 if ((GetOptions() & kHorizontalFrame) &&
763 (lm->InheritsFrom(TGHorizontalLayout::Class()))) {
765 }
else if ((GetOptions() & kVerticalFrame) &&
766 (lm->InheritsFrom(TGVerticalLayout::Class()))) {
769 out <<
" " << GetName() <<
"->SetLayoutManager(";
770 lm->SavePrimitive(out, option);
771 out <<
");"<< std::endl;
774 SavePrimitiveSubframes(out, option);