Logo ROOT  
Reference Guide
TObjectDrawable.cxx
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers. *
3 * All rights reserved. *
4 * *
5 * For the licensing terms see $ROOTSYS/LICENSE. *
6 * For the list of contributors see $ROOTSYS/README/CREDITS. *
7 *************************************************************************/
8
10
12#include <ROOT/RColor.hxx>
13#include <ROOT/RLogger.hxx>
14#include <ROOT/RMenuItems.hxx>
15
16#include "TArrayI.h"
17#include "TColor.h"
18#include "TObjArray.h"
19#include "TObjString.h"
20#include "TROOT.h"
21#include "TList.h"
22#include "TStyle.h"
23#include "TMethodCall.h"
24
25#include <exception>
26#include <sstream>
27#include <iostream>
28#include <cstring>
29
30using namespace ROOT::Experimental;
31
32////////////////////////////////////////////////////////////////////
33/// Checks object ownership - used for TH1 directory handling and TF1 globals lists
34
35void TObjectDrawable::CheckOwnership(TObject *obj)
36{
37 if (obj && obj->InheritsFrom("TH1")) {
38 TMethodCall call(obj->IsA(), "SetDirectory", "nullptr");
39 call.Execute((void *)(obj));
40 } else if (obj && obj->InheritsFrom("TF1")) {
41 TMethodCall call(obj->IsA(), "AddToGlobalList", "kFALSE");
42 call.Execute((void *)(obj));
43 }
44}
45
46////////////////////////////////////////////////////////////////////
47/// Provide css type
48
50{
51 if (!obj) return "tobject";
52
53 const char *clname = obj->ClassName();
54 if (strncmp(clname, "TH3", 3) == 0) return "th3";
55 if (strncmp(clname, "TH2", 3) == 0) return "th2";
56 if ((strncmp(clname, "TH1", 3) == 0) || obj->InheritsFrom("TH1")) return "th1";
57 if (strncmp(clname, "TGraph", 6) == 0) return "tgraph";
58 if (strcmp(clname, "TLine") == 0) return "tline";
59 if (strcmp(clname, "TBox") == 0) return "tbox";
60 return "tobject";
61}
62
63////////////////////////////////////////////////////////////////////
64/// Default constructor
65
67{
68}
69
70////////////////////////////////////////////////////////////////////
71/// Constructor, can take ownership over the object is isowner specified
72
73TObjectDrawable::TObjectDrawable(TObject *obj, bool isowner) : RDrawable(DetectCssType(obj))
74{
75 fKind = kObject;
76 if (isowner) {
77 CheckOwnership(obj);
78 fObj = std::shared_ptr<TObject>(obj);
79 } else {
80 fExtObj = obj;
81 }
82}
83
84////////////////////////////////////////////////////////////////////
85/// Constructor, can take ownership over the object is isowner specified
86
87TObjectDrawable::TObjectDrawable(TObject *obj, const std::string &opt, bool isowner) : TObjectDrawable(obj, isowner)
88{
89 options = opt;
90}
91
92////////////////////////////////////////////////////////////////////
93/// Constructor
94
95TObjectDrawable::TObjectDrawable(const std::shared_ptr<TObject> &obj) : RDrawable(DetectCssType(obj.get()))
96{
97 fKind = kObject;
98 CheckOwnership(obj.get());
99 fObj = obj;
100}
101
102
103////////////////////////////////////////////////////////////////////
104/// Constructor
105
106TObjectDrawable::TObjectDrawable(const std::shared_ptr<TObject> &obj, const std::string &opt) : TObjectDrawable(obj)
107{
108 options = opt;
109}
110
111////////////////////////////////////////////////////////////////////
112/// Creates special kind for for palette or list of colors
113/// One can create persistent, which does not updated to actual values
114
116{
117 fKind = kind;
118
119 if (persistent)
120 fObj = CreateSpecials(kind);
121}
122
123////////////////////////////////////////////////////////////////////
124/// Destructor
125
127
128
129////////////////////////////////////////////////////////////////////
130/// Reset object
131
133{
134 fKind = kNone;
135 fObj = nullptr;
136 fExtObj = nullptr;
137}
138
139
140////////////////////////////////////////////////////////////////////
141/// Return assigned object
142
144{
145 // weak pointer - when object deleted outside only indirect way to handle it :(
146 if (fExtObj) {
148 return fExtObj;
149 }
150
151 return fObj.get();
152}
153
154
155////////////////////////////////////////////////////////////////////
156/// Set object
157
158void TObjectDrawable::Set(TObject *obj, bool isowner)
159{
160 Reset();
161
163 fKind = kObject;
164
165 if (isowner) {
166 CheckOwnership(obj);
167 fObj = std::shared_ptr<TObject>(obj);
168 } else {
169 fExtObj = obj;
170 }
171}
172
173////////////////////////////////////////////////////////////////////
174/// Set object
175
176void TObjectDrawable::Set(TObject *obj, const std::string &opt, bool isowner)
177{
178 Set(obj, isowner);
179 options = opt;
180}
181
182////////////////////////////////////////////////////////////////////
183/// Convert TColor to RGB string for using with SVG
184
186{
187 RColor rcol((uint8_t) (255*col->GetRed()), (uint8_t) (255*col->GetGreen()), (uint8_t) (255*col->GetBlue()));
188 if (col->GetAlpha() != 1)
189 rcol.SetAlphaFloat(col->GetAlpha());
190
191 return rcol.AsSVG();
192}
193
194////////////////////////////////////////////////////////////////////
195/// Create instance of requested special object
196
197std::unique_ptr<TObject> TObjectDrawable::CreateSpecials(int kind)
198{
199 switch (kind) {
200 case kColors: {
201 // convert list of colors into strings
202 auto arr = std::make_unique<TObjArray>();
203 arr->SetOwner(kTRUE);
204
205 auto cols = gROOT->GetListOfColors();
206 for (int n = 0; n <= cols->GetLast(); ++n) {
207 auto col = dynamic_cast<TColor *>(cols->At(n));
208 if (!col) continue;
209 auto code = TString::Format("%d=%s", n, GetColorCode(col).c_str());
210 arr->Add(new TObjString(code));
211 }
212
213 return arr;
214 }
215 case kStyle: { // create copy of gStyle
216 return std::make_unique<TStyle>(*gStyle);
217 }
218 case kPalette: { // copy color palette
219
220 auto arr = std::make_unique<TObjArray>();
221 arr->SetOwner(kTRUE);
222
223 auto palette = TColor::GetPalette();
224 for (int n = 0; n < palette.GetSize(); ++n) {
225 auto col = gROOT->GetColor(palette[n]);
226 arr->Add(new TObjString(GetColorCode(col).c_str()));
227 }
228
229 return arr;
230 }
231 }
232 return nullptr;
233}
234
235////////////////////////////////////////////////////////////////////
236/// Check if object has specified color value and store it in display item
237/// Ensure that color matches on client side too
238
239void TObjectDrawable::ExtractObjectColors(std::unique_ptr<TObjectDisplayItem> &item, const TObject *obj)
240{
241 if (!obj) return;
242
243 TClass *cl = obj->IsA();
244
245 auto ExtractColor = [&item, cl, obj](const char *class_name, const char *class_member) {
246 if (!cl->GetBaseClass(class_name)) return;
247
248 auto offset = cl->GetDataMemberOffset(class_member);
249 if (offset <= 0) return;
250
251 Color_t *icol = (Color_t *)((char *) obj + offset);
252 if (*icol < 10) return;
253
254 TColor *col = gROOT->GetColor(*icol);
255 if (col) item->UpdateColor(*icol, GetColorCode(col));
256 };
257
258 ExtractColor("TAttLine", "fLineColor");
259 ExtractColor("TAttFill", "fFillColor");
260 ExtractColor("TAttMarker", "fMarkerColor");
261 ExtractColor("TAttText", "fTextColor");
262 ExtractColor("TAttPad", "fFrameFillColor");
263 ExtractColor("TAttPad", "fFrameLineColor");
264 ExtractColor("TAttAxis", "fAxisColor");
265 ExtractColor("TAttAxis", "fLabelColor");
266 ExtractColor("TAttAxis", "fTitleColor");
267
268 if (cl->InheritsFrom("TH1")) {
269 auto offx = cl->GetDataMemberOffset("fXaxis");
270 if (offx > 0) ExtractObjectColors(item, (TObject *) ((char *) obj + offx));
271 auto offy = cl->GetDataMemberOffset("fYaxis");
272 if (offy > 0) ExtractObjectColors(item, (TObject *) ((char *) obj + offy));
273 auto offz = cl->GetDataMemberOffset("fZaxis");
274 if (offz > 0) ExtractObjectColors(item, (TObject *) ((char *) obj + offz));
275 }
276}
277
278
279////////////////////////////////////////////////////////////////////
280/// Create display item which will be delivered to the client
281
282std::unique_ptr<RDisplayItem> TObjectDrawable::Display(const RDisplayContext &ctxt)
283{
284 if (GetVersion() > ctxt.GetLastVersion()) {
285
286 auto obj = Get();
287
288 if ((fKind == kObject) || obj) {
289 auto item = std::make_unique<TObjectDisplayItem>(*this, fKind, obj);
290 if ((fKind == kObject) && obj) {
291 ExtractObjectColors(item, obj);
292
293 // special handling of THStack to support any custom colors inside
294 if (strcmp(obj->ClassName(), "THStack") == 0) {
295 TClass *cl = gROOT->GetClass("THStack");
296 // do not call stack->GetHistogram() to avoid it auto-creation
297 auto off1 = cl->GetDataMemberOffset("fHistogram");
298 if (off1 > 0) ExtractObjectColors(item, *((TObject **) ((char *) obj + off1)));
299 // here make identical to fHistogram, one also can use TMethodCall
300 auto off2 = cl->GetDataMemberOffset("fHists");
301 if (off2 > 0) {
302 TIter iter(*(TList **) (((char *) obj + off2)));
303 TObject *hist = nullptr;
304 while ((hist = iter()) != nullptr)
305 ExtractObjectColors(item, hist);
306 }
307
308 }
309 }
310
311 return item;
312 }
313
314 auto specials = CreateSpecials(fKind);
315 return std::make_unique<TObjectDisplayItem>(fKind, specials.release());
316 }
317
318 return nullptr;
319}
320
321////////////////////////////////////////////////////////////////////
322/// fill context menu items for the ROOT class
323
325{
326 auto obj = Get();
327
328 if ((fKind != kObject) || !obj)
329 return;
330
331 TClass *cl = obj->IsA();
332
333 if (!items.GetSpecifier().empty() && cl->InheritsFrom("TH1")) {
334 Longptr_t offset = 0;
335 if (items.GetSpecifier() == "x")
336 offset = cl->GetDataMemberOffset("fXaxis");
337 else if (items.GetSpecifier() == "y")
338 offset = cl->GetDataMemberOffset("fYaxis");
339 else if (items.GetSpecifier() == "z")
340 offset = cl->GetDataMemberOffset("fZaxis");
341 if (offset > 0) {
342 obj = (TObject *) ((char *) obj + offset);
343 cl = obj->IsA();
344 }
345 }
346
347 items.PopulateObjectMenu((void *)obj, cl);
348}
349
350////////////////////////////////////////////////////////////////////
351/// Execute object method
352
353void TObjectDrawable::Execute(const std::string &exec)
354{
355 auto obj = Get();
356
357 if ((fKind != kObject) || !obj) return;
358
359 std::string sub, ex = exec;
360 if (ex.compare(0, 6, "xaxis#") == 0) {
361 ex.erase(0,6);
362 ex.insert(0, "GetXaxis()->");
363 } else if (ex.compare(0, 6, "yaxis#") == 0) {
364 ex.erase(0,6);
365 ex.insert(0, "GetYaxis()->");
366 } else if (ex.compare(0, 6, "zaxis#") == 0) {
367 ex.erase(0,6);
368 ex.insert(0, "GetZaxis()->");
369 }
370
371 std::stringstream cmd;
372 cmd << "((" << obj->ClassName() << " *) " << std::hex << std::showbase << (size_t)obj << ")->" << ex << ";";
373 std::cout << "TObjectDrawable::Execute Obj " << obj->GetName() << " Cmd " << cmd.str() << std::endl;
374 gROOT->ProcessLine(cmd.str().c_str());
375}
short Color_t
Definition: RtypesCore.h:92
long Longptr_t
Definition: RtypesCore.h:82
const Bool_t kTRUE
Definition: RtypesCore.h:100
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
#define gROOT
Definition: TROOT.h:404
R__EXTERN TStyle * gStyle
Definition: TStyle.h:414
The color class.
Definition: RColor.hxx:33
void SetAlphaFloat(float alpha)
Set alpha as float value from range 0..1.
Definition: RColor.hxx:92
std::string AsSVG() const
Returns color value as it will be used in SVG drawing It either include hex format #66FF66 or just pl...
Definition: RColor.cxx:291
Base class for drawable entities: objects that can be painted on a RPad.
Definition: RDrawable.hxx:108
Version_t GetVersion() const
Definition: RDrawable.hxx:197
void SetCssType(const char *csstype)
Definition: RDrawable.hxx:192
List of items for object context menu.
Definition: RMenuItems.hxx:157
void PopulateObjectMenu(void *obj, TClass *cl)
Fill menu for provided object, using MENU as indicator in method comments.
Definition: RMenuItems.cxx:31
const std::string & GetSpecifier() const
Definition: RMenuItems.hxx:174
Provides v7 drawing facilities for TObject types (TGraph, TH1, TH2, etc).
RAttrValue< std::string > options
! object draw options
@ kPalette
list of colors from palette
@ kStyle
instance of TStyle object
static void ExtractObjectColors(std::unique_ptr< TObjectDisplayItem > &item, const TObject *obj)
Check if object has specified color value and store it in display item Ensure that color matches on c...
static void CheckOwnership(TObject *obj)
Checks object ownership - used for TH1 directory handling and TF1 globals lists.
Internal::RIOShared< TObject > fObj
The object to be painted, owned by the drawable.
std::unique_ptr< TObject > CreateSpecials(int kind)
Create instance of requested special object.
void PopulateMenu(RMenuItems &) final
fill context menu items for the ROOT class
static std::string GetColorCode(TColor *col)
Convert TColor to RGB string for using with SVG.
void Execute(const std::string &) final
Execute object method.
std::unique_ptr< RDisplayItem > Display(const RDisplayContext &) override
Create display item which will be delivered to the client.
virtual ~TObjectDrawable()
Destructor.
const TObject * Get()
Return assigned object.
static const char * DetectCssType(const TObject *obj)
Provide css type.
const TObject * fExtObj
! external object, managed outside of the drawable, not persistent
void Set(TObject *obj, bool isowner=false)
Set object.
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:81
TClass * GetBaseClass(const char *classname)
Return pointer to the base class "classname".
Definition: TClass.cxx:2656
Longptr_t GetDataMemberOffset(const char *membername) const
return offset for member name.
Definition: TClass.cxx:3466
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4863
TClass * IsA() const override
Definition: TClass.h:614
The color creation and management class.
Definition: TColor.h:19
static const TArrayI & GetPalette()
Static function returning the current active palette.
Definition: TColor.cxx:1462
Float_t GetRed() const
Definition: TColor.h:58
Float_t GetAlpha() const
Definition: TColor.h:64
Float_t GetBlue() const
Definition: TColor.h:60
Float_t GetGreen() const
Definition: TColor.h:59
A doubly linked list.
Definition: TList.h:38
Method or function calling interface.
Definition: TMethodCall.h:37
void Execute(const char *, const char *, int *=nullptr) override
Execute method on this object with the given parameter string, e.g.
Definition: TMethodCall.h:64
Collectable string class.
Definition: TObjString.h:28
Mother of all ROOT objects.
Definition: TObject.h:41
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:201
@ kNotDeleted
object has not been deleted
Definition: TObject.h:82
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:200
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:519
virtual TClass * IsA() const
Definition: TObject.h:245
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition: TString.cxx:2341
const Int_t n
Definition: legend1.C:16
Double_t ex[n]
Definition: legend1.C:17
static const std::string persistent("persistent")