Jypeli  5
The simple game programming library
VerticalScrollLayout.cs
Siirry tämän tiedoston dokumentaatioon.
1 #region MIT License
2 /*
3  * Copyright (c) 2009-2011 University of Jyväskylä, Department of Mathematical
4  * Information Technology.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #endregion
25 
26 /*
27  * Authors: Tomi Karppinen, Tero Jäntti
28  */
29 
30 using System;
31 using System.ComponentModel;
32 using System.Collections.Generic;
33 
34 namespace Jypeli.GameObjects
35 {
43  internal class VerticalScrollLayout : ILayout
44  {
45  private Sizing _horizontalSizing;
46  private Sizing _verticalSizing;
47  private Vector _preferredSize;
48  private double _heightRequestedByExpandingObjects;
49  private double _heightRequestedByFixedSizeObjects;
50  private double _spacing = 0;
51  private double _topPadding = 0;
52  private double _bottomPadding = 0;
53  private double _leftPadding = 0;
54  private double _rightPadding = 0;
55  private double _firstVisibleItemOffset = 0;
56 
57 
58  [EditorBrowsable( EditorBrowsableState.Never )]
59  public GameObject Parent { get; set; }
60 
64  public double Spacing
65  {
66  get { return _spacing; }
67  set { _spacing = value; NotifyParent(); }
68  }
69 
73  public double TopPadding
74  {
75  get { return _topPadding; }
76  set { _topPadding = value; NotifyParent(); }
77  }
78 
82  public double BottomPadding
83  {
84  get { return _bottomPadding; }
85  set { _bottomPadding = value; NotifyParent(); }
86  }
87 
91  public double LeftPadding
92  {
93  get { return _leftPadding; }
94  set { _leftPadding = value; NotifyParent(); }
95  }
96 
100  public double RightPadding
101  {
102  get { return _rightPadding; }
103  set { _rightPadding = value; NotifyParent(); }
104  }
105 
109  public int StartIndex { get; set; }
110 
114  public int EndIndex { get; set; }
115 
116  private void NotifyParent()
117  {
118  if ( Parent != null )
119  {
120  Parent.NotifyParentAboutChangedSizingAttributes();
121  }
122  }
123 
124  public void ScrollUp( IList<GameObject> objects )
125  {
126  if ( StartIndex > 0 )
127  {
128  StartIndex--;
129  _firstVisibleItemOffset = 0;
130  Update( objects, Parent.Size );
131  }
132  }
133 
134  public void ScrollDown( IList<GameObject> objects )
135  {
136  if ( StartIndex < objects.Count - 1 )
137  {
138  StartIndex++;
139  _firstVisibleItemOffset = 0;
140  Update( objects, Parent.Size );
141  }
142  }
143 
147  public void Scroll( IList<GameObject> objects, double amount )
148  {
149  if ( objects.Count == 0 ) return;
150 
151  if ( amount < 0 )
152  {
153  double totalScrollingAmount = -amount;
154  double spaceForCurrentObject = _firstVisibleItemOffset;
155 
156  while ( spaceForCurrentObject < totalScrollingAmount )
157  {
158  if ( StartIndex == 0 )
159  {
160  spaceForCurrentObject = 0;
161  break;
162  }
163 
164  totalScrollingAmount -= spaceForCurrentObject;
165  StartIndex--;
166  spaceForCurrentObject = objects[StartIndex].PreferredSize.Y + Spacing;
167  }
168 
169  spaceForCurrentObject -= totalScrollingAmount;
170  _firstVisibleItemOffset = spaceForCurrentObject;
171  }
172  else
173  {
174  double totalScrollingAmount = -amount;
175  double spaceForCurrentObject = objects[StartIndex].PreferredSize.Y + Spacing - _firstVisibleItemOffset;
176 
177  while ( spaceForCurrentObject < -totalScrollingAmount )
178  {
179  if ( StartIndex >= objects.Count - 1 )
180  {
181  spaceForCurrentObject = 0;
182  break;
183  }
184 
185  totalScrollingAmount += spaceForCurrentObject;
186  StartIndex++;
187  spaceForCurrentObject = objects[StartIndex].PreferredSize.Y + Spacing;
188  }
189 
190  spaceForCurrentObject += totalScrollingAmount;
191  _firstVisibleItemOffset = objects[StartIndex].PreferredSize.Y + Spacing - spaceForCurrentObject;
192  }
193 
194  Update( objects, Parent.Size );
195  }
196 
197  [EditorBrowsable( EditorBrowsableState.Never )]
198  public void UpdateSizeHints( IList<GameObject> objects )
199  {
200  if ( objects.Count == 0 )
201  return;
202 
203  double maxWidth = 0;
204  double heightOfExpandingObjects = 0;
205  double heightOfFixedSizeObjects = 0;
206  Sizing horizontalSizing = Sizing.FixedSize;
207  Sizing verticalSizing = Sizing.FixedSize;
208 
209  foreach ( var o in objects )
210  {
211  if ( o.PreferredSize.X > maxWidth )
212  {
213  maxWidth = o.PreferredSize.X;
214  }
215 
216  if ( o.VerticalSizing != Sizing.FixedSize )
217  {
218  verticalSizing = Sizing.Expanding;
219  heightOfExpandingObjects += o.PreferredSize.Y;
220  }
221  else if ( o.VerticalSizing == Sizing.FixedSize )
222  {
223  heightOfFixedSizeObjects += o.PreferredSize.Y;
224  }
225 
226  if ( o.HorizontalSizing != Sizing.FixedSize )
227  {
228  horizontalSizing = Sizing.Expanding;
229  }
230  }
231 
232  double preferredHeight = TopPadding + heightOfExpandingObjects + heightOfFixedSizeObjects + ( ( objects.Count - 1 ) * Spacing ) + BottomPadding;
233  double preferredWidth = LeftPadding + maxWidth + RightPadding;
234 
235  _horizontalSizing = horizontalSizing;
236  _verticalSizing = verticalSizing;
237  _heightRequestedByExpandingObjects = heightOfExpandingObjects;
238  _heightRequestedByFixedSizeObjects = heightOfFixedSizeObjects;
239  _preferredSize = new Vector( preferredWidth, preferredHeight );
240  }
241 
242  [EditorBrowsable( EditorBrowsableState.Never )]
243  public Sizing HorizontalSizing
244  {
245  get { return _horizontalSizing; }
246  }
247 
248  [EditorBrowsable( EditorBrowsableState.Never )]
249  public Sizing VerticalSizing
250  {
251  get { return _verticalSizing; }
252  }
253 
254  [EditorBrowsable( EditorBrowsableState.Never )]
255  public Vector PreferredSize
256  {
257  get { return _preferredSize; }
258  }
259 
260  [EditorBrowsable( EditorBrowsableState.Never )]
261  public void Update( IList<GameObject> objects, Vector maximumSize )
262  {
263  double contentHeight = maximumSize.Y - ( TopPadding + BottomPadding );
264  double contentWidth = maximumSize.X - ( LeftPadding + RightPadding );
265  double contentBottomLimit = -maximumSize.Y / 2 + BottomPadding;
266  double top = maximumSize.Y / 2 - TopPadding;
267  double offset = _firstVisibleItemOffset;
268  int i = StartIndex;
269 
270  while ( ( i < objects.Count ) && ( top >= contentBottomLimit ) )
271  {
272  GameObject o = objects[i];
273  double width = o.PreferredSize.X;
274  double height = o.PreferredSize.Y;
275 
276  if ( ( o.PreferredSize.X > contentWidth ) || ( o.HorizontalSizing != Sizing.FixedSize ) )
277  {
278  width = contentWidth;
279  }
280 
281  o.Size = new Vector( width, height );
282  o.X = ( -maximumSize.X / 2 ) + ( LeftPadding + contentWidth / 2 );
283  o.Y = top - height / 2 + offset;
284 
285  top -= height + Spacing - offset;
286 
287  // offset is zero for all but the first object.
288  offset = 0;
289  i++;
290  }
291 
292  EndIndex = i;
293  }
294  }
295 }
Sizing
Olion koon asettaminen asettelijan sisällä.
Definition: ILayout.cs:38