00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <stdlib.h>
00041
00042 #include "TROOT.h"
00043 #include "TGListTree.h"
00044 #include "TGPicture.h"
00045 #include "TGCanvas.h"
00046 #include "TGScrollBar.h"
00047 #include "TGToolTip.h"
00048 #include "KeySymbols.h"
00049 #include "TGTextEditDialogs.h"
00050 #include "TGResourcePool.h"
00051 #include "TGMsgBox.h"
00052 #include "TError.h"
00053 #include "TColor.h"
00054 #include "TSystem.h"
00055 #include "TString.h"
00056 #include "TObjString.h"
00057 #include "TGDNDManager.h"
00058 #include "TBufferFile.h"
00059 #include "Riostream.h"
00060
00061 Pixel_t TGListTree::fgGrayPixel = 0;
00062 const TGFont *TGListTree::fgDefaultFont = 0;
00063 TGGC *TGListTree::fgDrawGC = 0;
00064 TGGC *TGListTree::fgLineGC = 0;
00065 TGGC *TGListTree::fgHighlightGC = 0;
00066 TGGC *TGListTree::fgColorGC = 0;
00067 const TGPicture *TGListTree::fgOpenPic = 0;
00068 const TGPicture *TGListTree::fgClosedPic = 0;
00069 const TGPicture *TGListTree::fgCheckedPic = 0;
00070 const TGPicture *TGListTree::fgUncheckedPic = 0;
00071
00072
00073 ClassImp(TGListTreeItem)
00074 ClassImp(TGListTreeItemStd)
00075 ClassImp(TGListTree)
00076
00077
00078
00079
00080
00081
00082
00083 TGListTreeItem::TGListTreeItem(TGClient *client) :
00084 fClient(client),
00085 fParent (0), fFirstchild(0), fLastchild (0), fPrevsibling(0),
00086 fNextsibling(0),fOpen (kFALSE), fDNDState (0),
00087 fY (0), fXtext (0), fYtext(0), fHeight(0)
00088 {
00089
00090 }
00091
00092
00093 UInt_t TGListTreeItem::GetPicWidth() const
00094 {
00095
00096
00097 return GetPicture()->GetWidth();
00098 }
00099
00100
00101
00102
00103
00104
00105
00106 TGListTreeItemStd::TGListTreeItemStd(TGClient *client, const char *name,
00107 const TGPicture *opened,
00108 const TGPicture *closed,
00109 Bool_t checkbox) :
00110 TGListTreeItem(client)
00111 {
00112
00113
00114 fText = name;
00115 fCheckBox = checkbox;
00116 fChecked = kTRUE;
00117
00118 if (!opened)
00119 opened = TGListTree::GetOpenPic();
00120 else
00121 ((TGPicture *)opened)->AddReference();
00122
00123 if (!closed)
00124 closed = TGListTree::GetClosedPic();
00125 else
00126 ((TGPicture *)closed)->AddReference();
00127
00128 fOpenPic = opened;
00129 fClosedPic = closed;
00130
00131 fCheckedPic = TGListTree::GetCheckedPic();
00132 fUncheckedPic = TGListTree::GetUncheckedPic();
00133
00134 fActive = kFALSE;
00135
00136 fOwnsData = kFALSE;
00137 fUserData = 0;
00138
00139 fHasColor = kFALSE;
00140 fColor = 0;
00141 fDNDState = 0;
00142 }
00143
00144
00145 TGListTreeItemStd::~TGListTreeItemStd()
00146 {
00147
00148
00149 if (fOwnsData && fUserData) {
00150 TObject *obj = static_cast<TObject *>(fUserData);
00151 delete dynamic_cast<TObject *>(obj);
00152 }
00153 fClient->FreePicture(fOpenPic);
00154 fClient->FreePicture(fClosedPic);
00155 fClient->FreePicture(fCheckedPic);
00156 fClient->FreePicture(fUncheckedPic);
00157 }
00158
00159
00160 Pixel_t TGListTreeItemStd::GetActiveColor() const
00161 {
00162
00163
00164 return TGFrame::GetDefaultSelectedBackground();
00165 }
00166
00167
00168 Bool_t TGListTreeItemStd::HasCheckedChild(Bool_t first)
00169 {
00170
00171
00172 TGListTreeItem *item = this;
00173
00174 while (item) {
00175 if (item->IsChecked()) {
00176 return kTRUE;
00177 }
00178 if (item->GetFirstChild()) {
00179 if (item->GetFirstChild()->HasCheckedChild())
00180 return kTRUE;
00181 }
00182 if (!first)
00183 item = item->GetNextSibling();
00184 else
00185 break;
00186 }
00187 return kFALSE;
00188 }
00189
00190
00191 Bool_t TGListTreeItemStd::HasUnCheckedChild(Bool_t first)
00192 {
00193
00194
00195 TGListTreeItem *item = this;
00196
00197 while (item) {
00198 if (!item->IsChecked()) {
00199 return kTRUE;
00200 }
00201 if (item->GetFirstChild()) {
00202 if (item->GetFirstChild()->HasUnCheckedChild())
00203 return kTRUE;
00204 }
00205 if (!first)
00206 item = item->GetNextSibling();
00207 else
00208 break;
00209 }
00210 return kFALSE;
00211 }
00212
00213
00214 void TGListTreeItemStd::UpdateState()
00215 {
00216
00217
00218 if ((!fChecked && HasCheckedChild(kTRUE)) ||
00219 (fChecked && HasUnCheckedChild(kTRUE))) {
00220 SetCheckBoxPictures(gClient->GetPicture("checked_dis_t.xpm"),
00221 gClient->GetPicture("unchecked_dis_t.xpm"));
00222 }
00223 else {
00224 SetCheckBoxPictures(gClient->GetPicture("checked_t.xpm"),
00225 gClient->GetPicture("unchecked_t.xpm"));
00226 }
00227 }
00228
00229
00230 void TGListTreeItemStd::CheckAllChildren(Bool_t state)
00231 {
00232
00233
00234
00235 if (state) {
00236 if (!IsChecked())
00237 CheckItem();
00238 } else {
00239 if (IsChecked())
00240 Toggle();
00241 }
00242 CheckChildren(GetFirstChild(), state);
00243 UpdateState();
00244 }
00245
00246
00247 void TGListTreeItemStd::CheckChildren(TGListTreeItem *item, Bool_t state)
00248 {
00249
00250
00251
00252 if (!item) return;
00253
00254 while (item) {
00255 if (state){
00256 if (!item->IsChecked())
00257 item->CheckItem();
00258 } else {
00259 if (item->IsChecked())
00260 item->Toggle();
00261 }
00262 if (item->GetFirstChild()) {
00263 CheckChildren(item->GetFirstChild(), state);
00264 }
00265 item->UpdateState();
00266 item = item->GetNextSibling();
00267 }
00268 }
00269
00270
00271 void TGListTreeItemStd::SetCheckBox(Bool_t on)
00272 {
00273
00274
00275 fCheckBox = on;
00276 }
00277
00278
00279 void TGListTreeItemStd::SetCheckBoxPictures(const TGPicture *checked,
00280 const TGPicture *unchecked)
00281 {
00282
00283
00284 fClient->FreePicture(fCheckedPic);
00285 fClient->FreePicture(fUncheckedPic);
00286
00287 if (!checked) {
00288 ::Warning("TGListTreeItem::SetCheckBoxPictures", "checked picture not specified, defaulting to checked_t");
00289 checked = fClient->GetPicture("checked_t.xpm");
00290 } else
00291 ((TGPicture *)checked)->AddReference();
00292
00293 if (!unchecked) {
00294 ::Warning("TGListTreeItem::SetCheckBoxPictures", "unchecked picture not specified, defaulting to unchecked_t");
00295 unchecked = fClient->GetPicture("unchecked_t.xpm");
00296 } else
00297 ((TGPicture *)unchecked)->AddReference();
00298
00299 fCheckedPic = checked;
00300 fUncheckedPic = unchecked;
00301 }
00302
00303
00304 void TGListTreeItemStd::SetPictures(const TGPicture *opened, const TGPicture *closed)
00305 {
00306
00307
00308 fClient->FreePicture(fOpenPic);
00309 fClient->FreePicture(fClosedPic);
00310
00311 if (!opened) {
00312 ::Warning("TGListTreeItem::SetPictures", "opened picture not specified, defaulting to ofolder_t");
00313 opened = fClient->GetPicture("ofolder_t.xpm");
00314 } else
00315 ((TGPicture *)opened)->AddReference();
00316
00317 if (!closed) {
00318 ::Warning("TGListTreeItem::SetPictures", "closed picture not specified, defaulting to folder_t");
00319 closed = fClient->GetPicture("folder_t.xpm");
00320 } else
00321 ((TGPicture *)closed)->AddReference();
00322
00323 fOpenPic = opened;
00324 fClosedPic = closed;
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334 TGListTree::TGListTree(TGWindow *p, UInt_t w, UInt_t h, UInt_t options,
00335 ULong_t back) :
00336 TGContainer(p, w, h, options, back)
00337 {
00338
00339
00340 fMsgWindow = p;
00341 fCanvas = 0;
00342 fTip = 0;
00343 fTipItem = 0;
00344 fAutoTips = kFALSE;
00345 fAutoCheckBoxPic = kTRUE;
00346 fDisableOpen = kFALSE;
00347 fBdown = kFALSE;
00348 fUserControlled = kFALSE;
00349 fEventHandled = kFALSE;
00350
00351 fGrayPixel = GetGrayPixel();
00352 fFont = GetDefaultFontStruct();
00353
00354 fDrawGC = GetDrawGC()();
00355 fLineGC = GetLineGC()();
00356 fHighlightGC = GetHighlightGC()();
00357 fColorGC = GetColorGC()();
00358
00359 fFirst = fLast = fSelected = fCurrent = fBelowMouse = 0;
00360 fDefw = fDefh = 1;
00361
00362 fHspacing = 2;
00363 fVspacing = 2;
00364 fIndent = 3;
00365 fMargin = 2;
00366
00367 fXDND = fYDND = 0;
00368 fDNDData.fData = 0;
00369 fDNDData.fDataLength = 0;
00370 fDNDData.fDataType = 0;
00371 fBuf = 0;
00372
00373 fColorMode = kDefault;
00374 fCheckMode = kSimple;
00375 if (fCanvas) fCanvas->GetVScrollbar()->SetSmallIncrement(20);
00376
00377 gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
00378 kButtonPressMask | kButtonReleaseMask,
00379 kNone, kNone);
00380
00381 AddInput(kPointerMotionMask | kEnterWindowMask |
00382 kLeaveWindowMask | kKeyPressMask);
00383 SetWindowName();
00384
00385 fDNDTypeList = new Atom_t[3];
00386 fDNDTypeList[0] = gVirtualX->InternAtom("application/root", kFALSE);
00387 fDNDTypeList[1] = gVirtualX->InternAtom("text/uri-list", kFALSE);
00388 fDNDTypeList[2] = 0;
00389 gVirtualX->SetDNDAware(fId, fDNDTypeList);
00390 SetDNDTarget(kTRUE);
00391 fEditDisabled = kEditDisable | kEditDisableGrab | kEditDisableBtnEnable;
00392 }
00393
00394
00395 TGListTree::TGListTree(TGCanvas *p,UInt_t options,ULong_t back) :
00396 TGContainer(p, options, back)
00397 {
00398
00399
00400 fMsgWindow = p;
00401 fTip = 0;
00402 fTipItem = 0;
00403 fAutoTips = kFALSE;
00404 fAutoCheckBoxPic = kTRUE;
00405 fDisableOpen = kFALSE;
00406 fBdown = kFALSE;
00407 fUserControlled = kFALSE;
00408 fEventHandled = kFALSE;
00409
00410 fGrayPixel = GetGrayPixel();
00411 fFont = GetDefaultFontStruct();
00412
00413 fDrawGC = GetDrawGC()();
00414 fLineGC = GetLineGC()();
00415 fHighlightGC = GetHighlightGC()();
00416 fColorGC = GetColorGC()();
00417
00418 fFirst = fLast = fSelected = fCurrent = fBelowMouse = 0;
00419 fDefw = fDefh = 1;
00420
00421 fHspacing = 2;
00422 fVspacing = 2;
00423 fIndent = 3;
00424 fMargin = 2;
00425
00426 fXDND = fYDND = 0;
00427 fDNDData.fData = 0;
00428 fDNDData.fDataLength = 0;
00429 fDNDData.fDataType = 0;
00430 fBuf = 0;
00431
00432 fColorMode = kDefault;
00433 fCheckMode = kSimple;
00434 if (fCanvas) fCanvas->GetVScrollbar()->SetSmallIncrement(20);
00435
00436 gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
00437 kButtonPressMask | kButtonReleaseMask,
00438 kNone, kNone);
00439
00440 AddInput(kPointerMotionMask | kEnterWindowMask |
00441 kLeaveWindowMask | kKeyPressMask);
00442 SetWindowName();
00443
00444 fDNDTypeList = new Atom_t[3];
00445 fDNDTypeList[0] = gVirtualX->InternAtom("application/root", kFALSE);
00446 fDNDTypeList[1] = gVirtualX->InternAtom("text/uri-list", kFALSE);
00447 fDNDTypeList[2] = 0;
00448 gVirtualX->SetDNDAware(fId, fDNDTypeList);
00449 SetDNDTarget(kTRUE);
00450 fEditDisabled = kEditDisable | kEditDisableGrab | kEditDisableBtnEnable;
00451 }
00452
00453
00454 TGListTree::~TGListTree()
00455 {
00456
00457
00458 TGListTreeItem *item, *sibling;
00459
00460 delete [] fDNDTypeList;
00461 delete fTip;
00462
00463 item = fFirst;
00464 while (item) {
00465 PDeleteChildren(item);
00466 sibling = item->fNextsibling;
00467 delete item;
00468 item = sibling;
00469 }
00470 }
00471
00472
00473
00474
00475 Int_t TGListTree::FontHeight()
00476 {
00477
00478
00479 if (!fgDefaultFont)
00480 fgDefaultFont = gClient->GetResourcePool()->GetIconFont();
00481 return fgDefaultFont->TextHeight();
00482 }
00483
00484
00485 Int_t TGListTree::FontAscent()
00486 {
00487
00488
00489 FontMetrics_t m;
00490 if (!fgDefaultFont)
00491 fgDefaultFont = gClient->GetResourcePool()->GetIconFont();
00492 fgDefaultFont->GetFontMetrics(&m);
00493 return m.fAscent;
00494 }
00495
00496
00497 Int_t TGListTree::TextWidth(const char *c)
00498 {
00499
00500
00501 if (!fgDefaultFont)
00502 fgDefaultFont = gClient->GetResourcePool()->GetIconFont();
00503 return fgDefaultFont->TextWidth(c);
00504 }
00505
00506
00507
00508
00509 void TGListTree::HighlightItem(TGListTreeItem *item, Bool_t state, Bool_t draw)
00510 {
00511
00512
00513 if (item) {
00514 if ((item == fSelected) && !state) {
00515 fSelected = 0;
00516 if (draw) DrawItemName(fId, item);
00517 } else if (state != item->IsActive()) {
00518 item->SetActive(state);
00519 if (draw) DrawItemName(fId, item);
00520 }
00521 }
00522 }
00523
00524
00525 void TGListTree::HighlightChildren(TGListTreeItem *item, Bool_t state, Bool_t draw)
00526 {
00527
00528
00529 while (item) {
00530 HighlightItem(item, state, draw);
00531 if (item->fFirstchild)
00532 HighlightChildren(item->fFirstchild, state, (item->IsOpen()) ? draw : kFALSE);
00533 item = item->fNextsibling;
00534 }
00535 }
00536
00537
00538 void TGListTree::UnselectAll(Bool_t draw)
00539 {
00540
00541
00542 ClearViewPort();
00543 HighlightChildren(fFirst, kFALSE, draw);
00544 }
00545
00546
00547 Bool_t TGListTree::HandleButton(Event_t *event)
00548 {
00549
00550
00551 TGListTreeItem *item;
00552
00553 if (fTip) fTip->Hide();
00554
00555 Int_t page = 0;
00556 if (event->fCode == kButton4 || event->fCode == kButton5) {
00557 if (!fCanvas) return kTRUE;
00558 if (fCanvas->GetContainer()->GetHeight()) {
00559
00560
00561
00562
00563 Int_t r = fCanvas->GetViewPort()->GetHeight() / 5;
00564 page = TMath::Min(r, 90);
00565 }
00566 }
00567
00568 if (event->fCode == kButton4) {
00569
00570 Int_t newpos = fCanvas->GetVsbPosition() - page;
00571 if (newpos < 0) newpos = 0;
00572 fCanvas->SetVsbPosition(newpos);
00573 return kTRUE;
00574 }
00575 if (event->fCode == kButton5) {
00576
00577 Int_t newpos = fCanvas->GetVsbPosition() + page;
00578 fCanvas->SetVsbPosition(newpos);
00579 return kTRUE;
00580 }
00581
00582 if (event->fType == kButtonPress) {
00583 if ((item = FindItem(event->fY)) != 0) {
00584 if (event->fCode == kButton1) {
00585 Int_t minx, maxx;
00586 Int_t minxchk = 0, maxxchk = 0;
00587 if (item->HasCheckBox()) {
00588 minxchk = (item->fXtext - item->GetCheckBoxPicture()->GetWidth());
00589 maxxchk = (item->fXtext - 4);
00590 maxx = maxxchk - Int_t(item->GetPicWidth()) - 8;
00591 minx = minxchk - Int_t(item->GetPicWidth()) - 16;
00592 }
00593 else {
00594 maxx = (item->fXtext - Int_t(item->GetPicWidth())) - 8;
00595 minx = (item->fXtext - Int_t(item->GetPicWidth())) - 16;
00596 }
00597 if ((item->HasCheckBox()) && (event->fX < maxxchk) &&
00598 (event->fX > minxchk))
00599 {
00600 ToggleItem(item);
00601 if (fCheckMode == kRecursive) {
00602 CheckAllChildren(item, item->IsChecked());
00603 }
00604 UpdateChecked(item, kTRUE);
00605 Checked((TObject *)item->GetUserData(), item->IsChecked());
00606 return kTRUE;
00607 }
00608 if ((event->fX < maxx) && (event->fX > minx)) {
00609 item->SetOpen(!item->IsOpen());
00610 ClearViewPort();
00611 return kTRUE;
00612 }
00613 }
00614
00615 if (event->fCode == kButton1) {
00616 fXDND = event->fX;
00617 fYDND = event->fY;
00618 fBdown = kTRUE;
00619 }
00620 if (!fUserControlled) {
00621 if (fSelected) fSelected->SetActive(kFALSE);
00622 UnselectAll(kTRUE);
00623
00624 fCurrent = fSelected = item;
00625 HighlightItem(item, kTRUE, kTRUE);
00626 SendMessage(fMsgWindow, MK_MSG(kC_LISTTREE, kCT_ITEMCLICK),
00627 event->fCode, (event->fYRoot << 16) | event->fXRoot);
00628 }
00629 else {
00630 fCurrent = fSelected = item;
00631 ClearViewPort();
00632 }
00633 Clicked(item, event->fCode);
00634 Clicked(item, event->fCode, event->fXRoot, event->fYRoot);
00635 Clicked(item, event->fCode, event->fState, event->fXRoot, event->fYRoot);
00636 }
00637 }
00638 if (event->fType == kButtonRelease) {
00639 fBdown = kFALSE;
00640 }
00641 return kTRUE;
00642 }
00643
00644
00645 Bool_t TGListTree::HandleDoubleClick(Event_t *event)
00646 {
00647
00648
00649 TGListTreeItem *item = 0;
00650
00651 if (event->fCode == kButton4 || event->fCode == kButton5) {
00652 return kFALSE;
00653 }
00654
00655
00656 if (fDisableOpen && event->fCode == kButton1 && (item = FindItem(event->fY)) != 0) {
00657 SendMessage(fMsgWindow, MK_MSG(kC_LISTTREE, kCT_ITEMDBLCLICK),
00658 event->fCode, (event->fYRoot << 16) | event->fXRoot);
00659 DoubleClicked(item, event->fCode);
00660 DoubleClicked(item, event->fCode, event->fXRoot, event->fYRoot);
00661 return kTRUE;
00662 }
00663 item = FindItem(event->fY);
00664
00665
00666 if (event->fCode == kButton1 && item) {
00667 ClearViewPort();
00668 item->SetOpen(!item->IsOpen());
00669 if (!fUserControlled) {
00670 if (item != fSelected) {
00671 if (fSelected) fSelected->SetActive(kFALSE);
00672 UnselectAll(kTRUE);
00673 HighlightItem(item, kTRUE, kTRUE);
00674 }
00675 }
00676 SendMessage(fMsgWindow, MK_MSG(kC_LISTTREE, kCT_ITEMDBLCLICK),
00677 event->fCode, (event->fYRoot << 16) | event->fXRoot);
00678 DoubleClicked(item, event->fCode);
00679 DoubleClicked(item, event->fCode, event->fXRoot, event->fYRoot);
00680 }
00681 if (!fUserControlled)
00682 fSelected = item;
00683 return kTRUE;
00684 }
00685
00686
00687 Bool_t TGListTree::HandleCrossing(Event_t *event)
00688 {
00689
00690
00691 if (event->fType == kLeaveNotify) {
00692 if (fTip) {
00693 fTip->Hide();
00694 fTipItem = 0;
00695 }
00696 if (!fUserControlled) {
00697 if (fCurrent)
00698 DrawOutline(fId, fCurrent, 0xffffff, kTRUE);
00699 if (fBelowMouse)
00700 DrawOutline(fId, fBelowMouse, 0xffffff, kTRUE);
00701 fCurrent = 0;
00702 }
00703 if (fBelowMouse) {
00704 fBelowMouse = 0;
00705 MouseOver(0);
00706 MouseOver(0, event->fState);
00707 }
00708 }
00709 return kTRUE;
00710 }
00711
00712
00713 Atom_t TGListTree::HandleDNDPosition(Int_t , Int_t y, Atom_t action,
00714 Int_t , Int_t )
00715 {
00716
00717
00718 static TGListTreeItem *olditem = 0;
00719 TGListTreeItem *item;
00720 if ((item = FindItem(y)) != 0) {
00721 if (item->IsDNDTarget()) {
00722 fDropItem = item;
00723 if (olditem)
00724 HighlightItem(olditem, kFALSE, kTRUE);
00725 HighlightItem(item, kTRUE, kTRUE);
00726 olditem = item;
00727 return action;
00728 }
00729 }
00730 fDropItem = 0;
00731 if (olditem) {
00732 HighlightItem(olditem, kFALSE, kTRUE);
00733 olditem = 0;
00734 }
00735 return kNone;
00736 }
00737
00738
00739 Atom_t TGListTree::HandleDNDEnter(Atom_t *typelist)
00740 {
00741
00742
00743 Atom_t ret = kNone;
00744 for (int i = 0; typelist[i] != kNone; ++i) {
00745 if (typelist[i] == fDNDTypeList[0])
00746 ret = fDNDTypeList[0];
00747 if (typelist[i] == fDNDTypeList[1])
00748 ret = fDNDTypeList[1];
00749 }
00750 return ret;
00751 }
00752
00753
00754 Bool_t TGListTree::HandleDNDLeave()
00755 {
00756
00757
00758 return kTRUE;
00759 }
00760
00761
00762 Bool_t TGListTree::HandleDNDDrop(TDNDData *data)
00763 {
00764
00765
00766 DataDropped(fDropItem, data);
00767 HighlightItem(fDropItem, kFALSE, kTRUE);
00768
00769 return kTRUE;
00770 }
00771
00772
00773 void TGListTree::DataDropped(TGListTreeItem *item, TDNDData *data)
00774 {
00775
00776
00777 Long_t args[2];
00778
00779 args[0] = (Long_t)item;
00780 args[1] = (Long_t)data;
00781
00782 Emit("DataDropped(TGListTreeItem*,TDNDData*)", args);
00783 }
00784
00785
00786 Bool_t TGListTree::HandleMotion(Event_t *event)
00787 {
00788
00789
00790
00791 TGListTreeItem *item;
00792 TGPosition pos = GetPagePosition();
00793
00794 if (gDNDManager->IsDragging()) {
00795 gDNDManager->Drag(event->fXRoot, event->fYRoot,
00796 TGDNDManager::GetDNDActionCopy(), event->fTime);
00797 } else if ((item = FindItem(event->fY)) != 0) {
00798 if (!fUserControlled) {
00799 if (fCurrent)
00800 DrawOutline(fId, fCurrent, 0xffffff, kTRUE);
00801 if (fBelowMouse)
00802 DrawOutline(fId, fBelowMouse, 0xffffff, kTRUE);
00803 DrawOutline(fId, item);
00804 fCurrent = item;
00805 }
00806 if (item != fBelowMouse) {
00807 fBelowMouse = item;
00808 MouseOver(fBelowMouse);
00809 MouseOver(fBelowMouse, event->fState);
00810 }
00811
00812 if (item->HasCheckBox()) {
00813 if ((event->fX < (item->fXtext - 4) &&
00814 (event->fX > (item->fXtext - (Int_t)item->GetCheckBoxPicture()->GetWidth()))))
00815 {
00816 gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kPointer));
00817 return kTRUE;
00818 }
00819 else {
00820 gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kHand));
00821 }
00822 }
00823 if (!gDNDManager->IsDragging()) {
00824 if (fBdown && ((abs(event->fX - fXDND) > 2) || (abs(event->fY - fYDND) > 2))) {
00825 if (gDNDManager && item->IsDNDSource()) {
00826 if (!fBuf) fBuf = new TBufferFile(TBuffer::kWrite);
00827 fBuf->Reset();
00828
00829
00830 if (item->GetUserData()) {
00831 TObject *obj = static_cast<TObject *>(item->GetUserData());
00832 if (dynamic_cast<TObject *>(obj)) {
00833 TObjString *ostr = dynamic_cast<TObjString *>(obj);
00834 if (ostr) {
00835 TString& str = ostr->String();
00836 if (str.BeginsWith("file://")) {
00837 fDNDData.fDataType = fDNDTypeList[1];
00838 fDNDData.fData = (void *)strdup(str.Data());
00839 fDNDData.fDataLength = str.Length()+1;
00840 }
00841 }
00842 else {
00843 fDNDData.fDataType = fDNDTypeList[0];
00844 fBuf->WriteObject((TObject *)item->GetUserData());
00845 fDNDData.fData = fBuf->Buffer();
00846 fDNDData.fDataLength = fBuf->Length();
00847 }
00848 }
00849 }
00850 else {
00851 fDNDData.fDataType = fDNDTypeList[1];
00852 TString str = TString::Format("file://%s/%s\r\n",
00853 gSystem->UnixPathName(gSystem->WorkingDirectory()),
00854 item->GetText());
00855 fDNDData.fData = (void *)strdup(str.Data());
00856 fDNDData.fDataLength = str.Length()+1;
00857 }
00858 TString xmpname = item->GetPicture()->GetName();
00859 if (xmpname.EndsWith("_t.xpm"))
00860 xmpname.ReplaceAll("_t.xpm", "_s.xpm");
00861 if (xmpname.EndsWith("_t.xpm__16x16"))
00862 xmpname.ReplaceAll("_t.xpm__16x16", "_s.xpm");
00863 const TGPicture *pic = fClient->GetPicture(xmpname.Data());
00864 if (!pic) pic = item->GetPicture();
00865 if (pic) SetDragPixmap(pic);
00866
00867 gDNDManager->StartDrag(this, event->fXRoot, event->fYRoot);
00868 }
00869 }
00870 }
00871 if (gDNDManager->IsDragging()) {
00872 gDNDManager->Drag(event->fXRoot, event->fYRoot,
00873 TGDNDManager::GetDNDActionCopy(), event->fTime);
00874 } else {
00875 if (fTipItem == item) return kTRUE;
00876 if (!fUserControlled) {
00877 MouseOver(item);
00878 MouseOver(item, event->fState);
00879 }
00880 gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kHand));
00881 }
00882
00883 if (fTip)
00884 fTip->Hide();
00885
00886 if (item->GetTipTextLength() > 0) {
00887
00888 SetToolTipText(item->GetTipText(), item->fXtext,
00889 item->fY - pos.fY + item->fHeight, 1000);
00890
00891 } else if (fAutoTips && item->GetUserData()) {
00892
00893
00894 TObject *obj = (TObject *)item->GetUserData();
00895 if (obj->InheritsFrom(TObject::Class())) {
00896 SetToolTipText(obj->GetTitle(), item->fXtext,
00897 item->fY - pos.fY + item->fHeight, 1000);
00898 }
00899 }
00900 fTipItem = item;
00901 } else {
00902 if (fBelowMouse) {
00903 fBelowMouse = 0;
00904 MouseOver(fBelowMouse);
00905 MouseOver(fBelowMouse, event->fState);
00906 }
00907 gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kPointer));
00908 }
00909 return kTRUE;
00910 }
00911
00912
00913 Bool_t TGListTree::HandleKey(Event_t *event)
00914 {
00915
00916
00917
00918 char input[10];
00919 Int_t n;
00920 UInt_t keysym;
00921 TGListTreeItem *item = 0;
00922
00923 fLastEventState = event->fState;
00924 if (fTip) fTip->Hide();
00925
00926 if (event->fType == kGKeyPress) {
00927 gVirtualX->LookupString(event, input, sizeof(input), keysym);
00928 n = strlen(input);
00929
00930 if (!event->fState && (EKeySym)keysym == kKey_Escape) {
00931 if (gDNDManager->IsDragging()) gDNDManager->EndDrag();
00932 }
00933
00934 item = fCurrent;
00935 if (!item) return kFALSE;
00936
00937 fEventHandled = kFALSE;
00938 KeyPressed(item, keysym, event->fState);
00939
00940 if (fUserControlled && fEventHandled)
00941 return kTRUE;
00942
00943 switch ((EKeySym)keysym) {
00944 case kKey_Enter:
00945 case kKey_Return:
00946 event->fType = kButtonPress;
00947 event->fCode = kButton1;
00948
00949 if (fSelected == item) {
00950
00951 ClearViewPort();
00952 item->SetOpen(!item->IsOpen());
00953 DoubleClicked(item, 1);
00954 } else {
00955
00956 ClearViewPort();
00957 if (fSelected) fSelected->SetActive(kFALSE);
00958 fSelected = item;
00959 fSelected->SetActive(kTRUE);
00960 HighlightItem(item, kTRUE, kTRUE);
00961 Clicked(item, 1);
00962 Clicked(item, 1, event->fXRoot, event->fYRoot);
00963 Clicked(item, 1, event->fState, event->fXRoot, event->fYRoot);
00964 }
00965 break;
00966 case kKey_Space:
00967 if (item->HasCheckBox()) {
00968 ToggleItem(item);
00969 if (fCheckMode == kRecursive) {
00970 CheckAllChildren(item, item->IsChecked());
00971 }
00972 UpdateChecked(item, kTRUE);
00973 Checked((TObject *)item->GetUserData(), item->IsChecked());
00974 }
00975 break;
00976 case kKey_F5:
00977 Layout();
00978 break;
00979 case kKey_F7:
00980 Search();
00981 break;
00982 case kKey_Left:
00983 ClearViewPort();
00984 item->SetOpen(kFALSE);
00985 break;
00986 case kKey_Right:
00987 ClearViewPort();
00988 item->SetOpen(kTRUE);
00989 break;
00990 case kKey_Up:
00991 LineUp(event->fState & kKeyShiftMask);
00992 break;
00993 case kKey_Down:
00994 LineDown(event->fState & kKeyShiftMask);
00995 break;
00996 case kKey_PageUp:
00997 PageUp(event->fState & kKeyShiftMask);
00998 break;
00999 case kKey_PageDown:
01000 PageDown(event->fState & kKeyShiftMask);
01001 break;
01002 case kKey_Home:
01003 Home(event->fState & kKeyShiftMask);
01004 break;
01005 case kKey_End:
01006 End(event->fState & kKeyShiftMask);
01007 break;
01008 default:
01009 break;
01010 }
01011
01012 }
01013 return kTRUE;
01014 }
01015
01016
01017 void TGListTree::MouseOver(TGListTreeItem *entry)
01018 {
01019
01020
01021 Emit("MouseOver(TGListTreeItem*)", (Long_t)entry);
01022 }
01023
01024
01025 void TGListTree::MouseOver(TGListTreeItem *entry, UInt_t mask)
01026 {
01027
01028
01029 Long_t args[2];
01030 args[0] = (Long_t)entry;
01031 args[1] = mask;
01032 Emit("MouseOver(TGListTreeItem*,UInt_t)", args);
01033 }
01034
01035
01036 void TGListTree::KeyPressed(TGListTreeItem *entry, UInt_t keysym, UInt_t mask)
01037 {
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055 Long_t args[3];
01056 args[0] = (Long_t)entry;
01057 args[1] = (Long_t)keysym;
01058 args[2] = (Long_t)mask;
01059 Emit("KeyPressed(TGListTreeItem*,ULong_t,ULong_t)", args);
01060 SendMessage(fMsgWindow, MK_MSG(kC_LISTTREE, kCT_KEY), keysym, mask);
01061 }
01062
01063
01064 void TGListTree::ReturnPressed(TGListTreeItem *entry)
01065 {
01066
01067
01068 Emit("ReturnPressed(TGListTreeItem*)", (Long_t)entry);
01069 }
01070
01071
01072 void TGListTree::Checked(TObject *entry, Bool_t on)
01073 {
01074
01075
01076 Long_t args[2];
01077
01078 args[0] = (Long_t)entry;
01079 args[1] = on;
01080
01081 Emit("Checked(TObject*,Bool_t)", args);
01082 }
01083
01084
01085 void TGListTree::Clicked(TGListTreeItem *entry, Int_t btn)
01086 {
01087
01088
01089 Long_t args[2];
01090
01091 args[0] = (Long_t)entry;
01092 args[1] = btn;
01093
01094 Emit("Clicked(TGListTreeItem*,Int_t)", args);
01095 }
01096
01097
01098 void TGListTree::Clicked(TGListTreeItem *entry, Int_t btn, Int_t x, Int_t y)
01099 {
01100
01101
01102 Long_t args[4];
01103
01104 args[0] = (Long_t)entry;
01105 args[1] = btn;
01106 args[2] = x;
01107 args[3] = y;
01108
01109 Emit("Clicked(TGListTreeItem*,Int_t,Int_t,Int_t)", args);
01110 }
01111
01112
01113 void TGListTree::Clicked(TGListTreeItem *entry, Int_t btn, UInt_t mask, Int_t x, Int_t y)
01114 {
01115
01116
01117 Long_t args[5];
01118
01119 args[0] = (Long_t)entry;
01120 args[1] = btn;
01121 args[2] = mask;
01122 args[3] = x;
01123 args[4] = y;
01124
01125 Emit("Clicked(TGListTreeItem*,Int_t,UInt_t,Int_t,Int_t)", args);
01126 }
01127
01128
01129 void TGListTree::DoubleClicked(TGListTreeItem *entry, Int_t btn)
01130 {
01131
01132
01133 Long_t args[2];
01134
01135 args[0] = (Long_t)entry;
01136 args[1] = btn;
01137
01138 Emit("DoubleClicked(TGListTreeItem*,Int_t)", args);
01139 }
01140
01141
01142 void TGListTree::DoubleClicked(TGListTreeItem *entry, Int_t btn, Int_t x, Int_t y)
01143 {
01144
01145
01146 Long_t args[4];
01147
01148 args[0] = (Long_t)entry;
01149 args[1] = btn;
01150 args[2] = x;
01151 args[3] = y;
01152
01153 Emit("DoubleClicked(TGListTreeItem*,Int_t,Int_t,Int_t)", args);
01154 }
01155
01156
01157 void TGListTree::Home(Bool_t )
01158 {
01159
01160
01161 if (fCanvas) fCanvas->SetVsbPosition(0);
01162 }
01163
01164
01165 void TGListTree::End(Bool_t )
01166 {
01167
01168
01169 if (fCanvas) fCanvas->SetVsbPosition((Int_t)fHeight);
01170 }
01171
01172
01173 void TGListTree::PageUp(Bool_t )
01174 {
01175
01176
01177 if (!fCanvas) return;
01178
01179 TGDimension dim = GetPageDimension();
01180
01181 Int_t newpos = fCanvas->GetVsbPosition() - dim.fHeight;
01182 if (newpos<0) newpos = 0;
01183
01184 fCanvas->SetVsbPosition(newpos);
01185 }
01186
01187
01188 void TGListTree::PageDown(Bool_t )
01189 {
01190
01191
01192 if (!fCanvas) return;
01193
01194 TGDimension dim = GetPageDimension();
01195
01196 Int_t newpos = fCanvas->GetVsbPosition() + dim.fHeight;
01197
01198 fCanvas->SetVsbPosition(newpos);
01199 }
01200
01201
01202 void TGListTree::LineUp(Bool_t )
01203 {
01204
01205
01206 Int_t height;
01207 if (!fCurrent) return;
01208
01209 TGDimension dim = GetPageDimension();
01210 TGPosition pos = GetPagePosition();
01211 const TGPicture *pic1 = fCurrent->GetPicture();
01212 height = pic1->GetHeight() + fVspacing;
01213 Int_t findy = (fCurrent->fY - height) + (fMargin - pos.fY);
01214 TGListTreeItem *next = FindItem(findy);
01215 if (next && (next != fCurrent)) {
01216 DrawOutline(fId, fCurrent, 0xffffff, kTRUE);
01217 if (findy <= 2*height) {
01218 Int_t newpos = fCanvas->GetVsbPosition() - height;
01219 if (newpos<0) newpos = 0;
01220 fCanvas->SetVsbPosition(newpos);
01221 }
01222 DrawOutline(fId, next);
01223 fCurrent = next;
01224 }
01225 }
01226
01227
01228 void TGListTree::LineDown(Bool_t )
01229 {
01230
01231
01232 Int_t height;
01233 if (!fCurrent) return;
01234
01235 TGDimension dim = GetPageDimension();
01236 TGPosition pos = GetPagePosition();
01237 const TGPicture *pic1 = fCurrent->GetPicture();
01238 height = pic1->GetHeight() + fVspacing;
01239 Int_t findy = (fCurrent->fY + height) + (fMargin - pos.fY);
01240 TGListTreeItem *next = FindItem(findy);
01241 if (next && (next != fCurrent)) {
01242 DrawOutline(fId, fCurrent, 0xffffff, kTRUE);
01243 if (findy >= ((Int_t)dim.fHeight - 2*height)) {
01244 Int_t newpos = fCanvas->GetVsbPosition() + height;
01245 if (newpos<0) newpos = 0;
01246 fCanvas->SetVsbPosition(newpos);
01247 }
01248 DrawOutline(fId, next);
01249 fCurrent = next;
01250 }
01251 }
01252
01253
01254 void TGListTree::AdjustPosition(TGListTreeItem *item)
01255 {
01256
01257
01258
01259 TGListTreeItem *it = item;
01260
01261 if (!it) it = fSelected;
01262 if (!it) {
01263 HighlightItem(fFirst);
01264 return;
01265 }
01266
01267 Int_t y = 0;
01268 Int_t yparent = 0;
01269 Int_t vh = 0;
01270 Int_t v = 0;
01271
01272 if (it) {
01273 y = it->fY;
01274 if (it->GetParent()) yparent = it->GetParent()->fY;
01275 }
01276
01277 if (y==0) y = yparent;
01278
01279 if (fCanvas->GetVScrollbar()->IsMapped()) {
01280 vh = fCanvas->GetVScrollbar()->GetPosition()+(Int_t)fViewPort->GetHeight();
01281
01282 if (y<fCanvas->GetVScrollbar()->GetPosition()) {
01283 v = TMath::Max(0,y-(Int_t)fViewPort->GetHeight()/2);
01284 fCanvas->SetVsbPosition(v);
01285 } else if (y+(Int_t)it->fHeight>vh) {
01286 v = TMath::Min((Int_t)GetHeight()-(Int_t)fViewPort->GetHeight(),
01287 y+(Int_t)it->fHeight-(Int_t)fViewPort->GetHeight()/2);
01288 if (v<0) v = 0;
01289 fCanvas->SetVsbPosition(v);
01290 }
01291 }
01292 }
01293
01294
01295 void TGListTree::Search(Bool_t )
01296 {
01297
01298
01299 Int_t ret = 0;
01300 char msg[256];
01301 static TString buf;
01302
01303 TGSearchType *srch = new TGSearchType;
01304 srch->fBuffer = (char*)buf.Data();
01305
01306 TGListTreeItem *item;
01307 new TGSearchDialog(fClient->GetDefaultRoot(), fCanvas, 400, 150, srch, &ret);
01308
01309 if (ret) {
01310 item = FindItemByPathname(srch->fBuffer);
01311 if (!item) {
01312 snprintf(msg, 255, "Couldn't find \"%s\"", srch->fBuffer);
01313 gVirtualX->Bell(20);
01314 new TGMsgBox(fClient->GetDefaultRoot(), fCanvas, "Container", msg,
01315 kMBIconExclamation, kMBOk, 0);
01316 } else {
01317 ClearHighlighted();
01318 HighlightItem(item);
01319 }
01320 }
01321 buf = srch->fBuffer;
01322 delete srch;
01323 }
01324
01325
01326
01327
01328 void TGListTree::DrawRegion(Int_t , Int_t y, UInt_t , UInt_t h)
01329 {
01330
01331
01332 static GContext_t gcBg = 0;
01333
01334
01335 if (y > (Int_t)fViewPort->GetHeight()) {
01336 return;
01337 }
01338
01339 y = y < 0 ? 0 : y;
01340 UInt_t w = fViewPort->GetWidth();
01341
01342
01343 if (((Int_t)w < 1) || (w > 32768) || ((Int_t)h < 1)) {
01344 return;
01345 }
01346
01347 Pixmap_t pixmap = gVirtualX->CreatePixmap(fId, w, fViewPort->GetHeight());
01348
01349 if (!gcBg) {
01350 GCValues_t gcValues;
01351 gcValues.fForeground = fBackground;
01352 gcValues.fForeground = fBackground;
01353 gcValues.fGraphicsExposures = kTRUE;
01354 gcValues.fMask = kGCForeground | kGCBackground | kGCGraphicsExposures;
01355 gcBg = gVirtualX->CreateGC(fId, &gcValues);
01356 }
01357
01358 gVirtualX->SetForeground(gcBg, fBackground);
01359 gVirtualX->FillRectangle(pixmap, gcBg, 0, 0, w, fViewPort->GetHeight());
01360
01361 Draw(pixmap, 0, fViewPort->GetHeight());
01362
01363 gVirtualX->CopyArea(pixmap, fId, gcBg, 0, y, w, fViewPort->GetHeight(), 0, y);
01364
01365 gVirtualX->DeletePixmap(pixmap);
01366 gVirtualX->Update(kFALSE);
01367 }
01368
01369
01370 void TGListTree::Draw(Handle_t id, Int_t yevent, Int_t hevent)
01371 {
01372
01373
01374 TGListTreeItem *item;
01375 Int_t x, y, xbranch;
01376 UInt_t width, height, old_width, old_height;
01377
01378
01379
01380 fExposeTop = yevent - FontHeight();
01381 fExposeBottom = yevent + hevent + FontHeight();
01382 old_width = fDefw;
01383 old_height = fDefh;
01384 fDefw = fDefh = 1;
01385
01386 TGPosition pos = GetPagePosition();
01387 x = -pos.fX;
01388 y = fMargin;
01389 item = fFirst;
01390
01391 while (item) {
01392 xbranch = -1;
01393
01394 DrawItem(id, item, x, y, &xbranch, &width, &height);
01395
01396 width += pos.fX + x + fHspacing + fMargin;
01397
01398 if (width > fDefw) fDefw = width;
01399
01400 y += height + fVspacing;
01401 if (item->fFirstchild && item->IsOpen()) {
01402 y = DrawChildren(id, item->fFirstchild, x, y, xbranch);
01403 }
01404
01405 item = item->fNextsibling;
01406 }
01407
01408 fDefh = y + fMargin;
01409
01410 if ((old_width != fDefw) || (old_height != fDefh)) {
01411 fCanvas->Layout();
01412 }
01413 }
01414
01415
01416 Int_t TGListTree::DrawChildren(Handle_t id, TGListTreeItem *item,
01417 Int_t x, Int_t y, Int_t xroot)
01418 {
01419
01420
01421 UInt_t width, height;
01422 Int_t xbranch;
01423 TGPosition pos = GetPagePosition();
01424
01425 x += fIndent + (Int_t)item->fParent->GetPicWidth();
01426 while (item) {
01427 xbranch = xroot;
01428
01429 DrawItem(id, item, x, y, &xbranch, &width, &height);
01430
01431 width += pos.fX + x + fHspacing + fMargin;
01432 if (width > fDefw) fDefw = width;
01433
01434 y += height + fVspacing;
01435 if ((item->fFirstchild) && (item->IsOpen())) {
01436 y = DrawChildren(id, item->fFirstchild, x, y, xbranch);
01437 }
01438
01439 item = item->fNextsibling;
01440 }
01441 return y;
01442 }
01443
01444
01445 void TGListTree::DrawItem(Handle_t id, TGListTreeItem *item, Int_t x, Int_t y,
01446 Int_t *xroot, UInt_t *retwidth, UInt_t *retheight)
01447 {
01448
01449
01450 Int_t xpic1, ypic1, xbranch, ybranch, xtext, ytext, xline, yline, xc;
01451 Int_t xpic2 = 0, ypic2 = 0;
01452 UInt_t height;
01453 const TGPicture *pic1 = item->GetPicture();
01454 const TGPicture *pic2 = item->GetCheckBoxPicture();
01455
01456
01457 height = FontHeight();
01458 xline = 0;
01459 xpic1 = x;
01460 xtext = x + fHspacing + (Int_t)item->GetPicWidth();
01461 if (pic2) {
01462 if (pic2->GetHeight() > height) {
01463 ytext = y + (Int_t)((pic2->GetHeight() - height) >> 1);
01464 height = pic2->GetHeight();
01465 ypic2 = y;
01466 } else {
01467 ytext = y;
01468 ypic2 = y + (Int_t)((height - pic2->GetHeight()) >> 1);
01469 }
01470 xpic2 = xpic1 + pic1->GetWidth() + 1;
01471 xtext += pic2->GetWidth();
01472 } else {
01473 ypic1 = y;
01474 xline = 0;
01475 }
01476 if (pic1) {
01477 if (pic1->GetHeight() > height) {
01478 ytext = y + (Int_t)((pic1->GetHeight() - height) >> 1);
01479 height = pic1->GetHeight();
01480 ypic1 = y;
01481 } else {
01482 ytext = y;
01483 ypic1 = y + (Int_t)((height - pic1->GetHeight()) >> 1);
01484 }
01485 xbranch = xpic1 + (Int_t)(pic1->GetWidth() >> 1);
01486 ybranch = ypic1 + (Int_t)pic1->GetHeight();
01487 yline = ypic1 + (Int_t)(pic1->GetHeight() >> 1);
01488 if (xline == 0) xline = xpic1;
01489 } else {
01490 if (xline == 0) xline = xpic1;
01491 ypic1 = ytext = y;
01492 xbranch = xpic1 + (Int_t)(item->GetPicWidth() >> 1);
01493 yline = ybranch = ypic1 + (Int_t)(height >> 1);
01494 yline = ypic1 + (Int_t)(height >> 1);
01495 }
01496
01497
01498
01499
01500
01501 item->fY = y;
01502 item->fXtext = xtext;
01503 item->fYtext = ytext;
01504 item->fHeight = height;
01505
01506
01507 TGPosition pos = GetPagePosition();
01508 TGDimension dim = GetPageDimension();
01509 Int_t yp = y - pos.fY;
01510 Int_t ylinep = yline - pos.fY;
01511 Int_t ybranchp = ybranch - pos.fY;
01512 Int_t ypicp = ypic1 - pos.fY;
01513
01514 if ((yp >= fExposeTop) && (yp <= (Int_t)dim.fHeight))
01515 {
01516 if (*xroot >= 0) {
01517 xc = *xroot;
01518
01519 if (item->fNextsibling) {
01520 gVirtualX->DrawLine(id, fLineGC, xc, yp, xc, yp+height);
01521 } else {
01522 gVirtualX->DrawLine(id, fLineGC, xc, yp, xc, ylinep);
01523 }
01524
01525 TGListTreeItem *p = item->fParent;
01526 while (p) {
01527 xc -= (fIndent + (Int_t)item->GetPicWidth());
01528 if (p->fNextsibling) {
01529 gVirtualX->DrawLine(id, fLineGC, xc, yp, xc, yp+height);
01530 }
01531 p = p->fParent;
01532 }
01533 gVirtualX->DrawLine(id, fLineGC, *xroot, ylinep, xpic1, ylinep);
01534 DrawNode(id, item, *xroot, yline);
01535 }
01536 if (item->IsOpen() && item->fFirstchild) {
01537 gVirtualX->DrawLine(id, fLineGC, xbranch, ybranchp, xbranch,
01538 yp+height);
01539 }
01540 if (pic1)
01541 pic1->Draw(id, fDrawGC, xpic1, ypicp);
01542 if (pic2)
01543 pic2->Draw(id, fDrawGC, xpic2, ypicp);
01544 DrawItemName(id, item);
01545 }
01546
01547 *xroot = xbranch;
01548 *retwidth = TextWidth(item->GetText()) + item->GetPicWidth();
01549 *retheight = height;
01550 }
01551
01552
01553 void TGListTree::DrawOutline(Handle_t id, TGListTreeItem *item, Pixel_t col,
01554 Bool_t clear)
01555 {
01556
01557
01558 Int_t posx;
01559 TGPosition pos = GetPagePosition();
01560 TGDimension dim = GetPageDimension();
01561
01562 posx = item->fXtext - item->GetPicWidth();
01563 posx -= 5;
01564 if (item->HasCheckBox())
01565 posx -= item->GetCheckBoxPicture()->GetWidth();
01566 if (clear) {
01567 gVirtualX->SetForeground(fDrawGC, fCanvas->GetContainer()->GetBackground());
01568
01569 }
01570 else
01571 gVirtualX->SetForeground(fDrawGC, col);
01572 gVirtualX->DrawRectangle(id, fDrawGC, posx, item->fYtext-pos.fY-2,
01573 dim.fWidth-posx-2, FontHeight()+4);
01574 gVirtualX->SetForeground(fDrawGC, fgBlackPixel);
01575 }
01576
01577
01578 void TGListTree::DrawActive(Handle_t id, TGListTreeItem *item)
01579 {
01580
01581
01582 UInt_t width;
01583 TGPosition pos = GetPagePosition();
01584 TGDimension dim = GetPageDimension();
01585
01586 width = TextWidth(item->GetText());
01587 gVirtualX->SetForeground(fDrawGC, item->GetActiveColor());
01588 gVirtualX->FillRectangle(id, fDrawGC, item->fXtext-1,
01589 item->fYtext-pos.fY, width+2, FontHeight()+1);
01590 gVirtualX->SetForeground(fDrawGC, fgBlackPixel);
01591 gVirtualX->DrawString(id, fHighlightGC, item->fXtext,
01592 item->fYtext - pos.fY + FontAscent(),
01593 item->GetText(), item->GetTextLength());
01594 }
01595
01596
01597 void TGListTree::DrawItemName(Handle_t id, TGListTreeItem *item)
01598 {
01599
01600
01601 TGPosition pos = GetPagePosition();
01602 TGDimension dim = GetPageDimension();
01603
01604 if (item->IsActive()) {
01605 DrawActive(id, item);
01606 }
01607 else {
01608 gVirtualX->FillRectangle(id, fHighlightGC, item->fXtext,
01609 item->fYtext-pos.fY, dim.fWidth-item->fXtext-2,
01610 FontHeight()+1);
01611 gVirtualX->DrawString(id, fDrawGC,
01612 item->fXtext, item->fYtext-pos.fY + FontAscent(),
01613 item->GetText(), item->GetTextLength());
01614 }
01615 if (item == fCurrent) {
01616 DrawOutline(id, item);
01617 }
01618
01619 if (fColorMode != 0 && item->HasColor()) {
01620 UInt_t width = TextWidth(item->GetText());
01621 gVirtualX->SetForeground(fColorGC, TColor::Number2Pixel(item->GetColor()));
01622 if (fColorMode & kColorUnderline) {
01623 Int_t y = item->fYtext-pos.fY + FontAscent() + 2;
01624 gVirtualX->DrawLine(id, fColorGC, item->fXtext, y, item->fXtext + width, y);
01625 }
01626 if (fColorMode & kColorBox) {
01627 Int_t x = item->fXtext + width + 4;
01628 Int_t y = item->fYtext - pos.fY + 3;
01629 Int_t h = FontAscent() - 4;
01630 gVirtualX->FillRectangle(id, fColorGC, x, y, h, h);
01631 gVirtualX->DrawRectangle(id, fDrawGC, x, y, h, h);
01632 }
01633 }
01634 }
01635
01636
01637 void TGListTree::DrawNode(Handle_t id, TGListTreeItem *item, Int_t x, Int_t y)
01638 {
01639
01640
01641 TGPosition pos = GetPagePosition();
01642 Int_t yp = y - pos.fY;
01643
01644 if (item->fFirstchild) {
01645 gVirtualX->DrawLine(id, fHighlightGC, x, yp-2, x, yp+2);
01646 gVirtualX->SetForeground(fHighlightGC, fgBlackPixel);
01647 gVirtualX->DrawLine(id, fHighlightGC, x-2, yp, x+2, yp);
01648 if (!item->IsOpen())
01649 gVirtualX->DrawLine(id, fHighlightGC, x, yp-2, x, yp+2);
01650 gVirtualX->SetForeground(fHighlightGC, fGrayPixel);
01651 gVirtualX->DrawLine(id, fHighlightGC, x-4, yp-4, x+4, yp-4);
01652 gVirtualX->DrawLine(id, fHighlightGC, x+4, yp-4, x+4, yp+4);
01653 gVirtualX->DrawLine(id, fHighlightGC, x-4, yp+4, x+4, yp+4);
01654 gVirtualX->DrawLine(id, fHighlightGC, x-4, yp-4, x-4, yp+4);
01655 gVirtualX->SetForeground(fHighlightGC, fgWhitePixel);
01656 }
01657 }
01658
01659
01660 void TGListTree::SetToolTipText(const char *text, Int_t x, Int_t y, Long_t delayms)
01661 {
01662
01663
01664
01665
01666
01667 if (delayms == 0) {
01668 delete fTip;
01669 fTip = 0;
01670 return;
01671 }
01672
01673 if (text && strlen(text)) {
01674 if (!fTip)
01675 fTip = new TGToolTip(fClient->GetDefaultRoot(), this, text, delayms);
01676 else
01677 fTip->SetText(text);
01678 fTip->SetPosition(x, y);
01679 fTip->Reset();
01680 }
01681 }
01682
01683
01684 void TGListTree::RemoveReference(TGListTreeItem *item)
01685 {
01686
01687
01688
01689 ClearViewPort();
01690
01691
01692 if (item->fPrevsibling) {
01693 item->fPrevsibling->fNextsibling = item->fNextsibling;
01694 } else {
01695 if (item->fParent)
01696 item->fParent->fFirstchild = item->fNextsibling;
01697 else
01698 fFirst = item->fNextsibling;
01699 }
01700
01701 if (item->fNextsibling) {
01702 item->fNextsibling->fPrevsibling = item->fPrevsibling;
01703 } else {
01704 if (item->fParent)
01705 item->fParent->fLastchild = item->fPrevsibling;
01706 else
01707 fLast = item->fPrevsibling;
01708 }
01709 }
01710
01711
01712 void TGListTree::PDeleteItem(TGListTreeItem *item)
01713 {
01714
01715
01716
01717 if (fSelected == item) {
01718 fSelected = 0;
01719 }
01720 if (fCurrent == item) {
01721 DrawOutline(fId, fCurrent, 0xffffff, kTRUE);
01722 fCurrent = item->GetPrevSibling();
01723 if (! fCurrent) {
01724 fCurrent = item->GetNextSibling();
01725 if (! fCurrent)
01726 fCurrent = item->GetParent();
01727 }
01728 }
01729 if (fBelowMouse == item) {
01730 DrawOutline(fId, fBelowMouse, 0xffffff, kTRUE);
01731 fBelowMouse = 0;
01732 MouseOver(0);
01733 MouseOver(0,fLastEventState);
01734 }
01735
01736 delete item;
01737 }
01738
01739
01740 void TGListTree::PDeleteChildren(TGListTreeItem *item)
01741 {
01742
01743
01744 TGListTreeItem *child = item->fFirstchild;
01745
01746 while (child) {
01747 TGListTreeItem *next = child->fNextsibling;
01748 PDeleteChildren(child);
01749 PDeleteItem(child);
01750 child = next;
01751 }
01752
01753 item->fFirstchild = item->fLastchild = 0;
01754 }
01755
01756
01757 void TGListTree::InsertChild(TGListTreeItem *parent, TGListTreeItem *item)
01758 {
01759
01760
01761 TGListTreeItem *i;
01762
01763 item->fParent = parent;
01764 item->fNextsibling = item->fPrevsibling = 0;
01765
01766 if (parent) {
01767
01768 if (parent->fFirstchild) {
01769 if (parent->fLastchild) {
01770 i = parent->fLastchild;
01771 }
01772 else {
01773 i = parent->fFirstchild;
01774 while (i->fNextsibling) i = i->fNextsibling;
01775 }
01776 i->fNextsibling = item;
01777 item->fPrevsibling = i;
01778 } else {
01779 parent->fFirstchild = item;
01780 }
01781 parent->fLastchild = item;
01782
01783 } else {
01784
01785 if (fFirst) {
01786 if (fLast) {
01787 i = fLast;
01788 }
01789 else {
01790 i = fFirst;
01791 while (i->fNextsibling) i = i->fNextsibling;
01792 }
01793 i->fNextsibling = item;
01794 item->fPrevsibling = i;
01795 } else {
01796 fFirst = item;
01797 }
01798 fLast = item;
01799 }
01800 if (item->HasCheckBox())
01801 UpdateChecked(item);
01802 }
01803
01804
01805 void TGListTree::InsertChildren(TGListTreeItem *parent, TGListTreeItem *item)
01806 {
01807
01808
01809 TGListTreeItem *next, *newnext;
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819 next = item->fNextsibling;
01820
01821
01822 InsertChild(parent, item);
01823
01824
01825
01826 newnext = item->fNextsibling;
01827
01828
01829 item->fNextsibling = next;
01830
01831
01832
01833
01834 while (item->fNextsibling) {
01835 item->fParent = parent;
01836 item = item->fNextsibling;
01837 }
01838
01839
01840 item->fNextsibling = newnext;
01841 if (newnext)
01842 newnext->fPrevsibling = item;
01843 }
01844
01845
01846 Int_t TGListTree::SearchChildren(TGListTreeItem *item, Int_t y, Int_t findy,
01847 TGListTreeItem **finditem)
01848 {
01849
01850
01851 UInt_t height;
01852 const TGPicture *pic;
01853
01854 while (item) {
01855
01856 pic = item->GetPicture();
01857
01858
01859 height = FontHeight();
01860 if (pic->GetHeight() > height)
01861 height = pic->GetHeight();
01862
01863 if ((findy >= y) && (findy <= y + (Int_t)height)) {
01864 *finditem = item;
01865 return -1;
01866 }
01867
01868 y += (Int_t)height + fVspacing;
01869 if (item->fFirstchild && item->IsOpen()) {
01870 y = SearchChildren(item->fFirstchild, y, findy, finditem);
01871 if (*finditem) return -1;
01872 }
01873
01874 item = item->fNextsibling;
01875 }
01876
01877 return y;
01878 }
01879
01880
01881 TGListTreeItem *TGListTree::FindItem(Int_t findy)
01882 {
01883
01884
01885 Int_t y;
01886 UInt_t height;
01887 TGListTreeItem *item, *finditem;
01888 const TGPicture *pic;
01889 TGPosition pos = GetPagePosition();
01890
01891 y = fMargin - pos.fY;
01892 item = fFirst;
01893 finditem = 0;
01894 while (item && !finditem) {
01895
01896 pic = item->GetPicture();
01897
01898
01899 height = FontHeight();
01900 if (pic && (pic->GetHeight() > height))
01901 height = pic->GetHeight();
01902
01903 if ((findy >= y) && (findy <= y + (Int_t)height))
01904 return item;
01905
01906 y += (Int_t)height + fVspacing;
01907 if ((item->fFirstchild) && (item->IsOpen())) {
01908 y = SearchChildren(item->fFirstchild, y, findy, &finditem);
01909
01910 }
01911 item = item->fNextsibling;
01912 }
01913
01914 return finditem;
01915 }
01916
01917
01918
01919
01920 void TGListTree::AddItem(TGListTreeItem *parent, TGListTreeItem *item)
01921 {
01922
01923
01924 InsertChild(parent, item);
01925
01926 if ((parent == 0) || (parent && parent->IsOpen()))
01927 ClearViewPort();
01928 }
01929
01930
01931 TGListTreeItem *TGListTree::AddItem(TGListTreeItem *parent, const char *string,
01932 const TGPicture *open, const TGPicture *closed,
01933 Bool_t checkbox)
01934 {
01935
01936
01937 TGListTreeItem *item;
01938
01939 item = new TGListTreeItemStd(fClient, string, open, closed, checkbox);
01940 InsertChild(parent, item);
01941
01942 if ((parent == 0) || (parent && parent->IsOpen()))
01943 ClearViewPort();
01944 return item;
01945 }
01946
01947
01948 TGListTreeItem *TGListTree::AddItem(TGListTreeItem *parent, const char *string,
01949 void *userData, const TGPicture *open,
01950 const TGPicture *closed,
01951 Bool_t checkbox)
01952 {
01953
01954
01955
01956 TGListTreeItem *item = FindChildByData(parent, userData);
01957 if (!item) {
01958 item = AddItem(parent, string, open, closed, checkbox);
01959 if (item) item->SetUserData(userData);
01960 }
01961
01962 return item;
01963 }
01964
01965
01966 void TGListTree::RenameItem(TGListTreeItem *item, const char *string)
01967 {
01968
01969
01970 if (item) {
01971 item->Rename(string);
01972 }
01973
01974 DoRedraw();
01975 }
01976
01977
01978 Int_t TGListTree::DeleteItem(TGListTreeItem *item)
01979 {
01980
01981
01982 if (!fUserControlled)
01983 fCurrent = fBelowMouse = 0;
01984
01985 PDeleteChildren(item);
01986 RemoveReference(item);
01987 PDeleteItem(item);
01988
01989 fClient->NeedRedraw(this);
01990
01991 return 1;
01992 }
01993
01994
01995 void TGListTree::OpenItem(TGListTreeItem *item)
01996 {
01997
01998
01999 if (item) {
02000 item->SetOpen(kTRUE);
02001 DoRedraw();
02002 AdjustPosition(item);
02003 }
02004 }
02005
02006
02007 void TGListTree::CloseItem(TGListTreeItem *item)
02008 {
02009
02010
02011 if (item) {
02012 item->SetOpen(kFALSE);
02013 DoRedraw();
02014 AdjustPosition(item);
02015 }
02016 }
02017
02018
02019 Int_t TGListTree::RecursiveDeleteItem(TGListTreeItem *item, void *ptr)
02020 {
02021
02022
02023
02024 if (item && ptr) {
02025 if (item->GetUserData() == ptr) {
02026 DeleteItem(item);
02027 } else {
02028 if (item->IsOpen() && item->fFirstchild) {
02029 RecursiveDeleteItem(item->fFirstchild, ptr);
02030 }
02031 RecursiveDeleteItem(item->fNextsibling, ptr);
02032 }
02033 }
02034 return 1;
02035 }
02036
02037
02038 void TGListTree::SetToolTipItem(TGListTreeItem *item, const char *string)
02039 {
02040
02041
02042
02043
02044 if (item) {
02045 item->SetTipText(string);
02046 }
02047 }
02048
02049
02050 Int_t TGListTree::DeleteChildren(TGListTreeItem *item)
02051 {
02052
02053
02054 if (!fUserControlled)
02055 fCurrent = fBelowMouse = 0;
02056
02057 PDeleteChildren(item);
02058
02059 DoRedraw();
02060
02061 return 1;
02062 }
02063
02064
02065 Int_t TGListTree::Reparent(TGListTreeItem *item, TGListTreeItem *newparent)
02066 {
02067
02068
02069
02070 RemoveReference(item);
02071
02072
02073 InsertChild(newparent, item);
02074
02075 DoRedraw();
02076
02077 return 1;
02078 }
02079
02080
02081 Int_t TGListTree::ReparentChildren(TGListTreeItem *item,
02082 TGListTreeItem *newparent)
02083 {
02084
02085
02086 TGListTreeItem *first;
02087
02088 if (item->fFirstchild) {
02089 first = item->fFirstchild;
02090 item->fFirstchild = 0;
02091
02092 InsertChildren(newparent, first);
02093
02094 DoRedraw();
02095 return 1;
02096 }
02097 return 0;
02098 }
02099
02100
02101 extern "C"
02102 Int_t Compare(const void *item1, const void *item2)
02103 {
02104 return strcmp((*((TGListTreeItem **) item1))->GetText(),
02105 (*((TGListTreeItem **) item2))->GetText());
02106 }
02107
02108
02109 Int_t TGListTree::Sort(TGListTreeItem *item)
02110 {
02111
02112
02113 TGListTreeItem *first, *parent, **list;
02114 size_t i, count;
02115
02116
02117 while (item->fPrevsibling) item = item->fPrevsibling;
02118
02119 first = item;
02120 parent = first->fParent;
02121
02122
02123 count = 1;
02124 while (item->fNextsibling) item = item->fNextsibling, count++;
02125 if (count <= 1) return 1;
02126
02127 list = new TGListTreeItem* [count];
02128 list[0] = first;
02129 count = 1;
02130 while (first->fNextsibling) {
02131 list[count] = first->fNextsibling;
02132 count++;
02133 first = first->fNextsibling;
02134 }
02135
02136 ::qsort(list, count, sizeof(TGListTreeItem*), ::Compare);
02137
02138 list[0]->fPrevsibling = 0;
02139 for (i = 0; i < count; i++) {
02140 if (i < count - 1)
02141 list[i]->fNextsibling = list[i + 1];
02142 if (i > 0)
02143 list[i]->fPrevsibling = list[i - 1];
02144 }
02145 list[count - 1]->fNextsibling = 0;
02146 if (parent) {
02147 parent->fFirstchild = list[0];
02148 parent->fLastchild = list[count-1];
02149 }
02150 else {
02151 fFirst = list[0];
02152 fLast = list[count-1];
02153 }
02154
02155 delete [] list;
02156
02157 DoRedraw();
02158
02159 return 1;
02160 }
02161
02162
02163 Int_t TGListTree::SortSiblings(TGListTreeItem *item)
02164 {
02165
02166
02167 return Sort(item);
02168 }
02169
02170
02171 Int_t TGListTree::SortChildren(TGListTreeItem *item)
02172 {
02173
02174
02175 TGListTreeItem *first;
02176
02177 if (item) {
02178 first = item->fFirstchild;
02179 if (first) {
02180 SortSiblings(first);
02181 }
02182 } else {
02183 if (fFirst) {
02184 first = fFirst->fFirstchild;
02185 if (first) {
02186 SortSiblings(first);
02187 }
02188 }
02189 }
02190 DoRedraw();
02191 return 1;
02192 }
02193
02194
02195 TGListTreeItem *TGListTree::FindSiblingByName(TGListTreeItem *item, const char *name)
02196 {
02197
02198
02199
02200 if (item) {
02201 while (item->fPrevsibling) {
02202 item = item->fPrevsibling;
02203 }
02204
02205 while (item) {
02206 if (strcmp(item->GetText(), name) == 0) {
02207 return item;
02208 }
02209 item = item->fNextsibling;
02210 }
02211 return item;
02212 }
02213 return 0;
02214 }
02215
02216
02217 TGListTreeItem *TGListTree::FindSiblingByData(TGListTreeItem *item, void *userData)
02218 {
02219
02220
02221
02222 if (item) {
02223 while (item->fPrevsibling) {
02224 item = item->fPrevsibling;
02225 }
02226
02227 while (item) {
02228 if (item->GetUserData() == userData) {
02229 return item;
02230 }
02231 item = item->fNextsibling;
02232 }
02233 return item;
02234 }
02235 return 0;
02236 }
02237
02238
02239 TGListTreeItem *TGListTree::FindChildByName(TGListTreeItem *item, const char *name)
02240 {
02241
02242
02243
02244 if (item && item->fFirstchild) {
02245 item = item->fFirstchild;
02246 } else if (!item && fFirst) {
02247 item = fFirst;
02248 } else {
02249 item = 0;
02250 }
02251
02252 while (item) {
02253 if (strcmp(item->GetText(), name) == 0) {
02254 return item;
02255 }
02256 item = item->fNextsibling;
02257 }
02258 return 0;
02259 }
02260
02261
02262 TGListTreeItem *TGListTree::FindChildByData(TGListTreeItem *item, void *userData)
02263 {
02264
02265
02266
02267 if (item && item->fFirstchild) {
02268 item = item->fFirstchild;
02269 } else if (!item && fFirst) {
02270 item = fFirst;
02271 } else {
02272 item = 0;
02273 }
02274
02275 while (item) {
02276 if (item->GetUserData() == userData) {
02277 return item;
02278 }
02279 item = item->fNextsibling;
02280 }
02281 return 0;
02282 }
02283
02284
02285 TGListTreeItem *TGListTree::FindItemByPathname(const char *path)
02286 {
02287
02288
02289
02290 if (!path || !*path) return 0;
02291
02292 const char *p = path, *s;
02293 char dirname[1024];
02294 TGListTreeItem *item = 0;
02295 item = FindChildByName(item, "/");
02296 TGListTreeItem *diritem = 0;
02297 TString fulldir;
02298
02299 start:
02300 while (1) {
02301 while (*p && *p == '/') p++;
02302 if (!*p) break;
02303
02304 s = strchr(p, '/');
02305
02306 if (!s) {
02307 strlcpy(dirname, p, 1024);
02308 } else {
02309 strlcpy(dirname, p, (s-p)+1);
02310 }
02311
02312 item = FindChildByName(item, dirname);
02313
02314 if (!diritem && dirname[0]) {
02315 fulldir += "/";
02316 fulldir += dirname;
02317
02318 if ((diritem=FindChildByName(0, fulldir.Data()))) {
02319 if (!s || !strlen(s)) return diritem;
02320 p = ++s;
02321 item = diritem;
02322 goto start;
02323 }
02324 }
02325
02326 if (!s || !strlen(s)) return item;
02327 p = ++s;
02328 }
02329 return 0;
02330 }
02331
02332
02333 void TGListTree::HighlightItem(TGListTreeItem *item)
02334 {
02335
02336
02337 UnselectAll(kFALSE);
02338 HighlightItem(item, kTRUE, kFALSE);
02339 AdjustPosition(item);
02340 }
02341
02342
02343 void TGListTree::ClearHighlighted()
02344 {
02345
02346
02347 UnselectAll(kFALSE);
02348 }
02349
02350
02351 void TGListTree::GetPathnameFromItem(TGListTreeItem *item, char *path, Int_t depth)
02352 {
02353
02354
02355
02356 char tmppath[1024];
02357
02358 *path = '\0';
02359 while (item) {
02360 snprintf(tmppath, 1023, "/%s%s", item->GetText(), path);
02361 strlcpy(path, tmppath, 1024);
02362 item = item->fParent;
02363 if (--depth == 0 && item) {
02364 snprintf(tmppath, 1023, "...%s", path);
02365 strlcpy(path, tmppath, 1024);
02366 return;
02367 }
02368 }
02369 }
02370
02371
02372 Pixel_t TGListTree::GetGrayPixel()
02373 {
02374
02375
02376 static Bool_t init = kFALSE;
02377 if (!init) {
02378 if (!gClient->GetColorByName("#808080", fgGrayPixel))
02379 fgGrayPixel = fgBlackPixel;
02380 init = kTRUE;
02381 }
02382 return fgGrayPixel;
02383 }
02384
02385
02386 FontStruct_t TGListTree::GetDefaultFontStruct()
02387 {
02388
02389
02390 if (!fgDefaultFont)
02391 fgDefaultFont = gClient->GetResourcePool()->GetIconFont();
02392 return fgDefaultFont->GetFontStruct();
02393 }
02394
02395
02396 const TGGC &TGListTree::GetDrawGC()
02397 {
02398
02399
02400 if (!fgDrawGC) {
02401 GCValues_t gcv;
02402
02403 gcv.fMask = kGCLineStyle | kGCLineWidth | kGCFillStyle |
02404 kGCForeground | kGCBackground | kGCFont;
02405 gcv.fLineStyle = kLineSolid;
02406 gcv.fLineWidth = 0;
02407 gcv.fFillStyle = kFillSolid;
02408 gcv.fFont = fgDefaultFont->GetFontHandle();
02409 gcv.fBackground = fgWhitePixel;
02410 gcv.fForeground = fgBlackPixel;
02411
02412 fgDrawGC = gClient->GetGC(&gcv, kTRUE);
02413 }
02414 return *fgDrawGC;
02415 }
02416
02417
02418 const TGGC &TGListTree::GetLineGC()
02419 {
02420
02421
02422 if (!fgLineGC) {
02423 GCValues_t gcv;
02424
02425 gcv.fMask = kGCLineStyle | kGCLineWidth | kGCFillStyle |
02426 kGCForeground | kGCBackground | kGCFont;
02427 gcv.fLineStyle = kLineOnOffDash;
02428 gcv.fLineWidth = 0;
02429 gcv.fFillStyle = kFillSolid;
02430 gcv.fFont = fgDefaultFont->GetFontHandle();
02431 gcv.fBackground = fgWhitePixel;
02432 gcv.fForeground = GetGrayPixel();
02433
02434 fgLineGC = gClient->GetGC(&gcv, kTRUE);
02435 fgLineGC->SetDashOffset(0);
02436 fgLineGC->SetDashList("\x1\x1", 2);
02437 }
02438 return *fgLineGC;
02439 }
02440
02441
02442 const TGGC &TGListTree::GetHighlightGC()
02443 {
02444
02445
02446 if (!fgHighlightGC) {
02447 GCValues_t gcv;
02448
02449 gcv.fMask = kGCLineStyle | kGCLineWidth | kGCFillStyle |
02450 kGCForeground | kGCBackground | kGCFont;
02451 gcv.fLineStyle = kLineSolid;
02452 gcv.fLineWidth = 0;
02453 gcv.fFillStyle = kFillSolid;
02454 gcv.fFont = fgDefaultFont->GetFontHandle();
02455 gcv.fBackground = fgDefaultSelectedBackground;
02456 gcv.fForeground = fgWhitePixel;
02457
02458 fgHighlightGC = gClient->GetGC(&gcv, kTRUE);
02459 }
02460 return *fgHighlightGC;
02461 }
02462
02463
02464 const TGGC &TGListTree::GetColorGC()
02465 {
02466
02467
02468 if (!fgColorGC) {
02469 GCValues_t gcv;
02470
02471 gcv.fMask = kGCLineStyle | kGCLineWidth | kGCFillStyle |
02472 kGCForeground | kGCBackground;
02473 gcv.fLineStyle = kLineSolid;
02474 gcv.fLineWidth = 1;
02475 gcv.fFillStyle = kFillSolid;
02476 gcv.fBackground = fgDefaultSelectedBackground;
02477 gcv.fForeground = fgWhitePixel;
02478
02479 fgColorGC = gClient->GetGC(&gcv, kTRUE);
02480 }
02481 return *fgColorGC;
02482 }
02483
02484
02485 const TGPicture *TGListTree::GetOpenPic()
02486 {
02487
02488
02489 if (!fgOpenPic)
02490 fgOpenPic = gClient->GetPicture("ofolder_t.xpm");
02491 ((TGPicture *)fgOpenPic)->AddReference();
02492 return fgOpenPic;
02493 }
02494
02495
02496 const TGPicture *TGListTree::GetClosedPic()
02497 {
02498
02499
02500 if (!fgClosedPic)
02501 fgClosedPic = gClient->GetPicture("folder_t.xpm");
02502 ((TGPicture *)fgClosedPic)->AddReference();
02503 return fgClosedPic;
02504 }
02505
02506
02507 const TGPicture *TGListTree::GetCheckedPic()
02508 {
02509
02510
02511 if (!fgCheckedPic)
02512 fgCheckedPic = gClient->GetPicture("checked_t.xpm");
02513 ((TGPicture *)fgCheckedPic)->AddReference();
02514 return fgCheckedPic;
02515 }
02516
02517
02518 const TGPicture *TGListTree::GetUncheckedPic()
02519 {
02520
02521
02522 if (!fgUncheckedPic)
02523 fgUncheckedPic = gClient->GetPicture("unchecked_t.xpm");
02524 ((TGPicture *)fgUncheckedPic)->AddReference();
02525 return fgUncheckedPic;
02526 }
02527
02528
02529 void TGListTree::SavePrimitive(ostream &out, Option_t *option )
02530 {
02531
02532
02533 if (fBackground != GetWhitePixel()) SaveUserColor(out, option);
02534
02535 out << endl << " // list tree" << endl;
02536 out << " TGListTree *";
02537
02538 if ((fParent->GetParent())->InheritsFrom(TGCanvas::Class())) {
02539 out << GetName() << " = new TGListTree(" << GetCanvas()->GetName();
02540 } else {
02541 out << GetName() << " = new TGListTree(" << fParent->GetName();
02542 out << "," << GetWidth() << "," << GetHeight();
02543 }
02544
02545 if (fBackground == GetWhitePixel()) {
02546 if (GetOptions() == kSunkenFrame) {
02547 out <<");" << endl;
02548 } else {
02549 out << "," << GetOptionString() <<");" << endl;
02550 }
02551 } else {
02552 out << "," << GetOptionString() << ",ucolor);" << endl;
02553 }
02554 if (option && strstr(option, "keep_names"))
02555 out << " " << GetName() << "->SetName(\"" << GetName() << "\");" << endl;
02556
02557 out << endl;
02558
02559 static Int_t n = 0;
02560
02561 TGListTreeItem *current;
02562 current = GetFirstItem();
02563
02564 out << " const TGPicture *popen; //used for list tree items" << endl;
02565 out << " const TGPicture *pclose; //used for list tree items" << endl;
02566 out << endl;
02567
02568 while (current) {
02569 out << " TGListTreeItem *item" << n << " = " << GetName() << "->AddItem(";
02570 current->SavePrimitive(out, TString::Format("%d",n), n);
02571 if (current->IsOpen())
02572 out << " " << GetName() << "->OpenItem(item" << n << ");" << endl;
02573 else
02574 out << " " << GetName() << "->CloseItem(item" << n << ");" << endl;
02575
02576 if (current == fSelected)
02577 out << " " << GetName() << "->SetSelected(item" << n << ");" << endl;
02578
02579 n++;
02580 if (current->fFirstchild) {
02581 SaveChildren(out, current->fFirstchild, n);
02582 }
02583 current = current->fNextsibling;
02584 }
02585
02586 out << endl;
02587 }
02588
02589
02590 void TGListTree::SaveChildren(ostream &out, TGListTreeItem *item, Int_t &n)
02591 {
02592
02593
02594 Int_t p = n-1;
02595 while (item) {
02596 out << " TGListTreeItem *item" << n << " = " << GetName() << "->AddItem(";
02597 item->SavePrimitive(out, TString::Format("%d",p),n);
02598 n++;
02599 if (item->fFirstchild) {
02600 SaveChildren(out, item->fFirstchild, n);
02601 }
02602 item = item->fNextsibling;
02603 }
02604 }
02605
02606
02607 void TGListTreeItemStd::SavePrimitive(ostream &out, Option_t *option, Int_t n)
02608 {
02609
02610
02611 static const TGPicture *oldopen=0;
02612 static const TGPicture *oldclose=0;
02613 static const TGPicture *oldcheck=0;
02614 static const TGPicture *olduncheck=0;
02615 static Bool_t makecheck = kTRUE;
02616 static Bool_t makeuncheck = kTRUE;
02617 static Color_t oldcolor = -1;
02618
02619 char quote = '"';
02620 TString s = TString::Format("%d", n);
02621
02622 if (!fParent)
02623 out << "NULL,";
02624 else
02625 out << "item" << option << ",";
02626 TString text = GetText();
02627 text.ReplaceAll('\\', "\\\\");
02628 text.ReplaceAll("\"", "\\\"");
02629 out << quote << text << quote;
02630 out << ");" << endl;
02631
02632 if (oldopen != fOpenPic) {
02633 oldopen = fOpenPic;
02634 out << " popen = gClient->GetPicture(" << quote
02635 << gSystem->ExpandPathName(gSystem->UnixPathName(fOpenPic->GetName()))
02636 << quote << ");" << endl;
02637 }
02638 if (oldclose != fClosedPic) {
02639 oldclose = fClosedPic;
02640 out << " pclose = gClient->GetPicture(" << quote
02641 << gSystem->ExpandPathName(gSystem->UnixPathName(fClosedPic->GetName()))
02642 << quote << ");" << endl;
02643 }
02644 out << " item" << s.Data() << "->SetPictures(popen, pclose);" << endl;
02645 if (HasCheckBox()) {
02646 if (fCheckedPic && makecheck) {
02647 out << " const TGPicture *pcheck; //used for checked items" << endl;
02648 makecheck = kFALSE;
02649 }
02650 if (fUncheckedPic && makeuncheck) {
02651 out << " const TGPicture *puncheck; //used for unchecked items" << endl;
02652 makeuncheck = kFALSE;
02653 }
02654 out << " item" << s.Data() << "->CheckItem();" << endl;
02655 if (fCheckedPic && oldcheck != fCheckedPic) {
02656 oldcheck = fCheckedPic;
02657 out << " pcheck = gClient->GetPicture(" << quote
02658 << gSystem->ExpandPathName(gSystem->UnixPathName(fCheckedPic->GetName()))
02659 << quote << ");" << endl;
02660 }
02661 if (fUncheckedPic && olduncheck != fUncheckedPic) {
02662 olduncheck = fUncheckedPic;
02663 out << " puncheck = gClient->GetPicture(" << quote
02664 << gSystem->ExpandPathName(gSystem->UnixPathName(fUncheckedPic->GetName()))
02665 << quote << ");" << endl;
02666 }
02667 out << " item" << s.Data() << "->SetCheckBoxPictures(pcheck, puncheck);" << endl;
02668 out << " item" << s.Data() << "->SetCheckBox(kTRUE);" << endl;
02669 }
02670 if (fHasColor) {
02671 if (oldcolor != fColor) {
02672 oldcolor = fColor;
02673 out << " item" << s.Data() << "->SetColor(" << fColor << ");" << endl;
02674 }
02675 }
02676 if (fTipText.Length() > 0) {
02677 TString tiptext = GetTipText();
02678 tiptext.ReplaceAll('\\', "\\\\");
02679 tiptext.ReplaceAll("\n", "\\n");
02680 tiptext.ReplaceAll("\"", "\\\"");
02681 out << " item" << s.Data() << "->SetTipText(" << quote
02682 << tiptext << quote << ");" << endl;
02683 }
02684
02685 }
02686
02687
02688 void TGListTree::CheckItem(TGListTreeItem *item, Bool_t check)
02689 {
02690
02691
02692 item->CheckItem(check);
02693 }
02694
02695
02696 void TGListTree::SetCheckBox(TGListTreeItem *item, Bool_t on)
02697 {
02698
02699
02700 item->SetCheckBox(on);
02701 }
02702
02703
02704 void TGListTree::ToggleItem(TGListTreeItem *item)
02705 {
02706
02707
02708 item->Toggle();
02709 }
02710
02711
02712 void TGListTree::UpdateChecked(TGListTreeItem *item, Bool_t redraw)
02713 {
02714
02715
02716 if (fAutoCheckBoxPic == kFALSE) return;
02717
02718 TGListTreeItem *parent;
02719 TGListTreeItem *current;
02720 current = item->GetFirstChild();
02721 parent = current ? current : item;
02722
02723 while (parent && parent->HasCheckBox()) {
02724 if ((!parent->IsChecked() && parent->HasCheckedChild(kTRUE)) ||
02725 (parent->IsChecked() && parent->HasUnCheckedChild(kTRUE))) {
02726 parent->SetCheckBoxPictures(fClient->GetPicture("checked_dis_t.xpm"),
02727 fClient->GetPicture("unchecked_dis_t.xpm"));
02728 }
02729 else {
02730 parent->SetCheckBoxPictures(fClient->GetPicture("checked_t.xpm"),
02731 fClient->GetPicture("unchecked_t.xpm"));
02732 }
02733 parent = parent->GetParent();
02734 if (parent && fCheckMode == kRecursive) {
02735 if (!parent->IsChecked() && parent->GetFirstChild() &&
02736 !parent->GetFirstChild()->HasUnCheckedChild()) {
02737 parent->SetCheckBoxPictures(fClient->GetPicture("checked_t.xpm"),
02738 fClient->GetPicture("unchecked_t.xpm"));
02739 parent->CheckItem(kTRUE);
02740 }
02741 else if (parent->IsChecked() && parent->GetFirstChild() &&
02742 !parent->GetFirstChild()->HasCheckedChild()) {
02743 parent->SetCheckBoxPictures(fClient->GetPicture("checked_t.xpm"),
02744 fClient->GetPicture("unchecked_t.xpm"));
02745 parent->CheckItem(kFALSE);
02746 }
02747 }
02748 }
02749 if (redraw) {
02750 ClearViewPort();
02751 }
02752 }
02753
02754
02755 TGListTreeItem *TGListTree::FindItemByObj(TGListTreeItem *item, void *ptr)
02756 {
02757
02758
02759
02760 TGListTreeItem *fitem;
02761 if (item && ptr) {
02762 if (item->GetUserData() == ptr)
02763 return item;
02764 else {
02765 if (item->fFirstchild) {
02766 fitem = FindItemByObj(item->fFirstchild, ptr);
02767 if (fitem) return fitem;
02768 }
02769 return FindItemByObj(item->fNextsibling, ptr);
02770 }
02771 }
02772 return 0;
02773 }
02774
02775
02776 void TGListTree::GetChecked(TList *checked)
02777 {
02778
02779
02780
02781
02782 if (!checked || !fFirst) return;
02783 TGListTreeItem *current = fFirst;
02784 if (current->IsChecked()) {
02785 checked->Add(new TObjString(current->GetText()));
02786 }
02787 while(current) {
02788 if (current->GetFirstChild())
02789 GetCheckedChildren(checked, current->GetFirstChild());
02790 current = current->GetNextSibling();
02791 }
02792 }
02793
02794
02795 void TGListTree::GetCheckedChildren(TList *checked, TGListTreeItem *item)
02796 {
02797
02798
02799 if (!checked || !item) return;
02800
02801 while (item) {
02802 if (item->IsChecked()) {
02803 checked->Add(new TObjString(item->GetText()));
02804 }
02805 if (item->GetFirstChild()) {
02806 GetCheckedChildren(checked, item->GetFirstChild());
02807 }
02808 item = item->GetNextSibling();
02809 }
02810 }
02811
02812
02813 void TGListTree::CheckAllChildren(TGListTreeItem *item, Bool_t state)
02814 {
02815
02816
02817
02818 if (item)
02819 item->CheckAllChildren(state);
02820 }
02821