home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / OWLSRC.PAK / SCROLLER.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  10.3 KB  |  452 lines

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