Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGPicture.cxx
Go to the documentation of this file.
1 // @(#)root/gui:$Id$
2 // Author: Fons Rademakers 01/01/98
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 /**************************************************************************
12 
13  This source is based on Xclass95, a Win95-looking GUI toolkit.
14  Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.
15 
16  Xclass95 is free software; you can redistribute it and/or
17  modify it under the terms of the GNU Library General Public
18  License as published by the Free Software Foundation; either
19  version 2 of the License, or (at your option) any later version.
20 
21 **************************************************************************/
22 
23 //////////////////////////////////////////////////////////////////////////
24 // //
25 // TGPicture & TGPicturePool //
26 // //
27 // The TGPicture class implements pictures and icons used in the //
28 // different GUI elements and widgets. The TGPicturePool class //
29 // implements a TGPicture cache. TGPictures are created, managed and //
30 // destroyed by the TGPicturePool. //
31 // //
32 //////////////////////////////////////////////////////////////////////////
33 
34 #include "TGPicture.h"
35 #include "TGResourcePool.h"
36 #include "THashTable.h"
37 #include "TSystem.h"
38 #include "TGWindow.h"
39 #include "TVirtualX.h"
40 #include "TImage.h"
41 #include "TROOT.h"
42 #include <stdlib.h>
43 
44 TGGC *TGSelectedPicture::fgSelectedGC = 0;
45 
46 ClassImp(TGPicture);
47 ClassImp(TGSelectedPicture);
48 ClassImp(TGPicturePool);
49 
50 
51 ////////////////////////////////////////////////////////////////////////////////
52 ///copy constructor
53 
54 TGPicturePool::TGPicturePool(const TGPicturePool& pp) :
55  TObject(pp),
56  fClient(pp.fClient),
57  fPath(pp.fPath),
58  fPicList(pp.fPicList)
59 {
60 }
61 
62 ////////////////////////////////////////////////////////////////////////////////
63 ///assignment operator
64 
65 TGPicturePool& TGPicturePool::operator=(const TGPicturePool& pp)
66 {
67  if(this!=&pp) {
68  TObject::operator=(pp);
69  fClient=pp.fClient;
70  fPath=pp.fPath;
71  fPicList=pp.fPicList;
72  }
73  return *this;
74 }
75 
76 ////////////////////////////////////////////////////////////////////////////////
77 /// Get a picture from the picture pool. Picture must be freed using
78 /// TGPicturePool::FreePicture(). If picture is not found 0 is returned.
79 
80 const TGPicture *TGPicturePool::GetPicture(const char *name)
81 {
82  if (!fPicList)
83  fPicList = new THashTable(50);
84 
85  TString pname = name;
86  pname.Strip();
87  TString ext = strrchr(pname, '.');
88  ext.ToLower();
89 
90  if (ext.Length()) { // ".xpm", ".gif" etc
91  char *pxname = gSystem->ExpandPathName(gSystem->UnixPathName(pname));
92  pname = pxname;
93  delete [] pxname;
94  }
95 
96  TGPicture *pic = (TGPicture *)fPicList->FindObject(pname);
97  if (pic && !pic->IsScaled()) {
98  if (pic->fPic == kNone)
99  return 0;
100  pic->AddReference();
101  return pic;
102  }
103 
104  char *picnam = gSystem->Which(fPath, pname, kReadPermission);
105  if (!picnam) {
106  pic = new TGPicture(pname);
107  pic->fAttributes.fColormap = fClient->GetDefaultColormap();
108  pic->fAttributes.fCloseness = 40000; // Allow for "similar" colors
109  pic->fAttributes.fMask = kPASize | kPAColormap | kPACloseness;
110  fPicList->Add(pic);
111  return 0;
112  }
113 
114  TImage *img = TImage::Open(picnam);
115  if (!img) {
116  pic = new TGPicture(pname);
117  pic->fAttributes.fColormap = fClient->GetDefaultColormap();
118  pic->fAttributes.fCloseness = 40000; // Allow for "similar" colors
119  pic->fAttributes.fMask = kPASize | kPAColormap | kPACloseness;
120  fPicList->Add(pic);
121  delete [] picnam;
122  return 0;
123  }
124 
125  pic = new TGPicture(pname, img->GetPixmap(), img->GetMask());
126  delete [] picnam;
127  delete img;
128  fPicList->Add(pic);
129  return pic;
130 }
131 
132 ////////////////////////////////////////////////////////////////////////////////
133 /// Get picture with specified size from pool (picture will be scaled if
134 /// necessary). Picture must be freed using TGPicturePool::FreePicture(). If
135 /// picture is not found 0 is returned.
136 
137 const TGPicture *TGPicturePool::GetPicture(const char *name,
138  UInt_t new_width, UInt_t new_height)
139 {
140  if (!fPicList)
141  fPicList = new THashTable(50);
142 
143  TString pname = name;
144  pname.Strip();
145  TString ext = strrchr(pname, '.');
146  ext.ToLower();
147 
148  if (ext.Length()) { // ".xpm", ".gif" etc
149  char *pxname = gSystem->ExpandPathName(gSystem->UnixPathName(pname));
150  pname = pxname;
151  delete [] pxname;
152  }
153 
154  const char *hname = TGPicture::HashName(pname, new_width, new_height);
155  TGPicture *pic = (TGPicture *)fPicList->FindObject(hname);
156  if (pic && pic->GetWidth() == new_width && pic->GetHeight() == new_height) {
157  if (pic->fPic == kNone)
158  return 0;
159  pic->AddReference();
160  return pic;
161  }
162 
163  char *picnam = gSystem->Which(fPath, pname, kReadPermission);
164  if (!picnam) {
165  pic = new TGPicture(hname, kTRUE);
166  pic->fAttributes.fColormap = fClient->GetDefaultColormap();
167  pic->fAttributes.fCloseness = 40000; // Allow for "similar" colors
168  pic->fAttributes.fMask = kPASize | kPAColormap | kPACloseness;
169  pic->fAttributes.fWidth = new_width;
170  pic->fAttributes.fHeight = new_height;
171  fPicList->Add(pic);
172  return 0;
173  }
174 
175  TImage *img = TImage::Open(picnam);
176  if (!img) {
177  pic = new TGPicture(hname, kTRUE);
178  pic->fAttributes.fColormap = fClient->GetDefaultColormap();
179  pic->fAttributes.fCloseness = 40000; // Allow for "similar" colors
180  pic->fAttributes.fMask = kPASize | kPAColormap | kPACloseness;
181  pic->fAttributes.fWidth = new_width;
182  pic->fAttributes.fHeight = new_height;
183  fPicList->Add(pic);
184  delete [] picnam;
185  return 0;
186  }
187 
188  img->Scale(new_width, new_height);
189 
190  pic = new TGPicture(hname, img->GetPixmap(), img->GetMask());
191  delete [] picnam;
192  delete img;
193  fPicList->Add(pic);
194  return pic;
195 }
196 
197 ////////////////////////////////////////////////////////////////////////////////
198 /// Get picture with specified pixmap and mask from pool.
199 /// Picture must be freed using TGPicturePool::FreePicture().
200 /// If picture is not found 0 is returned.
201 
202 const TGPicture *TGPicturePool::GetPicture(const char *name, Pixmap_t pxmap,
203  Pixmap_t mask)
204 {
205  if (!fPicList)
206  fPicList = new THashTable(50);
207 
208  Int_t xy;
209  UInt_t w, h;
210 
211  gVirtualX->GetWindowSize(pxmap, xy, xy, w, h);
212 
213  const char *hname = TGPicture::HashName(name, w, h);
214  TGPicture *pic = (TGPicture *)fPicList->FindObject(hname);
215 
216  if (pic) {
217  pic->AddReference();
218  return pic;
219  }
220 
221  pic = new TGPicture(hname, pxmap, mask);
222  fPicList->Add(pic);
223 
224  return pic;
225 }
226 
227 ////////////////////////////////////////////////////////////////////////////////
228 /// Create picture from XPM data.
229 /// Picture must be freed using TGPicturePool::FreePicture().
230 /// If picture creation failed 0 is returned.
231 
232 const TGPicture *TGPicturePool::GetPicture(const char *name, char **xpm)
233 {
234  UInt_t w, h;
235 
236  if (!xpm || !*xpm) {
237  return 0;
238  }
239 
240  if (!fPicList) {
241  fPicList = new THashTable(50);
242  }
243  char *ptr = xpm[0];
244  while (isspace((int)*ptr)) ++ptr;
245  w = atoi(ptr);
246 
247  while (isspace((int)*ptr)) ++ptr;
248  h = atoi(ptr);
249 
250  const char *hname = TGPicture::HashName(name, w, h);
251  TGPicture *pic = (TGPicture *)fPicList->FindObject(hname);
252  if (pic) {
253  pic->AddReference();
254  return pic;
255  }
256 
257  TImage *img = TImage::Open(xpm);
258  if (!img) {
259  pic = new TGPicture(hname, kTRUE);
260  pic->fAttributes.fColormap = fClient->GetDefaultColormap();
261  pic->fAttributes.fCloseness = 40000; // Allow for "similar" colors
262  pic->fAttributes.fMask = kPASize | kPAColormap | kPACloseness;
263  pic->fAttributes.fWidth = w;
264  pic->fAttributes.fHeight = h;
265  fPicList->Add(pic);
266  return 0;
267  }
268 
269  pic = new TGPicture(hname, img->GetPixmap(), img->GetMask());
270  delete img;
271  return pic;
272 }
273 
274 ////////////////////////////////////////////////////////////////////////////////
275 /// Remove picture from cache if nobody is using it anymore.
276 
277 void TGPicturePool::FreePicture(const TGPicture *fpic)
278 {
279  if (!fPicList) return;
280 
281  TGPicture *pic = (TGPicture *)fPicList->FindObject(fpic);
282  if (pic) {
283  if (pic->RemoveReference() == 0) {
284  fPicList->Remove(pic);
285  delete pic;
286  }
287  }
288 }
289 
290 ////////////////////////////////////////////////////////////////////////////////
291 /// Delete picture cache.
292 
293 TGPicturePool::~TGPicturePool()
294 {
295  if (fPicList) {
296  fPicList->Delete();
297  delete fPicList;
298  }
299 
300  // Required since we overload TObject::Hash.
301  ROOT::CallRecursiveRemoveIfNeeded(*this);
302 }
303 
304 ////////////////////////////////////////////////////////////////////////////////
305 /// List all pictures in the pool.
306 
307 void TGPicturePool::Print(Option_t *) const
308 {
309  if (fPicList)
310  fPicList->Print();
311  else
312  Info("Print", "no pictures in picture pool");
313 }
314 
315 ////////////////////////////////////////////////////////////////////////////////
316 /// ctor. Important: both pixmaps pxmap and mask must be unique (not shared)
317 
318 TGPicture::TGPicture(const char *name, Pixmap_t pxmap, Pixmap_t mask)
319 {
320  fName = name;
321  fScaled = kFALSE;
322  fPic = pxmap;
323  fMask = mask;
324  Int_t xy;
325 
326  fAttributes.fColormap = gClient->GetDefaultColormap();
327  fAttributes.fCloseness = 40000; // Allow for "similar" colors
328  fAttributes.fMask = kPASize | kPAColormap | kPACloseness;
329  fAttributes.fPixels = 0;
330  fAttributes.fDepth = 0;
331  fAttributes.fNpixels = 0;
332  fAttributes.fXHotspot = 0;
333  fAttributes.fYHotspot = 0;
334 
335  gVirtualX->GetWindowSize(fPic, xy, xy, fAttributes.fWidth, fAttributes.fHeight);
336  SetRefCount(1);
337 }
338 
339 ////////////////////////////////////////////////////////////////////////////////
340 /// Draw a picture.
341 
342 void TGPicture::Draw(Handle_t id, GContext_t gc, Int_t x, Int_t y) const
343 {
344  GCValues_t gcv;
345 
346  gcv.fMask = kGCClipMask | kGCClipXOrigin | kGCClipYOrigin;
347  gcv.fClipMask = fMask;
348  gcv.fClipXOrigin = x;
349  gcv.fClipYOrigin = y;
350  gVirtualX->ChangeGC(gc, &gcv);
351  gVirtualX->CopyArea(fPic, id, gc, 0, 0, fAttributes.fWidth, fAttributes.fHeight,
352  x, y);
353  gcv.fMask = kGCClipMask;
354  gcv.fClipMask = kNone;
355  gVirtualX->ChangeGC(gc, &gcv);
356 }
357 
358 ////////////////////////////////////////////////////////////////////////////////
359 /// Delete picture object.
360 
361 TGPicture::~TGPicture()
362 {
363  if (fPic != kNone)
364  gVirtualX->DeletePixmap(fPic);
365  if (fMask != kNone)
366  gVirtualX->DeletePixmap(fMask);
367  if (fAttributes.fPixels)
368  delete [] fAttributes.fPixels;
369 }
370 
371 ////////////////////////////////////////////////////////////////////////////////
372 /// Static function returning a unique name used to look up a picture.
373 /// The unique name has the form "name__widthxheight".
374 
375 const char *TGPicture::HashName(const char *name, Int_t width, Int_t height)
376 {
377  static TString hashName;
378 
379  hashName.Form("%s__%dx%d", name, width, height);
380  return hashName.Data();
381 }
382 
383 ////////////////////////////////////////////////////////////////////////////////
384 /// Print picture info.
385 
386 void TGPicture::Print(Option_t *) const
387 {
388  Printf("TGPicture: %s,%sref cnt = %u %lx", GetName(),
389  fScaled ? " scaled, " : " ", References(), fPic);
390 }
391 
392 
393 ////////////////////////////////////////////////////////////////////////////////
394 /// Create a "selected" looking picture based on the original TGPicture.
395 
396 TGSelectedPicture::TGSelectedPicture(const TGClient *client, const TGPicture *p) :
397  TGPicture("")
398 {
399  GCValues_t gcv;
400  UInt_t w, h;
401 
402  fClient = client;
403  Window_t root = fClient->GetDefaultRoot()->GetId();
404 
405  w = p->GetWidth();
406  h = p->GetHeight();
407 
408  fPic = gVirtualX->CreatePixmap(root, w, h);
409  fMask = p->GetMask();
410 
411  fAttributes.fWidth = w;
412  fAttributes.fHeight = h;
413 
414  gVirtualX->CopyArea(p->GetPicture(), fPic, GetSelectedGC()(), 0, 0, w, h, 0, 0);
415 
416  gcv.fMask = kGCClipMask | kGCClipXOrigin | kGCClipYOrigin;
417  gcv.fClipMask = p->GetMask();
418  gcv.fClipXOrigin = 0;
419  gcv.fClipYOrigin = 0;
420  GetSelectedGC().SetAttributes(&gcv);
421 
422  gVirtualX->FillRectangle(fPic, GetSelectedGC()(), 0, 0, w, h);
423 
424  GetSelectedGC().SetClipMask(kNone);
425 }
426 
427 ////////////////////////////////////////////////////////////////////////////////
428 /// Delete selected picture.
429 
430 TGSelectedPicture::~TGSelectedPicture()
431 {
432  // fMask was borrowed so should not be deleted by ~TGPicture.
433  fMask = kNone;
434 }
435 
436 ////////////////////////////////////////////////////////////////////////////////
437 /// Return selection graphics context in use.
438 
439 TGGC &TGSelectedPicture::GetSelectedGC()
440 {
441  if (!fgSelectedGC) {
442  fgSelectedGC = new TGGC(*gClient->GetResourcePool()->GetFrameGC());
443  fgSelectedGC->SetForeground(gClient->GetResourcePool()->GetSelectedBgndColor());
444  fgSelectedGC->SetBackground(gClient->GetResourcePool()->GetBlackColor());
445  fgSelectedGC->SetFillStyle(kFillStippled);
446  fgSelectedGC->SetStipple(gClient->GetResourcePool()->GetCheckeredBitmap());
447  }
448  return *fgSelectedGC;
449 }