11 #include "TBufferJSON.h"
20 TWebCanvas(c,name,x,y,width,height)
22 printf(
"CREATING FULL CANVAS\n");
38 auto separ = sid.find(
"#");
40 bool search_hist =
false;
42 if (sid ==
"histogram") {
44 }
else if (separ == std::string::npos) {
47 kind = sid.substr(separ + 1);
48 id = std::stoul(sid.substr(0, separ));
51 if (!search_hist && TString::Hash(&pad,
sizeof(pad)) == id)
54 TObjLink *lnk = pad->GetListOfPrimitives()->FirstLink();
56 TObject *obj = lnk->GetObject();
61 TH1 *h1 = obj->InheritsFrom(TH1::Class()) ?
static_cast<TH1 *
>(obj) :
nullptr;
62 TGraph *gr = obj->InheritsFrom(TGraph::Class()) ?
static_cast<TGraph *
>(obj) :
nullptr;
67 auto offset = TGraph::Class()->GetDataMemberOffset(
"fHistogram");
69 return *((TH1 **)((
char*) gr + offset));
71 printf(
"ERROR: Cannot access fHistogram data member in TGraph\n");
79 if (TString::Hash(&obj,
sizeof(obj)) ==
id) {
83 if (gr && (kind.find(
"hist")==0)) {
85 obj = h1 = gr->GetHistogram();
87 if (!kind.empty() && (kind[0]==
'#')) kind.erase(0,1);
91 if (h1 && (kind ==
"x"))
92 return h1->GetXaxis();
93 if (h1 && (kind ==
"y"))
94 return h1->GetYaxis();
95 if (h1 && (kind ==
"z"))
96 return h1->GetZaxis();
98 if (!kind.empty() && (kind.compare(0,7,
"member_") == 0)) {
99 auto member = kind.substr(7);
100 auto offset = obj->IsA()->GetDataMemberOffset(member.c_str());
102 TObject **mobj = (TObject **)((
char*) obj + offset);
113 TIter fiter(h1 ? h1->GetListOfFunctions() : gr->GetListOfFunctions());
114 TObject *fobj =
nullptr;
115 while ((fobj = fiter()) !=
nullptr)
116 if (TString::Hash(&fobj,
sizeof(fobj)) == id) {
121 }
else if (obj->InheritsFrom(TPad::Class())) {
123 if (objpad && !*objpad)
139 if (TWebCanvas::ProcessData(connid, arg))
142 if (arg.compare(0, 8,
"GETMENU:") == 0) {
150 std::string buf =
"MENU:";
151 buf.append(TBufferJSON::ToJSON(&items, 103).Data());
153 AddToSendQueue(connid, buf);
155 }
else if (arg.compare(0, 8,
"PRIMIT6:") == 0) {
159 auto opt = TBufferJSON::FromJSON<TWebObjectOptions>(arg.c_str() + 8);
170 }
else if (arg.compare(0, 11,
"PADCLICKED:") == 0) {
172 auto click = TBufferJSON::FromJSON<TWebPadClick>(arg.c_str() + 11);
174 if (click && IsFirstConn(connid) && !
IsReadOnly()) {
176 TPad *pad =
dynamic_cast<TPad *
>(
FindPrimitive(click->padid));
177 if (pad && (pad != gPad)) {
178 Info(
"ProcessData",
"Activate pad %s", pad->GetName());
180 Canvas()->SetClickSelectedPad(pad);
185 if (!click->objid.empty()) {
187 Canvas()->SetClickSelected(selobj);
192 if ((click->x >= 0) && (click->y >= 0)) {
200 }
else if (arg.compare(0, 8,
"OBJEXEC:") == 0) {
202 auto buf = arg.substr(8);
203 auto pos = buf.find(
":");
205 if ((pos > 0) && IsFirstConn(connid) && !
IsReadOnly()) {
206 auto sid = buf.substr(0, pos);
207 buf.erase(0, pos + 1);
210 if (obj && !buf.empty()) {
212 while (!buf.empty()) {
213 std::string sub = buf;
214 auto pos = buf.find(
";;");
215 if (pos == std::string::npos) {
219 sub = buf.substr(0,pos);
220 buf = buf.substr(pos+2);
222 if (sub.empty())
continue;
224 std::stringstream exec;
225 exec <<
"((" << obj->ClassName() <<
" *) " << std::hex << std::showbase << (size_t)obj <<
")->" << sub <<
";";
226 Info(
"ProcessData",
"Obj %s Execute %s", obj->GetName(), exec.str().c_str());
227 gROOT->ProcessLine(exec.str().c_str());
230 CheckPadModified(Canvas());
234 }
else if (arg.compare(0, 12,
"EXECANDSEND:") == 0) {
238 std::string buf = arg.substr(12);
240 TObject *obj =
nullptr;
242 auto pos = buf.find(
":");
244 if ((pos > 0) && IsFirstConn(connid) && !
IsReadOnly()) {
246 reply = buf.substr(0, pos);
247 buf.erase(0, pos + 1);
250 auto sid = buf.substr(0, pos);
251 buf.erase(0, pos + 1);
256 if (obj && !buf.empty() && !reply.empty()) {
257 std::stringstream exec;
258 exec <<
"((" << obj->ClassName() <<
" *) " << std::hex << std::showbase << (size_t)obj
259 <<
")->" << buf <<
";";
261 Info(
"ProcessData",
"Obj %s Exec %s", obj->GetName(), exec.str().c_str());
263 Long_t res = gROOT->ProcessLine(exec.str().c_str());
264 TObject *resobj = (TObject *)res;
266 std::string send = reply;
268 send.append(TBufferJSON::ToJSON(resobj, 23).Data());
269 AddToSendQueue(connid, send);
288 auto arr = TBufferJSON::FromJSON<std::vector<TWebPadOptions>>(
msg);
293 for (
unsigned n = 0; n < arr->size(); ++n) {
294 auto &r = arr->at(n);
300 if (pad == Canvas()) AssignStatusBits(r.bits);
302 if (r.active && (pad != gPad)) gPad = pad;
304 pad->SetTicks(r.tickx, r.ticky);
305 pad->SetGrid(r.gridx, r.gridy);
306 if (r.logx != pad->GetLogx())
307 pad->SetLogx(r.logx);
308 if (r.logy != pad->GetLogy())
309 pad->SetLogy(r.logy);
310 if (r.logz != pad->GetLogz())
311 pad->SetLogz(r.logz);
313 pad->SetLeftMargin(r.mleft);
314 pad->SetRightMargin(r.mright);
315 pad->SetTopMargin(r.mtop);
316 pad->SetBottomMargin(r.mbottom);
320 Double_t ux1_, ux2_, uy1_, uy2_, px1_, px2_, py1_, py2_;
322 pad->GetRange(px1_, py1_, px2_, py2_);
323 pad->GetRangeAxis(ux1_, uy1_, ux2_, uy2_);
325 bool same_range = (r.ux1 == ux1_) && (r.ux2 == ux2_) && (r.uy1 == uy1_) && (r.uy2 == uy2_) &&
326 (r.px1 == px1_) && (r.px2 == px2_) && (r.py1 == py1_) && (r.py2 == py2_);
329 pad->RangeAxis(r.ux1, r.uy1, r.ux2, r.uy2);
331 pad->Range(r.px1, r.py1, r.px2, r.py2);
334 Info(
"DecodeAllRanges",
"Change ranges for pad %s", pad->GetName());
338 pad->SetPad(r.mleft, r.mbottom, 1-r.mright, 1-r.mtop);
340 TH1 *hist =
static_cast<TH1 *
>(
FindPrimitive(
"histogram", pad));
343 double hmin = 0, hmax = 0;
346 hist->GetXaxis()->SetRange(0,0);
348 hist->GetXaxis()->SetRangeUser(r.zx1, r.zx2);
350 if (hist->GetDimension() == 1) {
353 }
else if (r.zy1 == r.zy2) {
354 hist->GetYaxis()->SetRange(0,0);
356 hist->GetYaxis()->SetRangeUser(r.zy1, r.zy2);
359 if (hist->GetDimension() == 2) {
362 }
else if (hist->GetDimension() == 3) {
363 if (r.zz1 == r.zz2) {
364 hist->GetZaxis()->SetRange(0,0);
366 hist->GetZaxis()->SetRangeUser(r.zz1, r.zz2);
370 if (hmin == hmax) { hist->SetMinimum(); hist->SetMaximum(); }
371 else { hist->SetMinimum(hmin); hist->SetMaximum(hmax); }
375 for (
auto &item : r.primitives)
380 pad->Modified(
kTRUE);
383 if (fUpdatedSignal) fUpdatedSignal();
394 TObjLink *lnk =
nullptr;
395 TPad *objpad =
nullptr;
398 if (item.
fcust.compare(
"exec") == 0) {
399 auto pos = item.
opt.find(
"(");
400 if (obj && (pos != std::string::npos) && obj->IsA()->GetMethodAllAny(item.
opt.substr(0,pos).c_str())) {
401 std::stringstream exec;
402 exec <<
"((" << obj->ClassName() <<
" *) " << std::hex << std::showbase
403 << (size_t)obj <<
")->" << item.
opt <<
";";
404 Info(
"ProcessObjectOptions",
"Obj %s Execute %s", obj->GetName(), exec.str().c_str());
405 gROOT->ProcessLine(exec.str().c_str());
407 Error(
"ProcessObjectOptions",
"Fail to execute %s for object %p %s", item.
opt.c_str(), obj, obj ? obj->ClassName() :
"---");
413 bool modified =
false;
416 auto pos = item.
opt.find(
";;use_");
417 if (pos != std::string::npos) item.
opt.resize(pos);
420 Info(
"ProcessObjectOptions",
"Set draw option %s for object %s %s", item.
opt.c_str(),
421 obj->ClassName(), obj->GetName());
423 lnk->SetOption(item.
opt.c_str());
428 if (item.
fcust.compare(
"frame") == 0) {
429 if (obj && obj->InheritsFrom(TFrame::Class())) {
430 TFrame *frame =
static_cast<TFrame *
>(obj);
431 if (item.
fopt.size() >= 4) {
432 frame->SetX1(item.
fopt[0]);
433 frame->SetY1(item.
fopt[1]);
434 frame->SetX2(item.
fopt[2]);
435 frame->SetY2(item.
fopt[3]);
439 }
else if (item.
fcust.compare(
"pave") == 0) {
440 if (obj && obj->InheritsFrom(TPave::Class())) {
441 TPave *pave =
static_cast<TPave *
>(obj);
442 if ((item.
fopt.size() >= 4) && objpad) {
447 pave->ConvertNDCtoPad();
449 pave->SetX1NDC(item.
fopt[0]);
450 pave->SetY1NDC(item.
fopt[1]);
451 pave->SetX2NDC(item.
fopt[2]);
452 pave->SetY2NDC(item.
fopt[3]);
455 pave->ConvertNDCtoPad();
461 return modified ? objpad :
nullptr;
Bool_t IsReadOnly() const override
TPad * ProcessObjectOptions(TWebObjectOptions &item, TPad *pad)
ObjectSelectSignal_t fObjSelectSignal
! signal emitted when new object selected in the pad
TWebCanvasFull(TCanvas *c, const char *name, Int_t x, Int_t y, UInt_t width, UInt_t height)
constructor
PadClickedSignal_t fPadClickedSignal
! signal emitted when simple mouse click performed on the pad
Bool_t DecodePadOptions(const std::string &) override
Decode all pad options, which includes ranges plus objects options.
std::string fcust
custom string
std::string snapid
id of the object
std::string opt
drawing options
std::vector< double > fopt
custom float array
Bool_t fCanCreateObjects kTRUE
! indicates if canvas allowed to create extra objects for interactive painting
PadClickedSignal_t fPadDblClickedSignal
! signal emitted when simple mouse click performed on the pad
PadSignal_t fActivePadChangedSignal
! signal emitted when active pad changed in the canvas
TObject * FindPrimitive(const std::string &id, TPad *pad=nullptr, TObjLink **padlnk=nullptr, TPad **objpad=nullptr)
Class used to transport drawing options from the client.
Bool_t ProcessData(unsigned connid, const std::string &arg) override
Process reply from client, which is not processed by basic TWebCanvas.