home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / owlsrc.pak / SCROLLER.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  9.0 KB  |  396 lines

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