scroll.pas 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2000 by B'rczi, Gÿbor
  4. member of the Free Pascal development team
  5. Support objects for the install program
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit Scroll;
  13. interface
  14. uses Objects,
  15. FVConsts,
  16. Drivers,Views,App;
  17. const
  18. CScrollBoxBackground = #6;
  19. type
  20. PScrollBoxBackground = ^TScrollBoxBackground;
  21. TScrollBoxBackground = object(TBackground)
  22. function GetPalette: PPalette; virtual;
  23. end;
  24. PScrollBox = ^TScrollBox;
  25. TScrollBox = object(TGroup)
  26. Delta,Limit: TPoint;
  27. HScrollBar,VScrollBar: PScrollBar;
  28. Background: PScrollBoxBackground;
  29. constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  30. procedure InitBackground; virtual;
  31. procedure HandleEvent(var Event: TEvent); virtual;
  32. procedure ChangeBounds(var Bounds: TRect); virtual;
  33. procedure ScrollDraw; virtual;
  34. procedure ScrollTo(X, Y: Sw_Integer);
  35. procedure SetLimit(X, Y: Sw_Integer);
  36. procedure SetState(AState: Word; Enable: Boolean); virtual;
  37. procedure TrackCursor;
  38. procedure Draw; virtual;
  39. function ClipChilds: boolean; virtual;
  40. procedure BeforeInsert(P: PView); virtual;
  41. procedure AfterInsert(P: PView); virtual;
  42. procedure AfterDelete(P: PView); virtual;
  43. private
  44. DrawLock: Byte;
  45. DrawFlag: Boolean;
  46. ScrollFlag : boolean;
  47. procedure CheckDraw;
  48. procedure UpdateLimits;
  49. procedure ShiftViews(DX,DY: sw_integer);
  50. end;
  51. implementation
  52. function TScrollBoxBackground.GetPalette: PPalette;
  53. const P: string[length(CScrollBoxBackground)] = CScrollBoxBackground;
  54. begin
  55. GetPalette:=@P;
  56. end;
  57. constructor TScrollBox.Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  58. begin
  59. inherited Init(Bounds);
  60. EventMask:=EventMask or evBroadcast;
  61. HScrollBar:=AHScrollBar; VScrollBar:=AVScrollBar;
  62. InitBackground;
  63. if Assigned(Background) then Insert(Background);
  64. ReDraw;
  65. end;
  66. procedure TScrollBox.InitBackground;
  67. var R: TRect;
  68. begin
  69. GetExtent(R);
  70. New(Background, Init(R,' '));
  71. end;
  72. procedure TScrollBox.HandleEvent(var Event: TEvent);
  73. begin
  74. if (Event.What=evBroadcast) and (Event.Command=cmCursorChanged) then
  75. TrackCursor;
  76. If (Event.What = evBroadcast) AND
  77. (Event.Command = cmScrollBarChanged) AND { Scroll bar change }
  78. Not ScrollFlag AND
  79. ((Event.InfoPtr = HScrollBar) OR { Our scrollbar? }
  80. (Event.InfoPtr = VScrollBar)) Then ScrollDraw; { Redraw scroller }
  81. inherited HandleEvent(Event);
  82. end;
  83. procedure TScrollBox.ChangeBounds(var Bounds: TRect);
  84. begin
  85. SetBounds(Bounds);
  86. Inc(DrawLock);
  87. SetLimit(Limit.X, Limit.Y);
  88. Dec(DrawLock);
  89. DrawFlag := False;
  90. DrawView;
  91. end;
  92. procedure TScrollBox.CheckDraw;
  93. begin
  94. if (DrawLock = 0) and DrawFlag then
  95. begin
  96. DrawFlag := False;
  97. ReDraw; DrawView;
  98. end;
  99. end;
  100. procedure TScrollBox.ScrollDraw;
  101. var
  102. D: TPoint;
  103. begin
  104. if HScrollBar <> nil then
  105. D.X := HScrollBar^.Value
  106. else
  107. D.X := 0;
  108. if VScrollBar <> nil then
  109. D.Y := VScrollBar^.Value
  110. else
  111. D.Y := 0;
  112. if (D.X <> Delta.X) or (D.Y <> Delta.Y) then
  113. begin
  114. SetCursor(Cursor.X + Delta.X - D.X, Cursor.Y + Delta.Y - D.Y);
  115. ScrollTo(D.X,D.Y);
  116. if DrawLock <> 0 then
  117. DrawFlag := True
  118. else
  119. DrawView;
  120. end;
  121. end;
  122. procedure TScrollBox.ScrollTo(X, Y: Sw_Integer);
  123. var DX,DY: sw_integer;
  124. PrevScrollFlag : boolean;
  125. begin
  126. Inc(DrawLock);
  127. DX:=Delta.X-X;
  128. DY:=Delta.Y-Y;
  129. PrevScrollFlag:=ScrollFlag;
  130. ScrollFlag:=true;
  131. if HScrollBar <> nil then
  132. HScrollBar^.SetValue(X);
  133. if VScrollBar <> nil then
  134. VScrollBar^.SetValue(Y);
  135. ScrollFlag:=PrevScrollFlag;
  136. ShiftViews(DX,DY);
  137. Dec(DrawLock);
  138. CheckDraw;
  139. end;
  140. procedure TScrollBox.ShiftViews(DX,DY: sw_integer);
  141. procedure DoShift(P: PView);
  142. begin
  143. P^.MoveTo(P^.Origin.X+DX,P^.Origin.Y+DY);
  144. end;
  145. begin
  146. ForEach(@DoShift);
  147. Delta.X:=Delta.X-DX;
  148. Delta.Y:=Delta.Y-DY;
  149. end;
  150. procedure TScrollBox.SetLimit(X, Y: Sw_Integer);
  151. begin
  152. Limit.X := X;
  153. Limit.Y := Y;
  154. Inc(DrawLock);
  155. if HScrollBar <> nil then
  156. HScrollBar^.SetParams(HScrollBar^.Value, HScrollBar^.Min, HScrollBar^.Max, HScrollBar^.PgStep, HScrollBar^.ArStep);
  157. if VScrollBar <> nil then
  158. VScrollBar^.SetParams(VScrollBar^.Value, VScrollBar^.Min, VScrollBar^.Max, VScrollBar^.PgStep, VScrollBar^.ArStep);
  159. Dec(DrawLock);
  160. CheckDraw;
  161. end;
  162. procedure TScrollBox.SetState(AState: Word; Enable: Boolean);
  163. procedure ShowSBar(SBar: PScrollBar);
  164. begin
  165. if (SBar <> nil) then
  166. if GetState(sfActive + sfSelected) then
  167. SBar^.Show
  168. else
  169. SBar^.Hide;
  170. end;
  171. var OState: word;
  172. begin
  173. OState:=State;
  174. inherited SetState(AState, Enable);
  175. if AState and (sfActive + sfSelected) <> 0 then
  176. begin
  177. ShowSBar(HScrollBar);
  178. ShowSBar(VScrollBar);
  179. end;
  180. if ((OState xor State) and (sfFocused))<>0 then
  181. TrackCursor;
  182. end;
  183. procedure TScrollBox.TrackCursor;
  184. var V: PView;
  185. P,ND: TPoint;
  186. begin
  187. V:=Current;
  188. if (not Assigned(V)) then Exit;
  189. P.X:=V^.Origin.X+V^.Cursor.X;
  190. P.Y:=V^.Origin.Y+V^.Cursor.Y;
  191. ND:=Delta;
  192. if (P.X<0) then
  193. Dec(ND.X,-P.X)
  194. else
  195. if (P.X>=Size.X) then
  196. Inc(ND.X,P.X-(Size.X-1));
  197. if (P.Y<0) then
  198. Dec(ND.Y,-P.Y)
  199. else
  200. if (P.Y>=Size.Y) then
  201. Inc(ND.Y,P.Y-(Size.Y-1));
  202. if (ND.X<>Delta.X) or (ND.Y<>Delta.Y) then
  203. ScrollTo(ND.X,ND.Y);
  204. end;
  205. function TScrollBox.ClipChilds: boolean;
  206. begin
  207. ClipChilds:=false;
  208. end;
  209. procedure TScrollBox.BeforeInsert(P: PView);
  210. begin
  211. if Assigned(P) then
  212. P^.MoveTo(P^.Origin.X-Delta.X,P^.Origin.Y-Delta.Y);
  213. end;
  214. procedure TScrollBox.AfterInsert(P: PView);
  215. begin
  216. UpdateLimits;
  217. end;
  218. procedure TScrollBox.AfterDelete(P: PView);
  219. begin
  220. { UpdateLimits;
  221. removed because it creates GPF PM }
  222. end;
  223. procedure TScrollBox.Draw;
  224. begin
  225. inherited Draw;
  226. end;
  227. procedure TScrollBox.UpdateLimits;
  228. var Max: TPoint;
  229. procedure Check(P: PView);
  230. var O: TPoint;
  231. begin
  232. O.X:=P^.Origin.X+P^.Size.X+Delta.X;
  233. O.Y:=P^.Origin.Y+P^.Size.Y+Delta.Y;
  234. if O.X>Max.X then
  235. Max.X:=O.X;
  236. if O.Y>Max.Y then
  237. Max.Y:=O.Y;
  238. end;
  239. begin
  240. Max.X:=0; Max.Y:=0;
  241. ForEach(@Check);
  242. if (Max.X<>Limit.X) or (Max.Y<>Limit.Y) then
  243. SetLimit(Max.X,Max.Y);
  244. end;
  245. END.