// @(#)root/gui:$Id$
// Author: Reiner Rohlfs   24/03/2002

/*************************************************************************
 * Copyright (C) 1995-2001, Rene Brun, Fons Rademakers and Reiner Rohlfs *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TGXYLayout                                                           //
//                                                                      //
// Is a layout manager where the position and the size of each widget   //
// in the frame are defined by X / Y - coordinates. The coordinates     //
// for each widget are defined by the TGXYLayoutHints. Therefore it     //
// is not possible to share a layout hint for several widgets.          //
//                                                                      //
// The coordinates (X, Y) and the size (W, H) are defined in units      //
// of the size of a typical character. Also the size of the             //
// TGCompositeFrame for which a TGXYLayout manager is used has to be    //
// defined in its constructor in units of the size of a character!      //
//                                                                      //
// It is not possible to use any other layout hint than the             //
// TGXYLayoutHints for this layout manager!                             //
//                                                                      //
// The rubberFlag in the constructor of the TGLXYLayoutHins defines     //
// how the position and the size of a widget is recalculated if the     //
// size of the frame is increased:                                      //
// - kLRubberX: The X - position (left edge) is increased by the same   //
//              factor as the width of the frame increases.             //
// - kLRubberY: The Y - position (upper edge) is increased by the same  //
//              factor as the height of the frame increases.            //
// - kLRubberW: The width of the widget is increased by the same        //
//              factor as the width of the frame increases.             //
// - kLRubberH: The height of the widget is increased by the same       //
//              factor as the height of the frame increases.            //
// But the size never becomes smaller than defined by the               //
// TGXYLayoutHints and the X and Y coordinates becomes never smaller    //
// than defined by the layout hints.                                    //
//                                                                      //
// TGXYLayoutHints                                                      //
//                                                                      //
// This layout hint must be used for the TGXYLouyout manager!           //
//                                                                      //
//                                                                      //
// Example how to use this layout manager:                              //
//                                                                      //
// TGMyFrame::TGMyFrame()                                               //
//    : TGMainFrame(gClient->GetRoot(), 30, 12)                         //
//    // frame is 30 character long and 12 character heigh              //
// {                                                                    //
//    SetLayoutManager(new TGXYLayout(this));                           //
//                                                                      //
//    // create a button of size 8 X 1.8 at position 20 / 1             //
//    TGTextButton * button;                                            //
//    button = new TGTextButton(this, "&Apply", 1);                     //
//    AddFrame(button, new TGXYLayoutHints(20, 1, 8, 1.8));             //
//                                                                      //
//    // create a listbox of size 18 X 10 at position 1 / 1.            //
//    // The height will increase if the frame height increases         //
//    TGListBox * listBox;                                              //
//    listBox = new TGListBox(this, 2);                                 //
//    AddFrame(listBox, new TGXYLayoutHints(1, 1, 18, 10,               //
//             TGXYLayoutHints::kLRubberX |                             //
//             TGXYLayoutHints::kLRubberY |                             //
//             TGXYLayoutHints::kLRubberH ));                           //
//    .                                                                 //
//    .                                                                 //
//    .                                                                 //
// }                                                                    //
//                                                                      //
// Normaly there is one layout hint per widget. Therefore these         //
// can be deleted like in the following example in the desctuctor       //
// of the frame:                                                        //
//                                                                      //
// TGMyFrame::~TGMyFrame()                                              //
// {                                                                    //
//    // Destructor, deletes all frames and their layout hints.         //
//                                                                      //
//    TGFrameElement *ptr;                                              //
//                                                                      //
//    // delete all frames and layout hints                             //
//    if (fList) {                                                      //
//       TIter next(fList);                                             //
//       while ((ptr = (TGFrameElement *) next())) {                    //
//          if (ptr->fLayout)                                           //
//             delete ptr->fLayout;                                     //
//          if (ptr->fFrame)                                            //
//             delete ptr->fFrame;                                      //
//       }                                                              //
//    }                                                                 //
// }                                                                    //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TGXYLayout.h"
#include "TGFrame.h"
#include "TGLabel.h"
#include "Riostream.h"


ClassImp(TGXYLayout)
ClassImp(TGXYLayoutHints)

//______________________________________________________________________________
TGXYLayoutHints::TGXYLayoutHints(Double_t x, Double_t y, Double_t w, Double_t h,
                                 UInt_t rubberFlag)
   : TGLayoutHints(kLHintsNormal, 0,0,0,0)
{
   // Constructor. The x, y, w and h define the position of the widget in
   // its frame and the size of the widget. The unit is the size of a
   // character. The rubberFlag defines how to move and to resize the
   // widget when the frame is resized. Default is moving the X and Y
   // position but keep the size of the widget.

   fX    = x;
   fY    = y;
   fW    = w;
   fH    = h;
   fFlag = rubberFlag;
}

//______________________________________________________________________________
void TGXYLayoutHints::SavePrimitive(std::ostream &out, Option_t * /*option = ""*/)
{
   // Save XY layout hints as a C++ statement(s) on output stream.
   
   TString flag = "";
   if (fFlag & kLRubberX) {
      if (flag.Length() == 0)  flag  = "TGXYLayoutHints::kLRubberX";
      else                     flag += " | TGXYLayoutHints::kLRubberX";
   }
   if (fFlag & kLRubberY) {
      if  (flag.Length() == 0) flag  = "TGXYLayoutHints::kLRubberY";
      else                      flag += " | TGXYLayoutHints::kLRubberY";
   }
   if (fFlag & kLRubberW) {
      if (flag.Length() == 0) flag  = "TGXYLayoutHints::kLRubberW";
      else                     flag += " | TGXYLayoutHints::kLRubberW";
   }
   if (fFlag & kLRubberH) {
      if (flag.Length() == 0) flag  = "TGXYLayoutHints::kLRubberH";
      else                     flag += " | TGXYLayoutHints::kLRubberH";
   }

   out << ", new TGXYLayoutHints(" << GetX() << ", " << GetY() << ", " 
       << GetW() << ", " << GetH();

   if (!flag.Length()) 
      out << ")";
   else
      out << ", " << flag << ")";

}

//______________________________________________________________________________
TGXYLayout::TGXYLayout(TGCompositeFrame *main)
{
   // Constructor. The main is the frame for which this layout manager works.

   UInt_t  width, height;
   Int_t   dummy;

   fMain = main;
   fList = main->GetList();
   fFirst = kTRUE;
   fFirstWidth = fFirstHeight = 0;

   FontStruct_t fs = TGLabel::GetDefaultFontStruct();

   // get standard width an height of a character
   fTWidth = gVirtualX->TextWidth(fs, "1234567890", 10) / 10;
   gVirtualX->GetFontProperties(fs, fTHeight, dummy);

   // the size of the main window are defined in units of a character
   // but the system does not understand this. We have to recalculate
   // the size into pixels.
   width  = main->GetWidth() * fTWidth;
   height = main->GetHeight() * fTHeight;

   main->Resize(width, height);
}

//______________________________________________________________________________
TGXYLayout::TGXYLayout(const TGXYLayout& xyl) :
  TGLayoutManager(xyl),
  fList(xyl.fList),
  fMain(xyl.fMain),
  fFirst(xyl.fFirst),
  fFirstWidth(xyl.fFirstWidth),
  fFirstHeight(xyl.fFirstHeight),
  fTWidth(xyl.fTWidth),
  fTHeight(xyl.fTHeight)
{ 
   //copy constructor
}

//______________________________________________________________________________
TGXYLayout& TGXYLayout::operator=(const TGXYLayout& xyl) 
{
   //assignment operator
   if(this!=&xyl) {
      TGLayoutManager::operator=(xyl);
      fList=xyl.fList;
      fMain=xyl.fMain;
      fFirst=xyl.fFirst;
      fFirstWidth=xyl.fFirstWidth;
      fFirstHeight=xyl.fFirstHeight;
      fTWidth=xyl.fTWidth;
      fTHeight=xyl.fTHeight;
   } 
   return *this;
}

//______________________________________________________________________________
void TGXYLayout::Layout()
{
   // Recalculates the postion and the size of all widgets.

   TGFrameElement   *ptr;
   TGXYLayoutHints  *layout;
   Double_t          xFactor;
   Double_t          yFactor;
   Int_t             newX, newY;
   UInt_t            newW, newH;
   Double_t          temp;

   if (!fList) return;

   if (fFirst) {
      // save the original size of the frame. It is used to determin
      // if the user has changed the window
      fFirstWidth   = fMain->GetWidth();
      fFirstHeight  = fMain->GetHeight();
      fFirst        = kFALSE;
   }

   // get the factor of the increacement of the window
   xFactor = (Double_t)fMain->GetWidth() / (Double_t)fFirstWidth;
   if (xFactor < 1.0) xFactor = 1.0;
   yFactor = (Double_t)fMain->GetHeight() / (Double_t)fFirstHeight;
   if (yFactor < 1.0) yFactor = 1.0;

   // set the position an size for each widget and call the layout
   // function for each widget
   TIter next(fList);
   while ((ptr = (TGFrameElement *) next()))  {
      if (ptr->fState & kIsVisible) {
         layout = (TGXYLayoutHints*)ptr->fLayout;
         if (layout == 0)
            continue;

         temp = layout->GetX() * fTWidth ;
         if (layout->GetFlag() & TGXYLayoutHints::kLRubberX)
            temp *= xFactor;
         newX = (Int_t)(temp + 0.5);

         temp = layout->GetY() * fTHeight;
         if (layout->GetFlag() & TGXYLayoutHints::kLRubberY)
            temp *= yFactor;
         newY = (Int_t)(temp + 0.5);

         temp = layout->GetW() * fTWidth;
         if (layout->GetFlag() & TGXYLayoutHints::kLRubberW)
            temp *= xFactor;
         newW = (UInt_t)(temp + 0.5);

         temp = layout->GetH() * fTHeight;
         if (layout->GetFlag() & TGXYLayoutHints::kLRubberH)
            temp *= yFactor;
         newH = (UInt_t)(temp + 0.5);
         ptr->fFrame->MoveResize(newX, newY, newW, newH);
         ptr->fFrame->Layout();
      }
   }
}

//______________________________________________________________________________
TGDimension TGXYLayout::GetDefaultSize() const
{
   // Returns the original size of the frame.

   TGDimension size(fFirstWidth, fFirstHeight);

   return size;
}

//______________________________________________________________________________
void TGXYLayout::SavePrimitive(std::ostream &out, Option_t * /*option = ""*/)
{
   // Save XY layout manager as a C++ statement(s) on output stream.
   
   out << "new TGXYLayout(" << fMain->GetName() << ")";

}
 TGXYLayout.cxx:1
 TGXYLayout.cxx:2
 TGXYLayout.cxx:3
 TGXYLayout.cxx:4
 TGXYLayout.cxx:5
 TGXYLayout.cxx:6
 TGXYLayout.cxx:7
 TGXYLayout.cxx:8
 TGXYLayout.cxx:9
 TGXYLayout.cxx:10
 TGXYLayout.cxx:11
 TGXYLayout.cxx:12
 TGXYLayout.cxx:13
 TGXYLayout.cxx:14
 TGXYLayout.cxx:15
 TGXYLayout.cxx:16
 TGXYLayout.cxx:17
 TGXYLayout.cxx:18
 TGXYLayout.cxx:19
 TGXYLayout.cxx:20
 TGXYLayout.cxx:21
 TGXYLayout.cxx:22
 TGXYLayout.cxx:23
 TGXYLayout.cxx:24
 TGXYLayout.cxx:25
 TGXYLayout.cxx:26
 TGXYLayout.cxx:27
 TGXYLayout.cxx:28
 TGXYLayout.cxx:29
 TGXYLayout.cxx:30
 TGXYLayout.cxx:31
 TGXYLayout.cxx:32
 TGXYLayout.cxx:33
 TGXYLayout.cxx:34
 TGXYLayout.cxx:35
 TGXYLayout.cxx:36
 TGXYLayout.cxx:37
 TGXYLayout.cxx:38
 TGXYLayout.cxx:39
 TGXYLayout.cxx:40
 TGXYLayout.cxx:41
 TGXYLayout.cxx:42
 TGXYLayout.cxx:43
 TGXYLayout.cxx:44
 TGXYLayout.cxx:45
 TGXYLayout.cxx:46
 TGXYLayout.cxx:47
 TGXYLayout.cxx:48
 TGXYLayout.cxx:49
 TGXYLayout.cxx:50
 TGXYLayout.cxx:51
 TGXYLayout.cxx:52
 TGXYLayout.cxx:53
 TGXYLayout.cxx:54
 TGXYLayout.cxx:55
 TGXYLayout.cxx:56
 TGXYLayout.cxx:57
 TGXYLayout.cxx:58
 TGXYLayout.cxx:59
 TGXYLayout.cxx:60
 TGXYLayout.cxx:61
 TGXYLayout.cxx:62
 TGXYLayout.cxx:63
 TGXYLayout.cxx:64
 TGXYLayout.cxx:65
 TGXYLayout.cxx:66
 TGXYLayout.cxx:67
 TGXYLayout.cxx:68
 TGXYLayout.cxx:69
 TGXYLayout.cxx:70
 TGXYLayout.cxx:71
 TGXYLayout.cxx:72
 TGXYLayout.cxx:73
 TGXYLayout.cxx:74
 TGXYLayout.cxx:75
 TGXYLayout.cxx:76
 TGXYLayout.cxx:77
 TGXYLayout.cxx:78
 TGXYLayout.cxx:79
 TGXYLayout.cxx:80
 TGXYLayout.cxx:81
 TGXYLayout.cxx:82
 TGXYLayout.cxx:83
 TGXYLayout.cxx:84
 TGXYLayout.cxx:85
 TGXYLayout.cxx:86
 TGXYLayout.cxx:87
 TGXYLayout.cxx:88
 TGXYLayout.cxx:89
 TGXYLayout.cxx:90
 TGXYLayout.cxx:91
 TGXYLayout.cxx:92
 TGXYLayout.cxx:93
 TGXYLayout.cxx:94
 TGXYLayout.cxx:95
 TGXYLayout.cxx:96
 TGXYLayout.cxx:97
 TGXYLayout.cxx:98
 TGXYLayout.cxx:99
 TGXYLayout.cxx:100
 TGXYLayout.cxx:101
 TGXYLayout.cxx:102
 TGXYLayout.cxx:103
 TGXYLayout.cxx:104
 TGXYLayout.cxx:105
 TGXYLayout.cxx:106
 TGXYLayout.cxx:107
 TGXYLayout.cxx:108
 TGXYLayout.cxx:109
 TGXYLayout.cxx:110
 TGXYLayout.cxx:111
 TGXYLayout.cxx:112
 TGXYLayout.cxx:113
 TGXYLayout.cxx:114
 TGXYLayout.cxx:115
 TGXYLayout.cxx:116
 TGXYLayout.cxx:117
 TGXYLayout.cxx:118
 TGXYLayout.cxx:119
 TGXYLayout.cxx:120
 TGXYLayout.cxx:121
 TGXYLayout.cxx:122
 TGXYLayout.cxx:123
 TGXYLayout.cxx:124
 TGXYLayout.cxx:125
 TGXYLayout.cxx:126
 TGXYLayout.cxx:127
 TGXYLayout.cxx:128
 TGXYLayout.cxx:129
 TGXYLayout.cxx:130
 TGXYLayout.cxx:131
 TGXYLayout.cxx:132
 TGXYLayout.cxx:133
 TGXYLayout.cxx:134
 TGXYLayout.cxx:135
 TGXYLayout.cxx:136
 TGXYLayout.cxx:137
 TGXYLayout.cxx:138
 TGXYLayout.cxx:139
 TGXYLayout.cxx:140
 TGXYLayout.cxx:141
 TGXYLayout.cxx:142
 TGXYLayout.cxx:143
 TGXYLayout.cxx:144
 TGXYLayout.cxx:145
 TGXYLayout.cxx:146
 TGXYLayout.cxx:147
 TGXYLayout.cxx:148
 TGXYLayout.cxx:149
 TGXYLayout.cxx:150
 TGXYLayout.cxx:151
 TGXYLayout.cxx:152
 TGXYLayout.cxx:153
 TGXYLayout.cxx:154
 TGXYLayout.cxx:155
 TGXYLayout.cxx:156
 TGXYLayout.cxx:157
 TGXYLayout.cxx:158
 TGXYLayout.cxx:159
 TGXYLayout.cxx:160
 TGXYLayout.cxx:161
 TGXYLayout.cxx:162
 TGXYLayout.cxx:163
 TGXYLayout.cxx:164
 TGXYLayout.cxx:165
 TGXYLayout.cxx:166
 TGXYLayout.cxx:167
 TGXYLayout.cxx:168
 TGXYLayout.cxx:169
 TGXYLayout.cxx:170
 TGXYLayout.cxx:171
 TGXYLayout.cxx:172
 TGXYLayout.cxx:173
 TGXYLayout.cxx:174
 TGXYLayout.cxx:175
 TGXYLayout.cxx:176
 TGXYLayout.cxx:177
 TGXYLayout.cxx:178
 TGXYLayout.cxx:179
 TGXYLayout.cxx:180
 TGXYLayout.cxx:181
 TGXYLayout.cxx:182
 TGXYLayout.cxx:183
 TGXYLayout.cxx:184
 TGXYLayout.cxx:185
 TGXYLayout.cxx:186
 TGXYLayout.cxx:187
 TGXYLayout.cxx:188
 TGXYLayout.cxx:189
 TGXYLayout.cxx:190
 TGXYLayout.cxx:191
 TGXYLayout.cxx:192
 TGXYLayout.cxx:193
 TGXYLayout.cxx:194
 TGXYLayout.cxx:195
 TGXYLayout.cxx:196
 TGXYLayout.cxx:197
 TGXYLayout.cxx:198
 TGXYLayout.cxx:199
 TGXYLayout.cxx:200
 TGXYLayout.cxx:201
 TGXYLayout.cxx:202
 TGXYLayout.cxx:203
 TGXYLayout.cxx:204
 TGXYLayout.cxx:205
 TGXYLayout.cxx:206
 TGXYLayout.cxx:207
 TGXYLayout.cxx:208
 TGXYLayout.cxx:209
 TGXYLayout.cxx:210
 TGXYLayout.cxx:211
 TGXYLayout.cxx:212
 TGXYLayout.cxx:213
 TGXYLayout.cxx:214
 TGXYLayout.cxx:215
 TGXYLayout.cxx:216
 TGXYLayout.cxx:217
 TGXYLayout.cxx:218
 TGXYLayout.cxx:219
 TGXYLayout.cxx:220
 TGXYLayout.cxx:221
 TGXYLayout.cxx:222
 TGXYLayout.cxx:223
 TGXYLayout.cxx:224
 TGXYLayout.cxx:225
 TGXYLayout.cxx:226
 TGXYLayout.cxx:227
 TGXYLayout.cxx:228
 TGXYLayout.cxx:229
 TGXYLayout.cxx:230
 TGXYLayout.cxx:231
 TGXYLayout.cxx:232
 TGXYLayout.cxx:233
 TGXYLayout.cxx:234
 TGXYLayout.cxx:235
 TGXYLayout.cxx:236
 TGXYLayout.cxx:237
 TGXYLayout.cxx:238
 TGXYLayout.cxx:239
 TGXYLayout.cxx:240
 TGXYLayout.cxx:241
 TGXYLayout.cxx:242
 TGXYLayout.cxx:243
 TGXYLayout.cxx:244
 TGXYLayout.cxx:245
 TGXYLayout.cxx:246
 TGXYLayout.cxx:247
 TGXYLayout.cxx:248
 TGXYLayout.cxx:249
 TGXYLayout.cxx:250
 TGXYLayout.cxx:251
 TGXYLayout.cxx:252
 TGXYLayout.cxx:253
 TGXYLayout.cxx:254
 TGXYLayout.cxx:255
 TGXYLayout.cxx:256
 TGXYLayout.cxx:257
 TGXYLayout.cxx:258
 TGXYLayout.cxx:259
 TGXYLayout.cxx:260
 TGXYLayout.cxx:261
 TGXYLayout.cxx:262
 TGXYLayout.cxx:263
 TGXYLayout.cxx:264
 TGXYLayout.cxx:265
 TGXYLayout.cxx:266
 TGXYLayout.cxx:267
 TGXYLayout.cxx:268
 TGXYLayout.cxx:269
 TGXYLayout.cxx:270
 TGXYLayout.cxx:271
 TGXYLayout.cxx:272
 TGXYLayout.cxx:273
 TGXYLayout.cxx:274
 TGXYLayout.cxx:275
 TGXYLayout.cxx:276
 TGXYLayout.cxx:277
 TGXYLayout.cxx:278
 TGXYLayout.cxx:279
 TGXYLayout.cxx:280
 TGXYLayout.cxx:281
 TGXYLayout.cxx:282
 TGXYLayout.cxx:283
 TGXYLayout.cxx:284
 TGXYLayout.cxx:285
 TGXYLayout.cxx:286
 TGXYLayout.cxx:287
 TGXYLayout.cxx:288
 TGXYLayout.cxx:289
 TGXYLayout.cxx:290
 TGXYLayout.cxx:291
 TGXYLayout.cxx:292
 TGXYLayout.cxx:293
 TGXYLayout.cxx:294
 TGXYLayout.cxx:295
 TGXYLayout.cxx:296
 TGXYLayout.cxx:297
 TGXYLayout.cxx:298