#include "TGView.h"
#include "TGScrollBar.h"
#include "TGResourcePool.h"
#include "TMath.h"
#include "KeySymbols.h"
ClassImp(TGViewFrame)
TGViewFrame::TGViewFrame(TGView *v, UInt_t w, UInt_t h, UInt_t options,
                         ULong_t back) :
   TGCompositeFrame(v, w, h, options | kOwnBackground, back)
{
   
   fView = v;
   SetBackgroundColor(back);
      
   gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
                         kButtonPressMask | kButtonReleaseMask |
                         kButtonMotionMask, kNone, kNone);
   AddInput(kKeyPressMask | kEnterWindowMask | kLeaveWindowMask |
            kFocusChangeMask);
   SetWindowAttributes_t wattr;
   wattr.fMask = kWAWinGravity | kWABitGravity;
   wattr.fBitGravity = 1; 
   wattr.fWinGravity = 1;
   gVirtualX->ChangeWindowAttributes(fId, &wattr);
   
   fEditDisabled = kEditDisableGrab | kEditDisableKeyEnable | kEditDisableBtnEnable;
}
ClassImp(TGView)
TGView::TGView(const TGWindow *p, UInt_t w, UInt_t h, Int_t id,
               UInt_t xMargin, UInt_t yMargin, UInt_t options,
               UInt_t sboptions, ULong_t back)
       : TGCompositeFrame(p, w, h, options, GetDefaultFrameBackground())
{
   
   
   fWidgetId    = id;
   fMsgWindow   = p;
   fWidgetFlags = kWidgetWantFocus;
   fXMargin = xMargin;
   fYMargin = yMargin;
   fScrollVal.fX = 1;
   fScrollVal.fY = 1;
   fExposedRegion.Empty();
   fClipboard = fClient->GetResourcePool()->GetClipboard();
   fCanvas = new TGViewFrame(this, 10, 10, kChildFrame | kOwnBackground, back);
   AddFrame(fCanvas);
   if (!(sboptions & kNoHSB)) {
      fHsb = new TGHScrollBar(this, 10, 10, kChildFrame);
      AddFrame(fHsb);
      fHsb->Associate(this);
   } else {
      fHsb = 0;
   }
   if (!(sboptions & kNoVSB)) {
      fVsb = new TGVScrollBar(this, 10, 10, kChildFrame);
      AddFrame(fVsb);
      fVsb->Associate(this);
   } else {
      fVsb = 0;
   }
   fWhiteGC.SetGraphicsExposures(kTRUE);
   fWhiteGC.SetBackground(back);
   
   if (fVsb) {
      fVsb->SetEditDisabled(kEditDisableGrab | kEditDisableBtnEnable);
   }
   if (fHsb) {
      fHsb->SetEditDisabled(kEditDisableGrab  | kEditDisableBtnEnable);
   }
   fEditDisabled = kEditDisableLayout;
   
   delete fLayoutManager;
   fLayoutManager = 0;
}
TGView::~TGView()
{
   
   if (!MustCleanup()) {
      delete fCanvas;
      delete fHsb;
      delete fVsb;
   }
}
void TGView::Clear(Option_t *)
{
   
   fScrolling = -1;
   fMousePos.fX = fMousePos.fY = -1;
   fVisible.fX  = fVisible.fY = 0;
   UpdateBackgroundStart();
   fVirtualSize = TGDimension(0, 0);
   gVirtualX->ClearArea(fCanvas->GetId(), 0, 0,
                        fCanvas->GetWidth(), fCanvas->GetHeight());
   Layout();
}
void TGView::SetVisibleStart(Int_t newTop, Int_t direction)
{
   
   if (direction == kHorizontal) {
      if (newTop / fScrollVal.fX == fVisible.fX / fScrollVal.fX) {
         return;
      }
      ScrollCanvas(newTop, kHorizontal);
   } else {
      if (newTop / fScrollVal.fY == fVisible.fY / fScrollVal.fY) {
         return;
      }
      ScrollCanvas(newTop, kVertical);
   }
}
void TGView::DrawRegion(Int_t, Int_t, UInt_t, UInt_t)
{
   
   return;
}
void TGView::UpdateRegion(Int_t x, Int_t y, UInt_t w, UInt_t h)
{
   
   x = x < 0 ? 0 : x;
   y = y < 0 ? 0 : y;
   w = x + w > fCanvas->GetWidth() ? fCanvas->GetWidth() - x : w;
   h = y + h > fCanvas->GetHeight() ? fCanvas->GetHeight() - y : h;
   if (fExposedRegion.IsEmpty()) {
      fExposedRegion.fX = x;
      fExposedRegion.fY = y;
      fExposedRegion.fW = w;
      fExposedRegion.fH = h;
   } else {
      TGRectangle r(x, y, w, h);
      fExposedRegion.Merge(r);
   }
   fClient->NeedRedraw(this);
}
void TGView::UpdateBackgroundStart()
{
   
   fWhiteGC.SetTileStipXOrigin(-fVisible.fX);
   fWhiteGC.SetTileStipYOrigin(-fVisible.fY);
}
Bool_t TGView::HandleButton(Event_t *event)
{
   
   if (event->fType == kButtonPress) {
      int amount, ch;
      ch = fCanvas->GetHeight();
      if (fScrollVal.fY == 1) {
         amount = fScrollVal.fY * TMath::Max(ch/6, 1);
      } else {
         amount = fScrollVal.fY * 5;
      }
      if (event->fState & kKeyShiftMask) {
         amount = fScrollVal.fY;
      } else if (event->fState & kKeyControlMask) {
         amount = ch - TMath::Max(ch / 20, 1);
      }
      if (event->fCode == kButton4) {
         ScrollDown(amount);
         return kTRUE;
      } else if (event->fCode == kButton5) {
         ScrollUp(amount);
         return kTRUE;
      }
   }
   return kFALSE;
}
void TGView::DoRedraw()
{
   
   DrawBorder();
   if (!fExposedRegion.IsEmpty()) {
      DrawRegion(fExposedRegion.fX, fExposedRegion.fY, 
                 fExposedRegion.fW, fExposedRegion.fH);
      fExposedRegion.Empty();
   }
}
Bool_t TGView::HandleExpose(Event_t *event)
{
   
   if (event->fWindow == fCanvas->GetId()) {
      TGPosition pos(event->fX, event->fY);
      TGDimension dim(event->fWidth, event->fHeight);
      TGRectangle rect(pos, dim);
      if (fExposedRegion.IsEmpty()) {
         fExposedRegion = rect;
      } else {
         if (((!rect.fX && !fExposedRegion.fY) || 
              (!rect.fY && !fExposedRegion.fX)) && 
             ((rect.fX >= (int)fExposedRegion.fW) || 
              (rect.fY >= (int)fExposedRegion.fH))) {
            DrawRegion(rect.fX, rect.fY, rect.fW, rect.fY);
         } else {
            fExposedRegion.Merge(rect);
         }
      }
      fClient->NeedRedraw(this);
   } else {
      return TGCompositeFrame::HandleExpose(event);
   }
   return kTRUE;
}
Bool_t TGView::ProcessMessage(Long_t msg, Long_t parm1, Long_t)
{
   
   switch(GET_MSG(msg)) {
      case kC_HSCROLL:
         switch(GET_SUBMSG(msg)) {
            case kSB_SLIDERTRACK:
            case kSB_SLIDERPOS:
               SetVisibleStart(Int_t(parm1 * fScrollVal.fX), kHorizontal);
               break;
         }
         break;
      case kC_VSCROLL:
         switch(GET_SUBMSG(msg)) {
            case kSB_SLIDERTRACK:
            case kSB_SLIDERPOS:
               SetVisibleStart(Int_t(parm1 * fScrollVal.fY), kVertical);
               break;
         }
         break;
      default:
         break;
   }
   return kTRUE;
}
void TGView::Layout()
{
   
   Bool_t need_vsb, need_hsb;
   Int_t cw, ch;
   need_vsb = need_hsb = kFALSE;
   
   cw = fWidth - (fBorderWidth << 1) - fXMargin - 1;
   ch = fHeight - (fBorderWidth << 1) - fYMargin - 1;
   fCanvas->SetWidth(cw);
   fCanvas->SetHeight(ch);
   ItemLayout();
   if ((Int_t)fVirtualSize.fWidth > cw) {
      if (fHsb) {
         need_hsb = kTRUE;
         ch -= fVsb->GetDefaultWidth();
         if (ch < 0) ch = 0;
         fCanvas->SetHeight(ch);
         ItemLayout();
      }
   }
   if ((Int_t)fVirtualSize.fHeight > ch) {
      if (fVsb) {
         need_vsb = kTRUE;
         cw -= fHsb->GetDefaultHeight();
         if (cw < 0) cw = 0;
         fCanvas->SetWidth(cw);
         ItemLayout();
      }
   }
   
   if ((Int_t)fVirtualSize.fWidth > cw) {
      if (!need_hsb) {
         need_hsb = kTRUE;
         ch -= fVsb->GetDefaultWidth();
         if (ch < 0) ch = 0;
         fCanvas->SetHeight(ch);
         ItemLayout();
      }
   }
   if (need_hsb) {
      fHsb->MoveResize(fBorderWidth + fXMargin, ch + fBorderWidth + fYMargin,
                       cw, fHsb->GetDefaultHeight());
      fHsb->MapRaised();
   } else {
      fHsb->UnmapWindow();
      fHsb->SetPosition(0);
   }
   if (need_vsb) {
      fVsb->MoveResize(cw + fBorderWidth + fXMargin,  fBorderWidth + fYMargin,
                        fVsb->GetDefaultWidth(), ch);
      fVsb->MapWindow();
   } else {
      fVsb->UnmapWindow();
      fVsb->SetPosition(0);
   }
   fCanvas->MoveResize(fBorderWidth + fXMargin, fBorderWidth + fYMargin, cw, ch);
   if (fHsb) {
      fHsb->SetRange(fVirtualSize.fWidth / fScrollVal.fX, fCanvas->GetWidth() / fScrollVal.fX);
   }
   if (fVsb) {
      fVsb->SetRange(fVirtualSize.fHeight / fScrollVal.fY, fCanvas->GetHeight() / fScrollVal.fY);
   }
}
void TGView::DrawBorder()
{
   
   switch (fOptions & (kSunkenFrame | kRaisedFrame | kDoubleBorder)) {
      case kSunkenFrame | kDoubleBorder:
         gVirtualX->DrawLine(fId, GetShadowGC()(), 0, 0, fWidth-2, 0);
         gVirtualX->DrawLine(fId, GetShadowGC()(), 0, 0, 0, fHeight-2);
         gVirtualX->DrawLine(fId, GetBlackGC()(), 1, 1, fWidth-3, 1);
         gVirtualX->DrawLine(fId, GetBlackGC()(), 1, 1, 1, fHeight-3);
         gVirtualX->DrawLine(fId, GetHilightGC()(), 0, fHeight-1, fWidth-1, fHeight-1);
         gVirtualX->DrawLine(fId, GetHilightGC()(), fWidth-1, fHeight-1, fWidth-1, 0);
         gVirtualX->DrawLine(fId, GetBckgndGC()(),  1, fHeight-2, fWidth-2, fHeight-2);
         gVirtualX->DrawLine(fId, GetBckgndGC()(),  fWidth-2, 1, fWidth-2, fHeight-2);
         break;
      default:
         TGFrame::DrawBorder();
         break;
   }
}
void TGView::ScrollToPosition(TGLongPosition pos)
{
   
   if (pos.fX != fHsb->GetPosition()) fHsb->SetPosition(pos.fX / fScrollVal.fX);
   if (pos.fY != fVsb->GetPosition()) fVsb->SetPosition(pos.fY / fScrollVal.fY);
}
void TGView::ScrollCanvas(Int_t new_top, Int_t direction)
{
   
   Point_t points[4];
   Int_t xsrc, ysrc, xdest, ydest, cpyheight, cpywidth;
   if (new_top < 0) {
      return;
   }
   if (direction == kVertical) {
      if (new_top == fVisible.fY) {
         return;
      } 
      points[0].fX = points[3].fX = 0;
      points[1].fX = points[2].fX = fCanvas->GetWidth();
      xsrc = xdest = 0;
      cpywidth = 0;
      if (new_top < fVisible.fY) {
         ysrc = 0;
         ydest = Int_t(fVisible.fY - new_top);
         cpyheight = ydest;
         if (ydest > (Int_t)fCanvas->GetHeight()) {
            ydest = fCanvas->GetHeight();
         }
         points[1].fY = points[0].fY = 0;
         points[3].fY = points[2].fY = ydest; 
      } else {
         ydest = 0;
         ysrc = Int_t(new_top - fVisible.fY);
         cpyheight= ysrc;
         if (ysrc > (Int_t)fCanvas->GetHeight()) {
            ysrc = fCanvas->GetHeight();
         }
         points[1].fY = points[0].fY = fCanvas->GetHeight()-ysrc; 
         points[3].fY = points[2].fY = fCanvas->GetHeight();
      }
      fVisible.fY = new_top;
      if (fVisible.fY < 0) {
         fVisible.fY = 0;
      }
   } else {
      if (new_top == fVisible.fX) {
         return;
      }
      points[0].fY = points[1].fY = 0;
      points[2].fY = points[3].fY = fCanvas->GetHeight();
      ysrc = ydest = 0;
      cpyheight = 0;
      if (new_top < fVisible.fX) {
         xsrc = 0;
         xdest = Int_t(fVisible.fX - new_top);
         cpywidth = xdest;
         if (xdest < 0) {
            xdest = fCanvas->GetWidth();
         }
         points[0].fX = points[3].fX = 0;
         points[1].fX = points[2].fX = xdest ; 
      } else {
         xdest = 0;
         xsrc =  Int_t(new_top - fVisible.fX);
         cpywidth = xsrc;
         if (xsrc > (Int_t)fCanvas->GetWidth()) {
            xsrc = fCanvas->GetWidth();
         }
         points[0].fX = points[3].fX = fCanvas->GetWidth()-xsrc; 
         points[1].fX = points[2].fX = fCanvas->GetWidth();
      }
      fVisible.fX = new_top;
      if (fVisible.fX < 0) {
         fVisible.fX = 0;
      }
   }
   UpdateBackgroundStart();
   
   gVirtualX->CopyArea(fCanvas->GetId(), fCanvas->GetId(), fWhiteGC(),
                       xsrc, ysrc, fCanvas->GetWidth()-cpywidth,
                       fCanvas->GetHeight()-cpyheight, xdest, ydest);
   UInt_t xdiff = points[2].fX - points[0].fX;
   UInt_t ydiff = points[2].fY - points[0].fY;
   
#ifdef WIN32
   xdiff = xdiff << 1;
   ydiff = ydiff << 1;
#endif
   DrawRegion(points[0].fX, points[0].fY, xdiff, ydiff);
}
void TGView::ChangeBackground(Pixel_t col)
{
   
   fCanvas->SetBackgroundColor(col);
   fWhiteGC.SetBackground(col);
   fWhiteGC.SetForeground(col);
   DrawRegion(0, 0, fCanvas->GetWidth(), fCanvas->GetHeight());
}
void TGView::SetBackgroundColor(Pixel_t col)
{
   
   fCanvas->SetBackgroundColor(col);
   fWhiteGC.SetBackground(col);
   fWhiteGC.SetForeground(col);
}
void TGView::SetBackgroundPixmap(Pixmap_t p)
{
   
   fCanvas->SetBackgroundPixmap(p);
}
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.