|
using System;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using System.Collections;
using Creatives.Windows.Metrics;
namespace Creatives.Windows.Controls
{
public class Carousel : Control
{
#region Ctor
public Carousel()
{
Size = new Size(200, 100);
MinimumSize = new Size(100, 100);
BackColor = Color.BurlyWood;
ViewOffset = 20;
ViewMargin = 20;
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
}
#endregion
#region Members
int animating = 0;
public bool IsAnimating
{
get
{
return animating != 0;
}
}
/// <summary>
/// Gets or sets the spacing between adjacent views.
/// </summary>
/// <remarks>Offset is not guranteed, valid only when engough space is available for layout. </remarks>
public int ViewOffset
{
get;
set;
}
private int viewPortItemsCount = 0;
/// <summary>
/// Gets or sets the number of Views visible within view port.
/// </summary>
public int ViewPortItemsCount
{
get
{
return (viewPortItemsCount > Views.Count)
? Views.Count :
viewPortItemsCount;
}
set
{
if (value > 0)
viewPortItemsCount = value;
else
viewPortItemsCount = 0;
}
}
private ViewCollection views = null;
/// <summary>
/// Gets or sets the views associated with the Carousel.
/// </summary>
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ViewCollection Views
{
get
{
if (views == null)
{
views = new ViewCollection(this);
views.CollectionChanged += new EventHandler(OnViewCollectionChanged);
}
return views;
}
set
{
if (views != null)
views.CollectionChanged -= new EventHandler(OnViewCollectionChanged);
views = value;
if (views != null)
views.CollectionChanged -= new EventHandler(OnViewCollectionChanged);
PerformLayout();
}
}
internal CircularList CircularViews { get; set; }
private LayoutManager layoutManager = null;
public View ActiveView
{
get;
set;
}
/// <summary>
/// Gets or sets the offset between carousel and the views.
/// </summary>
public int ViewMargin { get; set; }
#endregion
#region Overriden Members
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
layoutManager = new LayoutManager(this);
int visibleItems = (viewPortItemsCount == 0) ? Views.Count : viewPortItemsCount;
if (visibleItems <= 0) return;
double index = Math.Ceiling(((double)visibleItems / 2));
ActiveView = Views[(int)index - 1];
PerformLayout();
}
protected override void OnHandleDestroyed(EventArgs e)
{
layoutManager.Dispose();
base.OnHandleDestroyed(e);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
foreach (View view in Views)
view.Dispose();
Views.Clear();
}
}
#endregion
#region Implementations
private void BeginAnimation()
{
animating++;
}
private void EndAnimation()
{
if (animating > 0)
animating--;
}
private void OnViewCollectionChanged(object sender, EventArgs e)
{
UnWireViews();
if (!(Disposing || IsDisposed))
{
WireViews();
UpdateQueue();
PerformLayout();
}
}
private void UpdateQueue()
{
CircularViews = new CircularList(Views);
}
private void WireViews()
{
foreach(View view in this.Views)
view.Activated += new EventHandler(OnViewActivated);
}
void OnViewActivated(object sender, EventArgs e)
{
View activeNew = (View)sender;
if (ActiveView == activeNew) return;
int indexActive = Array.IndexOf(CircularViews.ToArray(), ActiveView);
int indexNew = Array.IndexOf(CircularViews.ToArray(), activeNew);
ActiveView = activeNew;
ShiftViews(indexActive, indexNew);
}
private void ShiftViews(int indexActive, int indexNew)
{
layoutManager.ShiftViews(Math.Abs(indexNew - indexActive), indexNew > indexActive);
}
private void UnWireViews()
{
foreach (View view in this.Views)
view.Activated -= new EventHandler(OnViewActivated);
}
protected override void OnLayout(LayoutEventArgs levent)
{
base.OnLayout(levent);
if (layoutManager != null && !IsAnimating)
layoutManager.PerformLayout();
}
public void Activate(View view)
{
}
public void ActivateNext()
{
}
public void ActivatePrevious()
{
}
#endregion
#region ** Layout Manager
private class LayoutManager
{
private Carousel _carousel;
public delegate void InvokeDelegate();
#region Ctor
public LayoutManager(Carousel carousel)
{
_carousel = carousel;
}
#endregion
#region Dispose
/// <summary>
/// Releases any references to the carousel control.
/// </summary>
public void Dispose()
{
this._carousel = null;
}
#endregion
#region Implementation
public void PerformLayout()
{
int heightAvailable = _carousel.Height - 2 *_carousel.ViewMargin ;
int widthAvailable = _carousel.Width - 2 * _carousel.ViewMargin;
int visibleItems = (_carousel.viewPortItemsCount == 0) ? _carousel.Views.Count : _carousel.viewPortItemsCount;
int x = _carousel.ViewMargin;
int y = _carousel.ViewMargin;
if (visibleItems <= 0) return;
int offsetX = _carousel.ViewOffset;
int offsetY = 20;
widthAvailable -= (visibleItems - 1) * offsetX;
int itemWidth = widthAvailable / visibleItems;
int itemHeight = heightAvailable;
foreach (View view in _carousel.CircularViews)
{
itemHeight = (view == _carousel.ActiveView) ? heightAvailable : heightAvailable - offsetY;
view.Size = new Size(itemWidth, itemHeight);
view.Location = new Point(x, y + ((heightAvailable - itemHeight) / 2));
x += view.Width + offsetX;
}
}
public void ShiftViews(int byNos, bool moveLeft)
{
int animOffset = byNos * (_carousel.ActiveView.Width + _carousel.ViewOffset + 2 * _carousel.ViewMargin);
foreach (View view in _carousel.Views)
{
IntAnimation Xanimation = new IntAnimation
{
By = 1,
Interval = 1,
Duration = animOffset * 10,
From = view.Left,
To = (moveLeft) ? view.Left - animOffset : view.Left + animOffset,
};
Xanimation.Completed += new AnimationEventHandler<int>(Xanimation_Completed);
_carousel.BeginAnimation();
view.Animate("Left", Xanimation);
}
while (byNos > 0)
{
if (moveLeft)
_carousel.CircularViews.ShiftLeft();
else
_carousel.CircularViews.ShiftRight();
byNos--;
}
}
private void ShiftLeft()
{
}
void Xanimation_Completed(object sender, AnimationEventArgs<int> e)
{
e.Animation.Completed -= new AnimationEventHandler<int>(Xanimation_Completed);
_carousel.EndAnimation();
if (!_carousel.IsAnimating)
{
_carousel.Invoke(new InvokeDelegate(PerformLayout));
}
}
private void ShiftRight()
{
int animOffset = _carousel.ActiveView.Width + _carousel.ViewOffset + 2 * _carousel.ViewMargin;
foreach (View view in _carousel.Views)
{
IntAnimation Xanimation = new IntAnimation
{
By = 1,
Interval = 1,
Duration = animOffset * 10,
From = view.Left,
To = view.Left + animOffset
};
Xanimation.Completed += new AnimationEventHandler<int>(Xanimation_Completed);
_carousel.BeginAnimation();
view.Animate("Left", Xanimation);
}
_carousel.CircularViews.ShiftRight();
}
#endregion
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.