00001 #include "MultiPage.h"
00002 #include "GfxProxy.h"
00003 #include "GfxCfg.h"
00004 #include "ViewState.h"
00005 #include "MultiPageObject.h"
00006
00007 #include <Midad/Base/PageProxy.h>
00008 #include <Midad/Base/PageDisplay.h>
00009 #include <Midad/Base/DigitText.h>
00010 #include <Midad/Base/ZoomPad.h>
00011 #include <Midad/Base/ColorAxis.h>
00012 #include <Midad/Base/RangeAxis.h>
00013 #include <Midad/Base/Mint.h>
00014 #include <Midad/Base/GfxButton.h>
00015
00016 #include <Midad/Util/RangeControl.h>
00017 #include <Midad/Util/CompositeRange.h>
00018 #include <Midad/Gui/GuiBox.h>
00019 #include <Midad/Gui/GuiCanvas.h>
00020 #include <Midad/Gui/GuiSlider.h>
00021
00022 #include <JobControl/JobC.h>
00023 #include <Conventions/Munits.h>
00024
00025 #include <TCanvas.h>
00026 #include <TH1F.h>
00027
00028
00029 #include <sigc++/sigc++.h>
00030 #include <sigc++/class_slot.h>
00031 using namespace SigC;
00032
00033
00034 static PageProxy<MultiPage> gsMultiPageProxy("Multi");
00035
00036 MultiPage::MultiPage()
00037 : fPageDisplay(0)
00038 , fMint(0)
00039 , fZoomHistory(0)
00040 , fCompositeRange(0)
00041 {
00042 fZoomHistory = manage(new UndoHistory);
00043 fCompositeRange = manage(new CompositeRange<double>);
00044 }
00045
00046 MultiPage::~MultiPage()
00047 {
00048 fPad[0]->Clear();
00049 fPad[1]->Clear();
00050 }
00051
00052 TObject* MultiPage::Init(Mint* mint, PageDisplay* pd, GuiBox& box)
00053 {
00054 this->CanvasPage::Init(mint,pd,box);
00055
00056 fMint = mint;
00057 fPageDisplay = pd;
00058
00059 fViewState[0] = manage(new ViewState);
00060 fViewState[1] = manage(new ViewState);
00061
00062 this->BuildMenus();
00063
00064
00065
00066 fRClist.push_back(fPageDisplay->GetTimeSlider().GetSignals().released.connect
00067 (slot_class(*this,&MultiPage::Update)));
00068
00069 TCanvas& canvas = this->GetCanvas();
00070
00071 RangeDouble* spatial_range[3];
00072 for (int i=0; i<3; ++i) {
00073 spatial_range[i] = manage(new RangeDouble(0,1));
00074 fSpatialControl[i] = new RangeControl<double>(fZoomHistory,
00075 spatial_range[i]);
00076 }
00077
00078
00079 const double x1=0.03, x2=0.90, x3=0.95;
00080
00081 const double centerline = 0.50, separation=0.02;
00082 const double y1=0.05, y2=centerline-separation;
00083 const double y3=centerline+separation, y4=0.95;
00084 const double xruv=x1*0.75, yrz=0.5*(y2+y3);
00085
00086 fPad[0] = new ZoomPad("U View", "U View", x1,y3, x2,y4);
00087 fPad[1] = new ZoomPad("V View", "V View", x1,y1, x2,y2);
00088
00089 fRangeAxis[0] = new RangeAxis(xruv,y3, xruv,y4);
00090 fRangeAxis[1] = new RangeAxis(xruv,y1, xruv,y2);
00091 fRangeAxis[2] = new RangeAxis(x1,yrz, x2,yrz);
00092
00093 for (int i = 0; i < 3; ++i) {
00094 fRangeAxis[i]->UseRange(spatial_range[i]);
00095 fRangeAxis[i]->SetLabelSize(0.5*fRangeAxis[i]->GetLabelSize());
00096 }
00097
00098 RangeDouble* color_range[2];
00099 for (int i = 0; i<2; ++i) {
00100 color_range[i] = manage(new RangeDouble(0,1));
00101 fColorControl[i] = new RangeControl<double>(fZoomHistory,color_range[i]);
00102
00103 fPad[i]->UseCurRangeX(spatial_range[2]);
00104 fPad[i]->selection.connect(bind(slot_class(*this,&MultiPage::SelectionZoom),fPad[i]));
00105 }
00106 fPad[0]->UseCurRangeY(spatial_range[0]);
00107 fPad[1]->UseCurRangeY(spatial_range[1]);
00108
00109 fColorAxis[0] = new ColorAxis(50,0.05, color_range[0], x3,y3+0.05, x3,y4-0.05, 505,"+L");
00110 fColorAxis[1] = new ColorAxis(50,0.05, color_range[1], x3,y1+0.05, x3,y2-0.05, 505,"+L");
00111 fColorButton[0] = manage(new GfxButton("time",x2,y4-0.05,x3,y4));
00112 fColorButton[1] = manage(new GfxButton("time",x2,y2-0.05,x3,y2));
00113
00114 for (int i=0; i<2; ++i) {
00115 fColorAxis[i]->SetScale(Munits::ns);
00116 RangeDouble& sel = fColorAxis[i]->GetSelectionRange();
00117 sel.modified.connect(bind(slot(*(fColorControl[i]),&RangeControl<double>::Apply),&sel));
00118 sel.modified.connect(slot_class(*this,&MultiPage::UpdateCanvas));
00119
00120 fColorButton[i]->clicked.connect(slot(*fViewState[i],&ViewState::ToggleColorSemantic));
00121 fViewState[i]->color_semantic.connect(bind(slot_class(*this,
00122 &MultiPage::ColorSemanticHandler),i));
00123 fViewState[i]->show_multiplex.connect(slot_class(*this,&MultiPage::Update));
00124 fViewState[i]->spatial_metric.connect(slot_class(*this,&MultiPage::Update));
00125 }
00126
00127 for (int i=0; i<3; ++i) {
00128 RangeDouble& s = fRangeAxis[i]->GetSelectionRange();
00129 s.modified.connect(bind(slot(*(fSpatialControl[i]),
00130 &RangeControl<double>::Apply),&s));
00131
00132 fRClist.push_back(spatial_range[i]->modified.connect
00133 (slot_class(*this,&MultiPage::UpdateCanvas)));
00134 }
00135
00136 canvas.cd();
00137
00138 this->Clear();
00139 fPad[0]->SetBorderSize(1);
00140 fPad[1]->SetBorderSize(1);
00141 fPad[0]->SetBorderMode(1);
00142 fPad[1]->SetBorderMode(1);
00143 fColorButton[0]->SetFillColor(2);
00144 fColorButton[1]->SetFillColor(2);
00145
00146 fPad[0]->Draw();
00147 fPad[1]->Draw();
00148 fRangeAxis[0]->Draw();
00149 fRangeAxis[1]->Draw();
00150 fRangeAxis[2]->Draw();
00151
00152 canvas.cd();
00153 fColorAxis[0]->Draw();
00154 fColorAxis[1]->Draw();
00155 fColorButton[0]->Draw();
00156 fColorButton[1]->Draw();
00157
00158
00159
00160
00161
00162 const char* default_gfx[] = {
00163 "DigitList",
00164 "TrackList",
00165 0
00166 };
00167 for (int ind=0; default_gfx[ind]; ++ind) this->AddGfx(default_gfx[ind]);
00168
00169
00170 this->Clear();
00171 this->Update();
00172 return new MultiPageObject(this);
00173 }
00174
00175
00176 static void toggle_mux(GuiMenu* menu,
00177 GuiMenu::GuiMenuList::iterator mit,
00178 ViewState* view_state)
00179 {
00180 bool show_mux = view_state->ShowMultiplex();
00181 menu->CheckEntry(mit,show_mux);
00182 }
00183
00184 void MultiPage::BuildMenus(void)
00185 {
00186 GuiMenuBar& mb = fPageDisplay->GetMenuBar();
00187 GuiMenu* pm = mb.GetMenu("Pages");
00188 if (!pm) return;
00189
00190 static int ninstances = 0;
00191
00192
00193 GuiMenu* mymenu = manage(new GuiMenu);
00194 pm->Add(Form("Multi (%d)",++ninstances),*mymenu);
00195
00196 GuiMenu::GuiMenuList::iterator mit;
00197
00198
00199 const char* mux_labels[2] = {
00200 "U vs. Z multiplexing",
00201 "V vs. Z multiplexing",
00202 };
00203 for (int ind = 0; ind < 2; ++ind) {
00204 mit = mymenu->Add(mux_labels[ind]);
00205
00206 ViewState* vs = fViewState[ind];
00207 mymenu->CheckEntry(mit,vs->ShowMultiplex());
00208 (*mit)->Connect(slot(*vs,&ViewState::ToggleMultiplex));
00209 vs->show_multiplex.connect(bind(bind(bind(slot(toggle_mux),vs),mit),mymenu));
00210 }
00211
00212
00213 mit = mymenu->Add("Use real coords");
00214 (*mit)->Connect(bind(slot_class(*this,&MultiPage::ToggleRealCoords),mymenu,mit));
00215
00216 mymenu->Add(0);
00217
00218 GuiMenu* add_menu = manage(new GuiMenu);
00219 mymenu->Add("Add Gfx",*add_menu);
00220
00221 list<const char*> gfx_names = GfxProxyBase::GetRegisteredNames();
00222 list<const char*>::iterator it, done = gfx_names.end();
00223
00224 for (it = gfx_names.begin(); it != done; ++it) {
00225 const char* name = *it;
00226 mit = add_menu->Add(name,bind(slot_class(*this,&MultiPage::AddGfx),name));
00227 (*mit)->Connect(slot_class(*this,&MultiPage::Update));
00228 }
00229
00230 mymenu->Add(0);
00231
00232 NamedFactory& nf = NamedFactory::Instance("Gfx");
00233 for (it = gfx_names.begin(); it != done; ++it) {
00234 const char* name = *it;
00235 GfxProxyBase* gpb = dynamic_cast<GfxProxyBase*>(nf.GetProxy(name));
00236 if (!gpb) {
00237 cerr << "Failed to get GfxProxy for " << name << endl;
00238 continue;
00239 }
00240 GuiMenu * gfx_menu = gpb->MakeMenu(this);
00241 if (! gfx_menu) continue;
00242 gfx_menu = manage(gfx_menu);
00243 mymenu->Add(name, *gfx_menu);
00244
00245 }
00246 }
00247
00248 void MultiPage::ToggleRealCoords(GuiMenu* menu, GuiMenu::GuiMenuList::iterator mit)
00249 {
00250
00251 bool is_real = ! menu->IsEntryChecked(mit);
00252 menu->CheckEntry(mit,is_real);
00253
00254 for (int ind = 0; ind < 2; ++ind) {
00255 fViewState[ind]->SetSpatialMetric(is_real ?
00256 ViewState::metric_is_continuous :
00257 ViewState::metric_is_discreet);
00258 }
00259
00260 this->FullZoom();
00261 }
00262
00263 void MultiPage::AddGfx(const char* gfx_name)
00264 {
00265 GfxProxyBase* gpb = dynamic_cast<GfxProxyBase*>
00266 (NamedFactory::Instance("Gfx").GetProxy(gfx_name));
00267 if (!gpb) {
00268 cerr << "Failed to get " << gfx_name << " proxy\n";
00269 return;
00270 }
00271
00272 PlaneView::PlaneView_t view[2] = {
00273 PlaneView::kU,
00274 PlaneView::kV
00275 };
00276
00277 TVirtualPad* old_pad = gPad;
00278 for (int ind = 0; ind < 2; ++ind) {
00279 fPad[ind]->cd();
00280
00281 GfxBase* gfx_base = gpb->Create();
00282 if (!gfx_base) {
00283 cerr << "Failed to create " << gfx_name << endl;
00284 break;
00285 }
00286
00287 gfx_base->text_info.connect(slot_class(*fPageDisplay,&PageDisplay::StatusBar));
00288 gfx_base->SetPlaneView(view[ind]);
00289 gfx_base->SetViewState(fViewState[ind]);
00290
00291 gfx_base->GetCfg().modified_signal.connect(slot_class(*this,&MultiPage::UpdateCanvas));
00292 gfx_base->Init(*fPageDisplay,*this);
00293
00294 fGfxList[gfx_base] = GfxInfo(view[ind]);
00295 }
00296 gPad = old_pad;
00297 this->Update();
00298 }
00299
00300 void MultiPage::InitView(PlaneView::PlaneView_t view)
00301 {
00302
00303 int ind = view - PlaneView::kU;
00304 fPad[ind]->cd();
00305 char cview[2] = "U";
00306 cview[0] += ind;
00307
00308
00309
00310 const char* hard_coded_default_gfx[] = {
00311 "DigitList",
00312 "StripList",
00313 "TrackList",
00314 0
00315 };
00316
00317 for (int ind=0; hard_coded_default_gfx[ind]; ++ind) {
00318 const char* gfx_name = hard_coded_default_gfx[ind];
00319 this->AddGfx(gfx_name);
00320 }
00321
00322 }
00323
00324
00325 void MultiPage::Clear()
00326 {
00327 fZoomHistory->Clear();
00328
00329 this->BlockRanges(true);
00330 this->FullZoom();
00331 this->BlockRanges(false);
00332 }
00333
00334 void MultiPage::FullZoom()
00335 {
00336 if (!fMint) return;
00337 if (fMint->GetDetector() == Detector::kUnknown) return;
00338 UgliGeomHandle ugh = fMint->GetUgliGeomHandle();
00339 if (! ugh.IsValid()) {
00340 cerr << "MultiPage::FullZoom: no valid geometry\n";
00341 return;
00342 }
00343
00344
00345 if (fViewState[0]->GetSpatialMetric() == ViewState::metric_is_discreet) {
00346 vector<UgliScintPlnHandle> usphv = ugh.GetScintPlnHandleVector();
00347 vector<UgliScintPlnHandle>::reverse_iterator rit, rdone = usphv.rend();
00348
00349 for (rit = usphv.rbegin(); rit != rdone; ++rit) {
00350 if (! rit->GetPlexPlaneId().IsVetoShield()) break;
00351 }
00352 if (rit == rdone) {
00353 cerr << "MultiPage::FullZoom: WTF, can't get last plane!\n";
00354 return;
00355 }
00356
00357 int first_plane = usphv[0].GetPlaneNumber(), last_plane = rit->GetPlaneNumber();
00358
00359
00360 int n_strips = usphv[0].NumberOfStrips();
00361
00362 fPad[0]->Range(first_plane,0,last_plane+1,n_strips);
00363 fPad[1]->Range(first_plane,0,last_plane+1,n_strips);
00364
00365 }
00366 else {
00367 float tmin, tmax, zmin, zmax;
00368 ugh.GetZExtent(zmin,zmax);
00369
00370 ugh.GetTransverseExtent(PlaneView::kU,tmin,tmax);
00371 fPad[0]->Range(zmin,tmin,zmax,tmax);
00372
00373 ugh.GetTransverseExtent(PlaneView::kV,tmin,tmax);
00374 fPad[1]->Range(zmin,tmin,zmax,tmax);
00375 }
00376 }
00377
00378 void MultiPage::BlockRanges(bool tf)
00379 {
00380 for (unsigned int ind = 0; ind < fRClist.size(); ++ind)
00381 fRClist[ind].block(tf);
00382 }
00383
00384 void MultiPage::Update()
00385 {
00386 if (!fMint) return;
00387
00388 this->ColorSemanticHandler(0);
00389 this->ColorSemanticHandler(1);
00390
00391 this->UpdateView(PlaneView::kU);
00392 this->UpdateView(PlaneView::kV);
00393 this->UpdateCanvas();
00394 }
00395 void MultiPage::UpdateCanvas()
00396 {
00397 fPad[0]->Modified();
00398 fPad[1]->Modified();
00399 this->GetCanvas().Modified();
00400 this->GetCanvas().Update();
00401 }
00402
00403 void MultiPage::UpdateView(PlaneView::PlaneView_t view)
00404 {
00405
00406 int ind = view - PlaneView::kU;
00407 fPad[ind]->cd();
00408
00409
00410 GfxList::iterator it, done = fGfxList.end();
00411 for (it = fGfxList.begin(); it != done; ++it) {
00412 if (it->second.view_type == view) {
00413 it->first->Configure(*fMint);
00414 it->first->Draw();
00415 }
00416 }
00417 }
00418
00419 void MultiPage::SelectionZoom(ZoomPad* zp)
00420 {
00421 fCompositeRange->push_back(fPad[0]->GetCurRange().x);
00422 fCompositeRange->push_back(fPad[0]->GetCurRange().y);
00423 fCompositeRange->push_back(fPad[1]->GetCurRange().x);
00424 fCompositeRange->push_back(fPad[1]->GetCurRange().y);
00425 fZoomHistory->Store(*fCompositeRange);
00426 zp->ApplySelectionToZoom();
00427 }
00428
00429 void MultiPage::Unzoom()
00430 {
00431 fZoomHistory->Undo();
00432 this->UpdateCanvas();
00433 }
00434 void MultiPage::Rezoom()
00435 {
00436 fZoomHistory->Redo();
00437 this->UpdateCanvas();
00438 }
00439 RangeControl<double> MultiPage::GetColorRangeControl(PlaneView::PlaneView_t view)
00440 {
00441 int iview = 0;
00442 if (view == PlaneView::kV) iview = 1;
00443 return *fColorControl[iview];
00444 }
00445 void MultiPage::ColorSemanticHandler(int which)
00446 {
00447 if (which < 0 || which > 2) return;
00448
00449 GfxButton* but = fColorButton[which];
00450
00451 RangeDouble& cr = fColorControl[which]->GetRange();
00452
00453 switch (fViewState[which]->GetColorSemantic()) {
00454 case ViewState::color_is_charge:
00455 but->SetTitle("charge");
00456 fColorAxis[which]->SetScale(1.0);
00457 cr.SetFrom(fMint->GetChargeRange());
00458 break;
00459 case ViewState::color_is_time:
00460 but->SetTitle("time");
00461 fColorAxis[which]->SetScale(Munits::ns);
00462 cr.SetFrom(fMint->GetTimeRange());
00463 break;
00464 default:
00465 break;
00466 }
00467 fPad[which]->Modified();
00468 this->GetCanvas().Modified();
00469 but->Modified();
00470 }
00471
00472 ViewState* MultiPage::GetViewState(PlaneView::PlaneView_t view)
00473 {
00474 int iview = 0;
00475 if (view == PlaneView::kV) iview = 1;
00476 return fViewState[iview];
00477 }
00478