home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c083 / 11.ddi / OWLSRC.PAK / SCROLLER.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-02  |  9.0 KB  |  395 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1993 by Borland International
  3. //   source\owl\scroller.cpp
  4. //   Implementation of class TScroller.
  5. //----------------------------------------------------------------------------
  6. #pragma hdrignore SECTION
  7. #include <owl\owlpch.h>
  8. #include <owl\scroller.h>
  9. #include <owl\window.h>
  10. #include <owl\dc.h>
  11. #include <stdlib.h>
  12.  
  13. #define max(a,b)   (((a) > (b)) ? (a) : (b))
  14. #define min(a,b)   (((a) < (b)) ? (a) : (b))
  15. #define abs(a)     ((a) >= 0 ? (a) : -(a))
  16.  
  17. #if !defined(SECTION) || SECTION == 1
  18. //
  19. // constructs a TScroller object
  20. //
  21. TScroller::TScroller(TWindow* window,
  22.                      int      xUnit,
  23.                      int      yUnit,
  24.                      long     xRange,
  25.                      long     yRange)
  26. {
  27.   Window = window;
  28.   XPos = YPos = 0;
  29.   XUnit = xUnit;
  30.   YUnit = yUnit;
  31.   XRange = xRange;
  32.   YRange = yRange;
  33.   XLine = 1;  YLine = 1;
  34.   XPage = 1;  YPage = 1;
  35.   AutoMode = TRUE;
  36.   TrackMode = TRUE;
  37.   AutoOrg = TRUE;
  38.   HasHScrollBar = Window && (Window->Attr.Style&WS_HSCROLL);
  39.   HasVScrollBar = Window && (Window->Attr.Style&WS_VSCROLL);
  40. }
  41.  
  42. //
  43. // destructs a TScroller object
  44. //
  45. // sets owning Window's Scroller member to 0
  46. //
  47. TScroller::~TScroller()
  48. {
  49.   if (Window)
  50.     Window->Scroller = 0;
  51. }
  52.  
  53. //
  54. // sets the number of units per page (amount by which to scroll on a page
  55. // scroll request) according to the current size of the Window's client area
  56. //
  57. void
  58. TScroller::SetPageSize()
  59. {
  60.   if (Window) {
  61.     TRect  clientRect;
  62.     Window->GetClientRect(clientRect);
  63.     int width = clientRect.Width();
  64.     int height = clientRect.Height();
  65.  
  66.     if (width && XUnit > 0)
  67.       XPage = max(1, (width+1) / XUnit - 1);
  68.  
  69.     if (height && YUnit > 0)
  70.       YPage = max(1, (height+1) / YUnit - 1);
  71.   }
  72. }
  73.  
  74. //
  75. // sets the range of the TScroller and also sets the range of its
  76. // Window's scrollbars
  77. //
  78. void
  79. TScroller::SetRange(long xRange, long yRange)
  80. {
  81.   XRange = xRange;
  82.   YRange = yRange;
  83.   SetSBarRange();
  84.   ScrollTo(XPos, YPos);
  85. }
  86.  
  87. //
  88. // resets the X and Y scroll unit size (in device units) to the passed
  89. // parameters
  90. //
  91. // calls SetPageSize to update the X and Y page size, which are specified
  92. // in scroll units
  93. //
  94. void
  95. TScroller::SetUnits(int xUnit, int yUnit)
  96. {
  97.   XUnit = xUnit;
  98.   YUnit = yUnit;
  99.   SetPageSize();
  100. }
  101.  
  102. //
  103. // sets the range of the Window's scrollbars & repaints as necessary
  104. //
  105. void
  106. TScroller::SetSBarRange()
  107. {
  108.   if (Window) {
  109.     if (HasHScrollBar) {
  110.       int curMin, curMax;
  111.       Window->GetScrollRange(SB_HORZ, curMin, curMax);
  112.       int newMax = max(0, (int)min(XRange, SHRT_MAX));
  113.       if (newMax != curMax || curMin != 0)
  114.         Window->SetScrollRange(SB_HORZ, 0, newMax, TRUE);
  115.     }
  116.  
  117.     if (HasVScrollBar) {
  118.       int curMin, curMax;
  119.       Window->GetScrollRange(SB_VERT, curMin, curMax);
  120.       int newMax = max(0, (int)min(YRange, SHRT_MAX));
  121.       if (newMax != curMax || curMin != 0)
  122.         Window->SetScrollRange(SB_VERT, 0, newMax, TRUE);
  123.     }
  124.   }
  125. }
  126.  
  127. //
  128. // sets the origin for the paint display context according to XPos, YPos
  129. //
  130. void
  131. TScroller::BeginView(TDC& dc, TRect& rect)
  132. {
  133.   long  xOrg = XPos * XUnit;
  134.   long  yOrg = YPos * YUnit;
  135.  
  136.   if (AutoOrg && xOrg <= SHRT_MAX && yOrg <= SHRT_MAX) {
  137.     TPoint offset(int(-xOrg), int(-yOrg));
  138.     dc.SetViewportOrg(offset);
  139.     rect -= offset;
  140.   }
  141. }
  142.  
  143. //
  144. // updates the position of the Window's scrollbar(s)
  145. //
  146. void
  147. TScroller::EndView()
  148. {
  149.   if (Window) {
  150.     if (HasHScrollBar) {
  151.       int  newPos = XRange > SHRT_MAX ? XScrollValue(XPos) : (int)XPos;
  152.       if (newPos != Window->GetScrollPos(SB_HORZ))
  153.         Window->SetScrollPos(SB_HORZ, newPos, TRUE);
  154.     }
  155.  
  156.     if (HasVScrollBar) {
  157.       int  newPos = YRange > SHRT_MAX ? YScrollValue(YPos) : (int)YPos;
  158.       if (newPos != Window->GetScrollPos(SB_VERT))
  159.         Window->SetScrollPos(SB_VERT, newPos, TRUE);
  160.     }
  161.   }
  162. }
  163.  
  164. //
  165. // scrolls vertically according to scroll action and thumb position
  166. //
  167. void
  168. TScroller::VScroll(UINT scrollEvent, int thumbPos)
  169. {
  170.   switch (scrollEvent) {
  171.     case SB_LINEDOWN:
  172.       ScrollBy(0, YLine);
  173.       break;
  174.  
  175.     case SB_LINEUP:
  176.       ScrollBy(0, -YLine);
  177.       break;
  178.  
  179.     case SB_PAGEDOWN:
  180.       ScrollBy(0, YPage);
  181.       break;
  182.  
  183.     case SB_PAGEUP:
  184.       ScrollBy(0, -YPage);
  185.       break;
  186.  
  187.     case SB_TOP:
  188.       ScrollTo(XPos, 0);
  189.       break;
  190.  
  191.     case SB_BOTTOM:
  192.       ScrollTo(XPos, YRange);
  193.       break;
  194.  
  195.     case SB_THUMBPOSITION:
  196.       if (YRange > SHRT_MAX)
  197.         ScrollTo(XPos, YRangeValue(thumbPos));
  198.  
  199.       else
  200.         ScrollTo(XPos, thumbPos);
  201.       break;
  202.  
  203.     case SB_THUMBTRACK:
  204.       if (TrackMode)
  205.         if (YRange > SHRT_MAX)
  206.          ScrollTo(XPos, YRangeValue(thumbPos));
  207.  
  208.         else
  209.          ScrollTo(XPos, thumbPos);
  210.  
  211.       if (Window && HasVScrollBar)
  212.         Window->SetScrollPos(SB_VERT, thumbPos, TRUE);
  213.       break;
  214.   }
  215. }
  216.  
  217. //
  218. // scrolls horizontally according to scroll action and thumb position
  219. //
  220. void
  221. TScroller::HScroll(UINT scrollEvent, int thumbPos)
  222. {
  223.   switch (scrollEvent) {
  224.     case SB_LINEDOWN:
  225.       ScrollBy(XLine, 0);
  226.       break;
  227.  
  228.     case SB_LINEUP:
  229.       ScrollBy(-XLine, 0);
  230.       break;
  231.  
  232.     case SB_PAGEDOWN:
  233.       ScrollBy(XPage, 0);
  234.       break;
  235.  
  236.     case SB_PAGEUP:
  237.       ScrollBy(-XPage, 0);
  238.       break;
  239.  
  240.     case SB_TOP:
  241.       ScrollTo(0, YPos);
  242.       break;
  243.  
  244.     case SB_BOTTOM:
  245.       ScrollTo(XRange, YPos);
  246.       break;
  247.  
  248.     case SB_THUMBPOSITION:
  249.       if (XRange > SHRT_MAX)
  250.         ScrollTo(XRangeValue(thumbPos), YPos);
  251.  
  252.       else
  253.         ScrollTo(thumbPos, YPos);
  254.       break;
  255.  
  256.     case SB_THUMBTRACK:
  257.       if (TrackMode)
  258.         if (XRange > SHRT_MAX)
  259.           ScrollTo(XRangeValue(thumbPos), YPos);
  260.  
  261.         else
  262.           ScrollTo(thumbPos, YPos);
  263.  
  264.       if (Window && HasHScrollBar)
  265.         Window->SetScrollPos(SB_HORZ, thumbPos, TRUE);
  266.       break;
  267.   }
  268. }
  269.  
  270. //
  271. // scrolls to an (x,y) position, after checking boundary conditions
  272. // causes a WM_PAINT message to be sent
  273. //
  274. // first scrolls the contents of the client area, if a portion of the client
  275. // area will remain visible
  276. //
  277. void
  278. TScroller::ScrollTo(long x, long y)
  279. {
  280.   if (Window) {
  281.     long  newXPos = max(0, min(x, XRange));
  282.     long  newYPos = max(0, min(y, YRange));
  283.  
  284.     if (newXPos != XPos || newYPos != YPos) {
  285.       //
  286.       // scaling isn't needed here. if condition is met, ScrollWindow()
  287.       // will succeed since XPage and YPage are ints
  288.       //
  289.       // if condition isn't met, ScrollWindow() is called in EndScroll()
  290.       // as a result of calling UpdateWindow()
  291.       //
  292.       // EndScroll() performs the necessary scaling
  293.       //
  294.       if (AutoOrg || abs(YPos-newYPos) < YPage && abs(XPos-newXPos) < XPage)
  295.         Window->ScrollWindow((int)(XPos - newXPos) * XUnit,
  296.                 (int)(YPos - newYPos) * YUnit, 0, 0);
  297.  
  298.       else
  299.         Window->Invalidate();
  300.  
  301.       XPos = newXPos;
  302.       YPos = newYPos;
  303.       Window->UpdateWindow();
  304.     }
  305.   }
  306. }
  307.  
  308. //
  309. //
  310. //
  311. BOOL
  312. TScroller::IsAutoMode()
  313. {
  314.   return AutoMode;
  315. }
  316.  
  317. //
  318. // performs "auto-scrolling" (dragging the mouse from within the client
  319. // client area of the Window to without results in auto-scrolling when
  320. // the AutoMode data member of the Scroller is TRUE)
  321. //
  322. void
  323. TScroller::AutoScroll()
  324. {
  325.   if (AutoMode && Window) {
  326.     TRect  clientRect;
  327.     TPoint cursorPos;
  328.     long  dx = 0, dy = 0;
  329.  
  330.     GetCursorPos(&cursorPos);
  331.     Window->ScreenToClient(cursorPos);
  332.     Window->GetClientRect(clientRect);
  333.  
  334.     if (cursorPos.y < 0)
  335.       dy = min(-YLine, max(-YPage, cursorPos.y / 10 * YLine));
  336.  
  337.     else if (cursorPos.y > clientRect.bottom)
  338.       dy = max(YLine, min(YPage, (cursorPos.y-clientRect.bottom)/10 * YLine));
  339.  
  340.     if (cursorPos.x < 0)
  341.       dx = min(-XLine, max(-XPage, cursorPos.x / 10 * XLine));
  342.  
  343.     else if (cursorPos.x > clientRect.right)
  344.       dx = max(XLine, min(XPage, (cursorPos.x-clientRect.right)/10 * XLine));
  345.  
  346.     ScrollBy(dx, dy);
  347.   }
  348. }
  349.  
  350. #endif
  351. #if !defined(SECTION) || SECTION == 2
  352.  
  353. IMPLEMENT_STREAMABLE(TScroller);
  354.  
  355. //
  356. // reads an instance of TScroller from the passed ipstream
  357. //
  358. void*
  359. TScroller::Streamer::Read(ipstream& is, uint32 /*version*/) const
  360. {
  361.   TScroller* o = GetObject();
  362.   is >> o->XPos >> o->YPos >>
  363.       o->XUnit >> o->YUnit >>
  364.       o->XRange >> o->YRange >>
  365.       o->XLine >> o->YLine >>
  366.       o->XPage >> o->YPage >>
  367.       o->AutoMode >> o->TrackMode >>
  368.       o->AutoOrg >>
  369.       o->HasHScrollBar >> o->HasVScrollBar;
  370.  
  371.   o->Window = 0;
  372.   return o;
  373. }
  374.  
  375. //
  376. // writes the TScroller to the passed opstream
  377. //
  378. void
  379. TScroller::Streamer::Write(opstream& os) const
  380. {
  381.   TScroller* o = GetObject();
  382.   os << o->XPos << o->YPos <<
  383.       o->XUnit << o->YUnit <<
  384.       o->XRange << o->YRange <<
  385.       o->XLine << o->YLine <<
  386.       o->XPage << o->YPage <<
  387.       o->AutoMode << o->TrackMode <<
  388.       o->AutoOrg <<
  389.       o->HasHScrollBar << o->HasVScrollBar;
  390. }
  391.  
  392.  
  393. #endif
  394.  
  395.