Merge "[NUI] Fix WidgetView dispose issue"
[platform/core/csapi/tizenfx.git] / src / ElmSharp / ElmSharp / List.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Collections.Generic;
19
20 namespace ElmSharp
21 {
22     /// <summary>
23     /// Enumeration for setting list's resizing behavior, transverse axis scrolling and items cropping.
24     /// </summary>
25     public enum ListMode
26     {
27         /// <summary>
28         /// The list won't set any of its size hints to inform how a possible container should resize it.
29         /// Then, if it's not created as a "resize object", it might end with zeroed dimensions.
30         /// The list will respect the container's geometry and, if any of its items won't fit into its transverse axis, one won't be able to scroll it in that direction.
31         /// </summary>
32         Compress = 0,
33         /// <summary>
34         /// This is the same as Compress, with the exception that if any of its items won't fit into its transverse axis, one will be able to scroll it in that direction.
35         /// </summary>
36         Scroll,
37         /// <summary>
38         /// Sets a minimum size hint on the genlist object, so that containers may respect it (and resize itself to fit the child properly).
39         /// More specifically, a minimum size hint will be set for its transverse axis, so that the largest item in that direction fits well.
40         /// This is naturally bound by the list object's maximum size hints, set externally.
41         /// </summary>
42         Limit,
43         /// <summary>
44         /// Besides setting a minimum size on the transverse axis, just like on Limit, the list will set a minimum size on th longitudinal axis, trying to reserve space to all its children to be visible at a time.
45         /// This is naturally bound by the list object's maximum size hints, set externally.
46         /// </summary>
47         Expand
48     }
49
50     /// <summary>
51     /// It inherits System.EventArgs.
52     /// It contains Item which is <see cref="ListItem"/> type.
53     /// All events of List contain ListItemEventArgs as a parameter.
54     /// </summary>
55     public class ListItemEventArgs : EventArgs
56     {
57         /// <summary>
58         /// Gets or sets List item. The return type is <see cref="ListItem"/>.
59         /// </summary>
60         public ListItem Item { get; set; }
61
62         internal static ListItemEventArgs CreateFromSmartEvent(IntPtr data, IntPtr obj, IntPtr info)
63         {
64             ListItem item = ItemObject.GetItemByHandle(info) as ListItem;
65             return new ListItemEventArgs() { Item = item };
66         }
67     }
68
69     /// <summary>
70     /// It inherits <see cref="Layout"/>.
71     /// The List is a widget that aims to display simple list item which has 2 icons and 1 text, and can be selected.
72     /// For more robust lists, <see cref="GenList"/> should probably be used.
73     /// </summary>
74     /// <seealso cref="GenList"/>
75     /// <seealso cref="GenGrid"/>
76     public class List : Layout, IScrollable
77     {
78         ScrollableAdapter _scroller;
79         HashSet<ListItem> _children = new HashSet<ListItem>();
80         SmartEvent<ListItemEventArgs> _selected;
81         SmartEvent<ListItemEventArgs> _unselected;
82         SmartEvent<ListItemEventArgs> _doubleClicked;
83         SmartEvent<ListItemEventArgs> _longpressed;
84         SmartEvent<ListItemEventArgs> _activated;
85
86         /// <summary>
87         /// Creates and initializes a new instance of the List class.
88         /// </summary>
89         /// <param name="parent">The parent is a given container which will be attached by List as a child. It's <see cref="EvasObject"/> type.</param>
90         public List(EvasObject parent) : base(parent)
91         {
92             _selected = new SmartEvent<ListItemEventArgs>(this, this.RealHandle, "selected", ListItemEventArgs.CreateFromSmartEvent);
93             _unselected = new SmartEvent<ListItemEventArgs>(this, this.RealHandle, "unselected", ListItemEventArgs.CreateFromSmartEvent);
94             _doubleClicked = new SmartEvent<ListItemEventArgs>(this, this.RealHandle, "clicked,double", ListItemEventArgs.CreateFromSmartEvent);
95             _longpressed = new SmartEvent<ListItemEventArgs>(this, this.RealHandle, "longpressed", ListItemEventArgs.CreateFromSmartEvent);
96             _activated = new SmartEvent<ListItemEventArgs>(this, this.RealHandle, "activated", ListItemEventArgs.CreateFromSmartEvent);
97             _selected.On += (s, e) => { ItemSelected?.Invoke(this, e); };
98             _unselected.On += (s, e) => { ItemUnselected?.Invoke(this, e); };
99             _doubleClicked.On += (s, e) => { ItemDoubleClicked?.Invoke(this, e); };
100             _longpressed.On += (s, e) => { ItemLongPressed?.Invoke(this, e); };
101             _activated.On += (s, e) => { ItemActivated?.Invoke(this, e); };
102         }
103
104         /// <summary>
105         /// Gets or sets which mode to use for the list.
106         /// </summary>
107         public ListMode Mode
108         {
109             get
110             {
111                 return (ListMode)Interop.Elementary.elm_list_mode_get(RealHandle);
112             }
113             set
114             {
115                 Interop.Elementary.elm_list_mode_set(RealHandle, (Interop.Elementary.Elm_List_Mode)value);
116             }
117         }
118
119         /// <summary>
120         /// Gets the selected item.
121         /// </summary>
122         public ListItem SelectedItem
123         {
124             get
125             {
126                 IntPtr item = Interop.Elementary.elm_list_selected_item_get(RealHandle);
127                 return ItemObject.GetItemByHandle(item) as ListItem;
128             }
129         }
130
131         /// <summary>
132         /// ItemSelected is raised when a new list item is selected.
133         /// </summary>
134         public event EventHandler<ListItemEventArgs> ItemSelected;
135
136         /// <summary>
137         /// ItemUnselected is raised when the list item is Unselected.
138         /// </summary>
139         public event EventHandler<ListItemEventArgs> ItemUnselected;
140
141         /// <summary>
142         /// ItemDoubleClicked is raised when a new list item is double clicked.
143         /// </summary>
144         public event EventHandler<ListItemEventArgs> ItemDoubleClicked;
145
146         /// <summary>
147         /// ItemLongPressed is raised when a list item is pressed for a certain amount of time. By default it's 1 second.
148         /// </summary>
149         public event EventHandler<ListItemEventArgs> ItemLongPressed;
150
151         /// <summary>
152         /// ItemActivated is raised when a new list item is double clicked or pressed (enter|return|spacebar).
153         /// </summary>
154         public event EventHandler<ListItemEventArgs> ItemActivated;
155
156         /// <summary>
157         /// Starts the list.
158         /// Call before running <see cref="EvasObject.Show"/> on the list object.
159         /// If not called, it won't display the list properly.
160         /// </summary>
161         public void Update()
162         {
163             Interop.Elementary.elm_list_go(RealHandle);
164         }
165
166         /// <summary>
167         /// Appends a new item with a text to the end of a given list widget.
168         /// </summary>
169         /// <param name="label">The text for the item.</param>
170         /// <returns>Return a new added list item that contains a text.</returns>
171         /// <seealso cref="ListItem"/>
172         public ListItem Append(string label)
173         {
174             return Append(label, null, null);
175         }
176
177         /// <summary>
178         /// Appends a new item with a text and 2 icons to the end of a given list widget.
179         /// </summary>
180         /// <param name="label">The text for the item.</param>
181         /// <param name="leftIcon">The left icon for the item.</param>
182         /// <param name="rightIcon">The right icon for the item.</param>
183         /// <returns>Return a new added list item that contains a text and 2 icons.</returns>
184         /// <seealso cref="ListItem"/>
185         public ListItem Append(string label, EvasObject leftIcon, EvasObject rightIcon)
186         {
187             ListItem item = new ListItem(label, leftIcon, rightIcon);
188             item.Handle = Interop.Elementary.elm_list_item_append(RealHandle, label, leftIcon, rightIcon, null, (IntPtr)item.Id);
189             AddInternal(item);
190             return item;
191         }
192
193         /// <summary>
194         /// Prepends a new item with a text to the beginning of a given list widget.
195         /// </summary>
196         /// <param name="label">The text for the item.</param>
197         /// <returns>Return a new added list item that contains a text.</returns>
198         public ListItem Prepend(string label)
199         {
200             return Prepend(label, null, null);
201         }
202
203         /// <summary>
204         /// Prepends a new item with a text and 2 icons to the beginning of a given list widget.
205         /// </summary>
206         /// <param name="label">The text for the item.</param>
207         /// <param name="leftIcon">The left icon for the item.</param>
208         /// <param name="rigthIcon">The right icon for the item.</param>
209         /// <returns>Return a new added list item that contains a text and 2 icons.</returns>
210         public ListItem Prepend(string label, EvasObject leftIcon, EvasObject rigthIcon)
211         {
212             ListItem item = new ListItem(label, leftIcon, rigthIcon);
213             item.Handle = Interop.Elementary.elm_list_item_prepend(RealHandle, label, leftIcon, rigthIcon, null, (IntPtr)item.Id);
214             AddInternal(item);
215             return item;
216         }
217
218         /// <summary>
219         /// Removes all items from a given list widget.
220         /// To delete just one item, use <see cref="ItemObject.Delete"/>.
221         /// </summary>
222         public void Clear()
223         {
224             Interop.Elementary.elm_list_clear(RealHandle);
225             foreach (var item in _children)
226             {
227                 item.Deleted -= Item_Deleted;
228             }
229             _children.Clear();
230         }
231
232         /// <summary>
233         /// Creates a widget handle.
234         /// </summary>
235         /// <param name="parent">Parent EvasObject</param>
236         /// <returns>Handle IntPtr</returns>
237         protected override IntPtr CreateHandle(EvasObject parent)
238         {
239             IntPtr handle = Interop.Elementary.elm_layout_add(parent.Handle);
240             Interop.Elementary.elm_layout_theme_set(handle, "layout", "elm_widget", "default");
241
242             RealHandle = Interop.Elementary.elm_list_add(handle);
243             Interop.Elementary.elm_object_part_content_set(handle, "elm.swallow.content", RealHandle);
244
245             _scroller = new ScrollableAdapter(this);
246
247             return handle;
248         }
249
250         #region IScroller Implementation
251
252         /// <summary>
253         /// Scrolled will be triggered when the content has been scrolled.
254         /// </summary>
255         public event EventHandler Scrolled
256         {
257             add => _scroller.Scrolled += value;
258             remove => _scroller.Scrolled -= value;
259         }
260
261         /// <summary>
262         /// DragStart will be triggered when dragging the contents around has started.
263         /// </summary>
264         public event EventHandler DragStart
265         {
266             add => _scroller.DragStart += value;
267             remove => _scroller.DragStart -= value;
268         }
269
270         /// <summary>
271         /// DragStop will be triggered when dragging the contents around has stopped.
272         /// </summary>
273         public event EventHandler DragStop
274         {
275             add => _scroller.DragStop += value;
276             remove => _scroller.DragStop -= value;
277         }
278
279         /// <summary>
280         /// PageScrolled will be triggered when the visible page has changed.
281         /// </summary>
282         public event EventHandler PageScrolled
283         {
284             add => _scroller.PageScrolled += value;
285             remove => _scroller.PageScrolled -= value;
286         }
287
288         /// <summary>
289         /// Gets the current region in the content object that is visible through the Scroller.
290         /// </summary>
291         public Rect CurrentRegion => _scroller.CurrentRegion;
292
293         /// <summary>
294         /// Sets or gets the value of HorizontalScrollBarVisiblePolicy
295         /// </summary>
296         /// <remarks>
297         /// ScrollBarVisiblePolicy.Auto means the horizontal scrollbar is made visible if it is needed, and otherwise kept hidden.
298         /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
299         /// </remarks>
300         public virtual ScrollBarVisiblePolicy HorizontalScrollBarVisiblePolicy
301         {
302             get => _scroller.HorizontalScrollBarVisiblePolicy;
303             set => _scroller.HorizontalScrollBarVisiblePolicy = value;
304         }
305
306         /// <summary>
307         /// Sets or gets the value of VerticalScrollBarVisiblePolicy
308         /// </summary>
309         /// <remarks>
310         /// ScrollBarVisiblePolicy.Auto means the vertical scrollbar is made visible if it is needed, and otherwise kept hidden.
311         /// ScrollBarVisiblePolicy.Visible turns it on all the time, and ScrollBarVisiblePolicy.Invisible always keeps it off.
312         /// </remarks>
313         public virtual ScrollBarVisiblePolicy VerticalScrollBarVisiblePolicy
314         {
315             get => _scroller.VerticalScrollBarVisiblePolicy;
316             set => _scroller.VerticalScrollBarVisiblePolicy = value;
317         }
318
319         /// <summary>
320         /// Sets or gets the value of ScrollBlock.
321         /// </summary>
322         /// <remarks>
323         /// This function will block scrolling movement  in a given direction.One can disable movements in the X axis, the Y axis or both.
324         /// The default value is ScrollBlock.None, where movements are allowed in both directions.
325         /// </remarks>
326         public ScrollBlock ScrollBlock
327         {
328             get => _scroller.ScrollBlock;
329             set => _scroller.ScrollBlock = value;
330         }
331
332         /// <summary>
333         /// Sets or gets scroll current page number.
334         /// </summary>
335         /// <remarks>
336         /// Current page means the page which meets the top of the viewport.
337         /// If there are two or more pages in the viewport, it returns the number of the page which meets the top of the viewport.
338         /// The page number starts from 0. 0 is the first page.
339         /// </remarks>
340         public int VerticalPageIndex => _scroller.VerticalPageIndex;
341
342         /// <summary>
343         /// Sets or gets scroll current page number.
344         /// </summary>
345         /// <remarks>
346         /// Current page means the page which meets the left of the viewport.
347         /// If there are two or more pages in the viewport, it returns the number of the page which meets the left of the viewport.
348         /// The page number starts from 0. 0 is the first page.
349         /// </remarks>
350         public int HorizontalPageIndex => _scroller.HorizontalPageIndex;
351
352         /// <summary>
353         /// Sets or gets the maximum limit of the movable page at vertical direction.
354         /// </summary>
355         public int VerticalPageScrollLimit
356         {
357             get => _scroller.VerticalPageScrollLimit;
358             set => _scroller.VerticalPageScrollLimit = value;
359         }
360
361         /// <summary>
362         /// Sets or gets the maximum limit of the movable page at horizontal direction.
363         /// </summary>
364         public int HorizontalPageScrollLimit
365         {
366             get => _scroller.HorizontalPageScrollLimit;
367             set => _scroller.HorizontalPageScrollLimit = value;
368         }
369
370         /// <summary>
371         /// Sets or gets the vertical bounce behaviour.
372         /// When scrolling, the scroller may "bounce" when reaching an edge of the content object.
373         /// This is a visual way to indicate the end has been reached.
374         /// This is enabled by default for both axis.
375         /// This API will set if it is enabled for the given axis with the boolean parameters for each axis.
376         /// </summary>
377         public bool VerticalBounce
378         {
379             get => _scroller.VerticalBounce;
380             set => _scroller.VerticalBounce = value;
381         }
382
383         /// <summary>
384         /// Sets or gets the horizontal bounce behaviour.
385         /// When scrolling, the scroller may "bounce" when reaching an edge of the content object.
386         /// This is a visual way to indicate the end has been reached.
387         /// This is enabled by default for both axis.
388         /// This API will set if it is enabled for the given axis with the boolean parameters for each axis.
389         /// </summary>
390         public bool HorizontalBounce
391         {
392             get => _scroller.HorizontalBounce;
393             set => _scroller.HorizontalBounce = value;
394         }
395
396         /// <summary>
397         /// Gets the width of the content object of the scroller.
398         /// </summary>
399         public int ChildWidth
400         {
401             get => _scroller.ChildWidth;
402         }
403
404         /// <summary>
405         /// Gets the height of the content object of the scroller.
406         /// </summary>
407         public int ChildHeight
408         {
409             get => _scroller.ChildHeight;
410         }
411
412         /// <summary>
413         /// Set scrolling gravity values for a scroller.
414         /// The gravity, defines how the scroller will adjust its view when the size of the scroller contents increase.
415         /// The scroller will adjust the view to glue itself as follows.
416         /// x=0.0, for staying where it is relative to the left edge of the content x=1.0, for staying where it is relative to the rigth edge of the content y=0.0, for staying where it is relative to the top edge of the content y=1.0, for staying where it is relative to the bottom edge of the content
417         /// Default values for x and y are 0.0
418         /// </summary>
419         public double HorizontalGravity
420         {
421             get => _scroller.HorizontalGravity;
422             set => _scroller.HorizontalGravity = value;
423         }
424
425         /// <summary>
426         /// Set scrolling gravity values for a scroller.
427         /// The gravity, defines how the scroller will adjust its view when the size of the scroller contents increase.
428         /// The scroller will adjust the view to glue itself as follows.
429         /// x=0.0, for staying where it is relative to the left edge of the content x=1.0, for staying where it is relative to the rigth edge of the content y=0.0, for staying where it is relative to the top edge of the content y=1.0, for staying where it is relative to the bottom edge of the content
430         /// Default values for x and y are 0.0
431         /// </summary>
432         public double VerticalGravity
433         {
434             get => _scroller.VerticalGravity;
435             set => _scroller.VerticalGravity = value;
436         }
437
438         /// <summary>
439         /// Get scroll last page number.
440         /// The page number starts from 0. 0 is the first page. This returns the last page number among the pages.
441         /// </summary>
442         public int LastVerticalPageNumber => _scroller.LastVerticalPageNumber;
443
444         /// <summary>
445         /// Get scroll last page number.
446         /// The page number starts from 0. 0 is the first page. This returns the last page number among the pages.
447         /// </summary>
448         public int LastHorizontalPageNumber => _scroller.LastHorizontalPageNumber;
449
450         /// <summary>
451         /// Set an infinite loop_ for a scroller.
452         /// This function sets the infinite loop vertically.
453         /// If the content is set, it will be shown repeatedly.
454         /// </summary>
455         public bool VerticalLoop
456         {
457             get => _scroller.VerticalLoop;
458             set => _scroller.VerticalLoop = value;
459         }
460
461         /// <summary>
462         /// Set an infinite loop_ for a scroller.
463         /// This function sets the infinite loop horizontally.
464         /// If the content is set, it will be shown repeatedly.
465         /// </summary>
466         public bool HorizontalLoop
467         {
468             get => _scroller.HorizontalLoop;
469             set => _scroller.HorizontalLoop = value;
470         }
471
472         /// <summary>
473         /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
474         /// </summary>
475         public int HorizontalPageSize
476         {
477             get => _scroller.HorizontalPageSize;
478             set => _scroller.HorizontalPageSize = value;
479         }
480
481         /// <summary>
482         /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
483         /// </summary>
484         public int VerticalPageSize
485         {
486             get => _scroller.VerticalPageSize;
487             set => _scroller.VerticalPageSize = value;
488         }
489
490         /// <summary>
491         /// Gets or sets a given scroller widget's scrolling page size, relative to its viewport size.
492         /// </summary>
493         public double VerticalRelativePageSize
494         {
495             get => _scroller.VerticalRelativePageSize;
496             set => _scroller.VerticalRelativePageSize = value;
497         }
498
499         /// <summary>
500         /// Gets or sets a given scroller widget's scrolling page size, relative to its viewport size.
501         /// </summary>
502         public double HorizontalRelativePageSize
503         {
504             get => _scroller.HorizontalRelativePageSize;
505             set => _scroller.HorizontalRelativePageSize = value;
506         }
507
508         /// <summary>
509         /// Gets or Sets the page snapping behavior of a scroller.
510         /// </summary>
511         /// <remarks>
512         /// When scrolling, if a scroller is paged (see VerticalRelativePageSize),
513         /// the scroller may snap to pages when being scrolled, i.e., even if it had momentum to scroll further,
514         /// it will stop at the next page boundaries. This is disabled, by default, for both axis.
515         /// This function will set if it that is enabled or not, for each axis.
516         /// </remarks>
517         public bool VerticalSnap
518         {
519             get => _scroller.VerticalSnap;
520             set => _scroller.VerticalSnap = value;
521         }
522
523         /// <summary>
524         /// Gets or Sets the page snapping behavior of a scroller.
525         /// </summary>
526         /// <remarks>
527         /// When scrolling, if a scroller is paged (see HorizontalRelativePageSize),
528         /// the scroller may snap to pages when being scrolled, i.e., even if it had momentum to scroll further,
529         /// it will stop at the next page boundaries. This is disabled, by default, for both axis.
530         /// This function will set if it that is enabled or not, for each axis.
531         /// </remarks>
532         public bool HorizontalSnap
533         {
534             get => _scroller.HorizontalSnap;
535             set => _scroller.HorizontalSnap = value;
536         }
537
538         /// <summary>
539         /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
540         /// </summary>
541         public int PageHeight
542         {
543             get => _scroller.PageHeight;
544             set => _scroller.PageHeight = value;
545         }
546
547         /// <summary>
548         /// Gets or sets the page size to an absolute fixed value, with 0 turning it off for that axis.
549         /// </summary>
550         public int PageWidth
551         {
552             get => _scroller.PageWidth;
553             set => _scroller.PageWidth = value;
554         }
555
556         /// <summary>
557         /// Gets or sets the step size to move scroller by key event.
558         /// </summary>
559         public int HorizontalStepSize
560         {
561             get => _scroller.HorizontalStepSize;
562             set => _scroller.HorizontalStepSize = value;
563         }
564
565         /// <summary>
566         /// Gets or sets the step size to move scroller by key event.
567         /// </summary>
568         public int VerticalStepSize
569         {
570             get => _scroller.VerticalStepSize;
571             set => _scroller.VerticalStepSize = value;
572         }
573
574         /// <summary>
575         /// Gets or sets a value whether mouse wheel is enabled or not over the scroller.
576         /// </summary>
577         public bool WheelDisabled
578         {
579             get => _scroller.WheelDisabled;
580             set => _scroller.WheelDisabled = value;
581         }
582
583         /// <summary>
584         /// Gets or sets the type of single direction scroll.
585         /// </summary>
586         public ScrollSingleDirection SingleDirection
587         {
588             get => _scroller.SingleDirection;
589             set => _scroller.SingleDirection = value;
590         }
591
592         /// <summary>
593         /// Sets the scroller minimum size limited to the minimum size of the content.
594         /// By default the scroller will be as small as its design allows, irrespective of its content.
595         /// This will make the scroller minimum size the right size horizontally and/or vertically to perfectly fit its content in that direction.
596         /// </summary>
597         /// <param name="horizontal">Enable limiting minimum size horizontally</param>
598         /// <param name="vertical">Enable limiting minimum size vertically</param>
599         public void MinimumLimit(bool horizontal, bool vertical)
600         {
601             _scroller.MinimumLimit(horizontal, vertical);
602         }
603
604         /// <summary>
605         /// Shows a specific virtual region within the scroller content object by the page number.
606         /// (0, 0) of the indicated page is located at the top-left corner of the viewport.
607         /// </summary>
608         /// <param name="horizontalPageIndex">The horizontal page number.</param>
609         /// <param name="verticalPageIndex">The vertical page number.</param>
610         /// <param name="animated">True means slider with animation.</param>
611         public void ScrollTo(int horizontalPageIndex, int verticalPageIndex, bool animated)
612         {
613             _scroller.ScrollTo(horizontalPageIndex, verticalPageIndex, animated);
614         }
615
616         /// <summary>
617         /// Shows a specific virtual region within the scroller content object.
618         /// </summary>
619         /// <remarks>
620         /// This ensures that all (or part, if it does not fit) of the designated region in the virtual content object ((0, 0)
621         /// starting at the top-left of the virtual content object) is shown within the scroller.
622         /// If set "animated" to true, it will allows the scroller to "smoothly slide" to this location
623         /// (if configuration in general calls for transitions).
624         /// It may not jump immediately to the new location and may take a while and show other content along the way.
625         /// </remarks>
626         /// <param name="region">Rect struct of region.</param>
627         /// <param name="animated">True means allows the scroller to "smoothly slide" to this location.</param>
628         public void ScrollTo(Rect region, bool animated)
629         {
630             _scroller.ScrollTo(region, animated);
631         }
632
633         #endregion
634
635         void AddInternal(ListItem item)
636         {
637             _children.Add(item);
638             item.Deleted += Item_Deleted;
639         }
640
641         void Item_Deleted(object sender, EventArgs e)
642         {
643             _children.Remove((ListItem)sender);
644         }
645     }
646 }