Logo ROOT   6.18/05
Reference Guide
TGDockableFrame.cxx
Go to the documentation of this file.
1// @(#)root/gui:$Id$
2// Author: Abdelhalim Ssadik 07/07/04
3
4/*************************************************************************
5 * Copyright (C) 1995-2004, 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// A TGDockableFrame is a frame with handles that allow it to be //
26// undocked (i.e. put in a transient frame of its own) and to be docked //
27// again or hidden and shown again. It uses the TGDockButton, which is //
28// a button with two vertical bars (||) and TGDockHideButton, which is //
29// a button with a small triangle. The TGUndockedFrame is a transient //
30// frame that on closure will put the frame back in the dock. //
31// //
32//////////////////////////////////////////////////////////////////////////
33
34#include "TColor.h"
35#include "TGFrame.h"
36#include "TMessage.h"
37#include "TGWidget.h"
38#include "TGButton.h"
39#include "TGDockableFrame.h"
40#include "TGWindow.h"
41#include "TList.h"
42#include "TVirtualX.h"
43#include "Riostream.h"
44
45
50
51////////////////////////////////////////////////////////////////////////////////
52/// Create a dock button (i.e. button with two vertical bars).
53
55 TGButton (p, id, GetDefaultGC()(), kChildFrame)
56{
60
62
63 Float_t r, g, b, h, l, s;
65 TColor::RGB2HLS(r, g, b, h, l, s);
66 l = l + (1. - l) * 45. / 100.;
67 TColor::HLS2RGB(h, l, s, r, g, b);
69
72}
73
74////////////////////////////////////////////////////////////////////////////////
75/// Delete dock button.
76
78{
79}
80
81////////////////////////////////////////////////////////////////////////////////
82/// Handle dock button crossing events.
83
85{
87 if (event->fType == kLeaveNotify) {
89 } else if (event->fType == kEnterNotify) {
91 }
92 if (IsEnabled())
93 fClient->NeedRedraw(this);
94
95 return kTRUE;
96}
97
98////////////////////////////////////////////////////////////////////////////////
99/// Draw borders of dock button.
100
102{
103 int options = GetOptions();
104
106 ;
107 else if (fMouseOn == kTRUE && IsEnabled()) {
110 } else {
113 }
114 gVirtualX->ClearWindow(fId);
116
117 ChangeOptions(options);
118}
119
120////////////////////////////////////////////////////////////////////////////////
121/// Draw the dock button, i.e. two vertical lines.
122
124{
125 int x = 1, y = 0;
126
127 DrawBorder();
128 if (fState == kButtonDown || fState == kButtonEngaged) { ++x; ++y; }
129
130 for (int i = 0; i < 5; i +=4) {
131 gVirtualX->DrawLine(fId, GetHilightGC()(), i+x, y+1, i+x, fHeight-y-3);
132 gVirtualX->DrawLine(fId, GetShadowGC()(), i+x+1, y+1, i+x+1, fHeight-y-3);
133 }
134}
135
136
137////////////////////////////////////////////////////////////////////////////////
138/// Create a dock hide button (i.e. button with small triangle).
139
141 TGDockButton (p, 2)
142{
143 Resize(10, 8);
144 fAspectRatio = 0;
146}
147
148////////////////////////////////////////////////////////////////////////////////
149/// Draw dock hide button.
150
152{
153 int x = 1, y = 0;
154
155 DrawBorder();
156 if (fState == kButtonDown || fState == kButtonEngaged) { ++x; ++y; }
157
158 if (fAspectRatio) {
159 gVirtualX->DrawLine(fId, GetBlackGC()(), x+1, y+1, x+5, y+3);
160 gVirtualX->DrawLine(fId, GetBlackGC()(), x+1, y+5, x+5, y+3);
161 gVirtualX->DrawLine(fId, GetHilightGC()(), x, y+1, x, y+5);
162 } else {
163 gVirtualX->DrawLine(fId, GetHilightGC()(), x+5, y+1, x+1, y+3);
164 gVirtualX->DrawLine(fId, GetHilightGC()(), x+5, y+5, x+1, y+3);
165 gVirtualX->DrawLine(fId, GetBlackGC()(), x+6, y+1, x+6, y+5);
166 }
167}
168
169
170////////////////////////////////////////////////////////////////////////////////
171/// Create the undocked (transient) frame.
172
174 TGTransientFrame(p, dockable ? dockable->GetMainFrame() : 0, 10, 10)
175{
176 SetWindowName("");
177 fDockable = dockable;
178
185}
186
187////////////////////////////////////////////////////////////////////////////////
188/// Delete undocked frame. Puts back dockable frame in its original container.
189
191{
192 if (fDockable && !fDockable->fDeleted) {
194 }
195}
196
197////////////////////////////////////////////////////////////////////////////////
198/// Fix the size of the undocked frame so it cannot be changed via the WM.
199
201{
205}
206
207////////////////////////////////////////////////////////////////////////////////
208/// Close undocked frame (called via WM close button).
209
211{
212 DeleteWindow();
213}
214
215
216////////////////////////////////////////////////////////////////////////////////
217/// Create a dockable frame widget.
218
221{
223
226 fLb = new TGLayoutHints(kLHintsExpandY | kLHintsLeft, 0, 2, 0, 0);
228
229 fButtons = new TGCompositeFrame(this, 10, 10, kVerticalFrame);
235
237
238 fContainer = new TGCompositeFrame(this, 10, 10);
239
241
244 fHidden = kFALSE;
245 fFrame = 0;
248
249 fDockButton->Associate(this);
250 fHideButton->Associate(this);
251
255}
256
257////////////////////////////////////////////////////////////////////////////////
258/// Cleanup dockable frame.
259
261{
262 // Just set the flag and delete fFrame. The other components
263 // are deleted in TGCompositeFrame destructor.
264 if (fFrame) {
265 fDeleted = kTRUE;
266 delete fFrame;
267 }
268}
269
270////////////////////////////////////////////////////////////////////////////////
271/// Add frame to dockable frame container. Frame and hints are NOT adopted.
272
274{
275 f->ReparentWindow(fContainer);
276 fContainer->AddFrame(f, fHints = hints);
278}
279
280////////////////////////////////////////////////////////////////////////////////
281/// Undock container.
282
284{
285 int ax, ay;
286 Window_t wdummy;
287
288 if (fFrame || !fEnableUndock) return;
289
292
297
298 gVirtualX->TranslateCoordinates(GetId(), fClient->GetDefaultRoot()->GetId(), fX,
299 fY + fFrame->GetHeight(), ax, ay, wdummy);
300
302
304 fFrame->Resize(size);
305 if (fFixedSize)
306 fFrame->FixSize();
307 fFrame->MapWindow();
308 fFrame->Move(ax, ay);
309
310 if (((TGFrame *)fParent)->IsComposite()) // paranoia check
311 ((TGCompositeFrame *)fParent)->HideFrame(this);
312
313 Layout();
314
316 Undocked();
317}
318
319////////////////////////////////////////////////////////////////////////////////
320/// Dock container back to TGDockableFrame.
321
323{
324 if (!fFrame) return;
325 if (del) {
326 delete fFrame; // this will call DockContainer again with del = kFALSE
327 return;
328 }
329
333
334 // kludge! (for special case)
336
337 Layout();
338 if (((TGFrame *)fParent)->IsComposite()) // paranoia check
339 ((TGCompositeFrame *)fParent)->ShowFrame(this);
340
341 // fFrame is just being deleted (we're here called by TGUndockedFrame's
342 // destructor) so just set it NULL below to avoid eventual problems in
343 // TGDockableFrame's destructor.
344
345 fFrame = 0;
346
348 Docked();
349}
350
351////////////////////////////////////////////////////////////////////////////////
352/// Show dock container.
353
355{
356 if (!fHidden) return;
357
361 if (((TGFrame *)fParent)->IsComposite()) // paranoia check
362 ((TGCompositeFrame *)fParent)->Layout();
363 fHidden = kFALSE;
364
366}
367
368////////////////////////////////////////////////////////////////////////////////
369/// Hide dock container.
370
372{
373 if (fHidden || !fEnableHide) return;
374
378 if (((TGFrame *)fParent)->IsComposite()) // paranoia check
379 ((TGCompositeFrame *)fParent)->Layout();
380 fHidden = kTRUE;
381
383}
384
385////////////////////////////////////////////////////////////////////////////////
386/// Process dockable frame messages.
387
389{
390 switch (GET_MSG(msg)) {
391 case kC_COMMAND:
392 switch (GET_SUBMSG(msg)) {
393 case kCM_BUTTON:
394 switch (parm1) {
395 case 1:
396 if (!fHidden) UndockContainer();
397 break;
398 case 2:
399 if (!fHidden)
401 else
403 break;
404 }
405 break;
406 }
407 break;
408 }
409
410 return kTRUE;
411}
412
413////////////////////////////////////////////////////////////////////////////////
414/// Enable undocking.
415
417{
418 fEnableUndock = onoff;
419 if (onoff)
421 else
423 Layout();
424}
425
426////////////////////////////////////////////////////////////////////////////////
427/// Enable hiding.
428
430{
431 fEnableHide = onoff;
432 if (onoff)
434 else
436 Layout();
437}
438
439////////////////////////////////////////////////////////////////////////////////
440/// Set window name so it appear as title of the undock window.
441
443{
444 fDockName = "";
445 if (name) {
446 fDockName = name;
448 }
449}
450
451////////////////////////////////////////////////////////////////////////////////
452/// Save a dockable frame widget as a C++ statement(s) on output stream out.
453
454void TGDockableFrame::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
455{
456 char quote = '"';
457
458 out << std::endl << " // dockable frame" << std::endl;
459 out << " TGDockableFrame *";
460 out << GetName()<<" = new TGDockableFrame(" << fParent->GetName();
461
462 if (GetOptions() == kHorizontalFrame) {
463 if (fWidgetId == -1) {
464 out << ");" << std::endl;
465 } else {
466 out << "," << fWidgetId << ");" << std::endl;
467 }
468 } else {
469 out << "," << fWidgetId << "," << GetOptionString() << ");" << std::endl;
470 }
471 if (option && strstr(option, "keep_names"))
472 out << " " << GetName() << "->SetName(\"" << GetName() << "\");" << std::endl;
473
474 if (GetContainer()->GetList()->First()) {
475 out << " TGCompositeFrame *" << GetContainer()->GetName() << " = "
476 << GetName() << "->GetContainer();" << std::endl;
477
478 TGFrameElement *el;
479 TIter next(GetContainer()->GetList());
480
481 while ((el = (TGFrameElement *) next())) {
482 el->fFrame->SavePrimitive(out, option);
483 out << " " << GetName() << "->AddFrame(" << el->fFrame->GetName();
484 el->fLayout->SavePrimitive(out, option);
485 out << ");"<< std::endl;
486 }
487 }
488 out << std::endl << " // next lines belong to the dockable frame widget" << std::endl;
489 if (EnableUndock())
490 out << " " << GetName() << "->EnableUndock(kTRUE);" << std::endl;
491 else
492 out << " " << GetName() << "->EnableUndock(kFALSE);" << std::endl;
493
494 if (EnableHide())
495 out << " " << GetName() << "->EnableHide(kTRUE);" << std::endl;
496 else
497 out << " " << GetName() << "->EnableHide(kFALSE);" << std::endl;
498
499 if (fDockName != "")
500 out << " " << GetName() << "->SetWindowName(" << quote << fDockName
501 << quote << ");" << std::endl;
502
503 if (IsUndocked())
504 out << " " << GetName() << "->UndockContainer();" << std::endl;
505 else
506 out << " " << GetName() << "->DockContainer();" << std::endl;
507
508 if (IsHidden())
509 out << " " << GetName() << "->HideContainer();" << std::endl;
510
511 out << std::endl;
512}
@ kEnterNotify
Definition: GuiTypes.h:60
@ kLeaveNotify
Definition: GuiTypes.h:60
const Mask_t kLeaveWindowMask
Definition: GuiTypes.h:167
const Mask_t kEnterWindowMask
Definition: GuiTypes.h:166
Handle_t Window_t
Definition: GuiTypes.h:28
ROOT::R::TRInterface & r
Definition: Object.C:4
#define b(i)
Definition: RSha256.hxx:100
#define f(i)
Definition: RSha256.hxx:104
#define g(i)
Definition: RSha256.hxx:105
#define h(i)
Definition: RSha256.hxx:106
int Int_t
Definition: RtypesCore.h:41
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
float Float_t
Definition: RtypesCore.h:53
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
#define ClassImp(name)
Definition: Rtypes.h:365
@ kButtonDown
Definition: TGButton.h:54
@ kButtonEngaged
Definition: TGButton.h:55
@ kMWMDecorResizeH
Definition: TGFrame.h:96
@ kMWMFuncAll
Definition: TGFrame.h:80
@ kMWMFuncResize
Definition: TGFrame.h:81
@ kMWMDecorMaximize
Definition: TGFrame.h:100
@ kMWMDecorMinimize
Definition: TGFrame.h:99
@ kMWMDecorMenu
Definition: TGFrame.h:98
@ kMWMDecorAll
Definition: TGFrame.h:94
@ kMWMFuncMaximize
Definition: TGFrame.h:84
@ kMWMInputModeless
Definition: TGFrame.h:88
@ kMWMFuncMinimize
Definition: TGFrame.h:83
@ kChildFrame
Definition: TGFrame.h:57
@ kVerticalFrame
Definition: TGFrame.h:59
@ kHorizontalFrame
Definition: TGFrame.h:60
@ kFixedSize
Definition: TGFrame.h:68
@ kLHintsExpandY
Definition: TGLayout.h:38
@ kLHintsLeft
Definition: TGLayout.h:31
@ kLHintsTop
Definition: TGLayout.h:34
@ kLHintsExpandX
Definition: TGLayout.h:37
@ kWidgetIsEnabled
Definition: TGWidget.h:48
XFontStruct * id
Definition: TGX11.cxx:108
char name[80]
Definition: TGX11.cxx:109
#define gVirtualX
Definition: TVirtualX.h:345
Int_t MK_MSG(EWidgetMessageTypes msg, EWidgetMessageTypes submsg)
Int_t GET_MSG(Long_t val)
@ kDOCK_UNDOCK
@ kDOCK_DOCK
@ kC_COMMAND
@ kDOCK_SHOW
@ kCM_BUTTON
@ kDOCK_HIDE
@ kC_DOCK
Int_t GET_SUBMSG(Long_t val)
static void HLS2RGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Static method to compute RGB from HLS.
Definition: TColor.cxx:1451
static ULong_t RGB2Pixel(Int_t r, Int_t g, Int_t b)
Convert r,g,b to graphics system dependent pixel value.
Definition: TColor.cxx:2041
static void Pixel2RGB(ULong_t pixel, Int_t &r, Int_t &g, Int_t &b)
Convert machine dependent pixel value (obtained via RGB2Pixel or via Number2Pixel() or via TColor::Ge...
Definition: TColor.cxx:2079
static void RGB2HLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Static method to compute HLS from RGB.
Definition: TColor.cxx:1591
virtual Bool_t HandleCrossing(Event_t *event)
Handle mouse crossing event.
Definition: TGButton.cxx:354
EButtonState fState
Definition: TGButton.h:75
const TGWindow * GetDefaultRoot() const
Returns the root (i.e.
Definition: TGClient.cxx:234
void NeedRedraw(TGWindow *w, Bool_t force=kFALSE)
Set redraw flags.
Definition: TGClient.cxx:372
virtual TList * GetList() const
Definition: TGFrame.h:369
Bool_t IsComposite() const
Definition: TGFrame.h:412
TGCompositeFrame(const TGCompositeFrame &)
virtual void AddFrame(TGFrame *f, TGLayoutHints *l=0)
Add frame to the composite frame using the specified layout hints.
Definition: TGFrame.cxx:1099
virtual void Layout()
Layout the elements of the composite frame.
Definition: TGFrame.cxx:1239
virtual void ChangeOptions(UInt_t options)
Change composite frame options. Options is an OR of the EFrameTypes.
Definition: TGFrame.cxx:1025
virtual void SetCleanup(Int_t mode=kLocalCleanup)
Turn on automatic cleanup of child frames in dtor.
Definition: TGFrame.cxx:1054
virtual TGDimension GetDefaultSize() const
std::cout << fWidth << "x" << fHeight << std::endl;
Definition: TGFrame.h:375
virtual void MapSubwindows()
Map all sub windows that are part of the composite frame.
Definition: TGFrame.cxx:1146
virtual void ShowFrame(TGFrame *f)
Show sub frame.
Definition: TGFrame.cxx:1186
virtual void SetEditDisabled(UInt_t on=1)
Set edit disable flag for this frame and subframes.
Definition: TGFrame.cxx:1004
virtual void RemoveFrame(TGFrame *f)
Remove frame from composite frame.
Definition: TGFrame.cxx:1131
virtual void HideFrame(TGFrame *f)
Hide sub frame.
Definition: TGFrame.cxx:1172
virtual Bool_t HandleCrossing(Event_t *event)
Handle dock button crossing events.
TGDockButton(const TGCompositeFrame *p=0, Int_t id=1)
Create a dock button (i.e. button with two vertical bars).
virtual void DrawBorder()
Draw borders of dock button.
virtual ~TGDockButton()
Delete dock button.
virtual void DoRedraw()
Draw the dock button, i.e. two vertical lines.
virtual void DoRedraw()
Draw dock hide button.
TGDockHideButton(const TGCompositeFrame *p=0)
Create a dock hide button (i.e. button with small triangle).
void SetAspectRatio(Int_t a)
void DockContainer(Int_t del=kTRUE)
Dock container back to TGDockableFrame.
friend class TGUndockedFrame
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a dockable frame widget as a C++ statement(s) on output stream out.
TGCompositeFrame * fButtons
virtual ~TGDockableFrame()
Cleanup dockable frame.
TGUndockedFrame * fFrame
TGLayoutHints * fLb
TGDockableFrame(const TGDockableFrame &)
Bool_t IsHidden() const
TGCompositeFrame * GetContainer() const
virtual void AddFrame(TGFrame *f, TGLayoutHints *hints)
Add frame to dockable frame container. Frame and hints are NOT adopted.
TGCompositeFrame * fContainer
void UndockContainer()
Undock container.
virtual void Undocked()
void HideContainer()
Hide dock container.
virtual Bool_t ProcessMessage(Long_t, Long_t, Long_t)
Process dockable frame messages.
Bool_t EnableUndock() const
TGLayoutHints * fHints
void SetWindowName(const char *name)
Set window name so it appear as title of the undock window.
Bool_t EnableHide() const
TGDockButton * fDockButton
void ShowContainer()
Show dock container.
TGDockHideButton * fHideButton
virtual void Docked()
TGLayoutHints * fLc
Bool_t IsUndocked() const
TGLayoutHints * fLayout
Definition: TGLayout.h:121
TGFrame * fFrame
Definition: TGLayout.h:119
virtual void ChangeOptions(UInt_t options)
Change frame options. Options is an OR of the EFrameTypes.
Definition: TGFrame.cxx:303
void AddInput(UInt_t emask)
Add events specified in the emask to the events the frame should handle.
Definition: TGFrame.cxx:321
static const TGGC & GetBlackGC()
Get black graphics context.
Definition: TGFrame.cxx:717
Int_t fX
Definition: TGFrame.h:132
virtual void ReparentWindow(const TGWindow *p, Int_t x=0, Int_t y=0)
Reparent window, make p the new parent and position the window at position (x,y) in new parent.
Definition: TGFrame.h:249
UInt_t fHeight
Definition: TGFrame.h:135
virtual UInt_t GetDefaultWidth() const
Definition: TGFrame.h:237
virtual UInt_t GetDefaultHeight() const
Definition: TGFrame.h:238
virtual void DrawBorder()
Draw frame border.
Definition: TGFrame.cxx:403
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a frame widget as a C++ statement(s) on output stream out.
Definition: TGFrame.cxx:3187
TGDimension GetSize() const
Definition: TGFrame.h:277
static const TGGC & GetHilightGC()
Get highlight color graphics context.
Definition: TGFrame.cxx:737
virtual void SetBackgroundColor(Pixel_t back)
Set background color (override from TGWindow base class).
Definition: TGFrame.cxx:294
virtual void SendMessage(const TGWindow *w, Long_t msg, Long_t parm1, Long_t parm2)
Send message (i.e.
Definition: TGFrame.cxx:627
virtual void DeleteWindow()
Delete window.
Definition: TGFrame.cxx:258
virtual UInt_t GetOptions() const
Definition: TGFrame.h:244
TString GetOptionString() const
Returns a frame option string - used in SavePrimitive().
Definition: TGFrame.cxx:2460
Int_t fY
Definition: TGFrame.h:133
static const TGGC & GetShadowGC()
Get shadow color graphics context.
Definition: TGFrame.cxx:747
virtual void Move(Int_t x, Int_t y)
Move frame.
Definition: TGFrame.cxx:575
virtual void Resize(UInt_t w=0, UInt_t h=0)
Resize the frame.
Definition: TGFrame.cxx:587
UInt_t fWidth
Definition: TGFrame.h:134
UInt_t GetHeight() const
Definition: TGFrame.h:272
virtual void MapWindow()
Definition: TGFrame.h:251
Pixel_t fBackground
Definition: TGFrame.h:142
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition: TGLayout.cxx:1003
void SetWMSize(UInt_t w, UInt_t h)
Give the window manager a window size hint.
Definition: TGFrame.cxx:1849
void SetMWMHints(UInt_t value, UInt_t funcs, UInt_t input)
Set decoration style for MWM-compatible wm (mwm, ncdwm, fvwm?).
Definition: TGFrame.cxx:1824
void SetWMSizeHints(UInt_t wmin, UInt_t hmin, UInt_t wmax, UInt_t hmax, UInt_t winc, UInt_t hinc)
Give the window manager minimum and maximum size hints.
Definition: TGFrame.cxx:1862
void SetWindowName(const char *name=0)
Set window name. This is typically done via the window manager.
Definition: TGFrame.cxx:1746
TGClient * fClient
Definition: TGObject.h:37
Handle_t GetId() const
Definition: TGObject.h:47
Handle_t fId
Definition: TGObject.h:36
TGUndockedFrame(const TGUndockedFrame &)
void FixSize()
Fix the size of the undocked frame so it cannot be changed via the WM.
virtual ~TGUndockedFrame()
Delete undocked frame. Puts back dockable frame in its original container.
TGDockableFrame * fDockable
void CloseWindow()
Close undocked frame (called via WM close button).
Int_t fWidgetId
Definition: TGWidget.h:58
virtual void Associate(const TGWindow *w)
Definition: TGWidget.h:84
Int_t fWidgetFlags
Definition: TGWidget.h:59
const TGWindow * fMsgWindow
Definition: TGWidget.h:60
Bool_t IsEnabled() const
Definition: TGWidget.h:81
virtual void SetWindowName(const char *name=0)
Set window name.
Definition: TGWindow.cxx:118
virtual const char * GetName() const
Return unique name, used in SavePrimitive methods.
Definition: TGWindow.cxx:221
const TGWindow * fParent
Definition: TGWindow.h:37
Double_t y[n]
Definition: legend1.C:17
Double_t x[n]
Definition: legend1.C:17
static constexpr double s
EGEventType fType
Definition: GuiTypes.h:174
auto * l
Definition: textangle.C:4