source: 2013/30/MiskaK/MW2(My Warfare 2)/Paranneltu Jypeli/GameObjects/VerticalScrollLayout.cs @ 4507

Revision 4507, 10.3 KB checked in by anlakane, 6 years ago (diff)

Talletus.

Line 
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
30using System;
31using System.ComponentModel;
32using System.Collections.Generic;
33
34namespace Jypeli.GameObjects
35{
36    /// <summary>
37    /// Asettelee widgetit päällekäin, järjestyksessä ylhäältä alas.
38    /// Jos widgeteille ei ole tarpeeksi tilaa, vain osa niistä asetellaan
39    /// paikalleen. Ensimmäisen näkyvän widgetin indeksi asetetaan <c>Update</c>:ssa
40    /// propertyyn <c>StartIndex</c> ja viimeisen jälkeisen indeksi propertyyn
41    /// <c>EndIndex</c>.
42    /// </summary>
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
61        /// <summary>
62        /// Olioiden väliin jäävä tyhjä tila.
63        /// </summary>
64        public double Spacing
65        {
66            get { return _spacing; }
67            set { _spacing = value; NotifyParent(); }
68        }
69
70        /// <summary>
71        /// Yläreunaan jäävä tyhjä tila.
72        /// </summary>
73        public double TopPadding
74        {
75            get { return _topPadding; }
76            set { _topPadding = value; NotifyParent(); }
77        }
78
79        /// <summary>
80        /// Alareunaan jäävä tyhjä tila.
81        /// </summary>
82        public double BottomPadding
83        {
84            get { return _bottomPadding; }
85            set { _bottomPadding = value; NotifyParent(); }
86        }
87
88        /// <summary>
89        /// Vasempaan reunaan jäävä tyhjä tila.
90        /// </summary>
91        public double LeftPadding
92        {
93            get { return _leftPadding; }
94            set { _leftPadding = value; NotifyParent(); }
95        }
96
97        /// <summary>
98        /// Oikeaan reunaan jäävä tyhjä tila.
99        /// </summary>
100        public double RightPadding
101        {
102            get { return _rightPadding; }
103            set { _rightPadding = value; NotifyParent(); }
104        }
105
106        /// <summary>
107        /// Ylhäältä lukien ensimmäisen piirtoalueen sisällä olevan widgetin indeksi.
108        /// </summary>
109        public int StartIndex { get; set; }
110
111        /// <summary>
112        /// Viimeisen piirtoalueella olevan widgetin jälkeinen indeksi.
113        /// </summary>
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
144        /// <summary>
145        /// Listan portaaton vieritys.
146        /// </summary>
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}
Note: See TracBrowser for help on using the repository browser.