bc... []
Home » Source Code » WPF 3D Tab Carousel » Carousel.xaml.cs

Carousel.xaml.cs ( File view )

  • By maninwest 2015-02-10
  • View(s):24
  • Download(s):0
  • Point(s): 1
			using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Bornander.Wpf.Meshes;
using System.Windows.Media.Media3D;
using System.Windows.Media.Animation;
using System.ComponentModel;

namespace Bornander.UI.TabCarousel
{

    public partial class Carousel : UserControl, INotifyPropertyChanged
    {

        private class SpinInstruction
        {

            public int From {
 get; private set; 
}
            public int To {
 get; private set; 
}

            public SpinInstruction(int from, int to)
            {

                From = from;
                To = to;
            
}
        
}

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        private IList<Tab> tabs = new List<Tab>();
        private IList<FrameworkElement> elements = new List<FrameworkElement>();

        private Queue<SpinInstruction> instructions = new Queue<SpinInstruction>();

        private int currentIndex = 0;
        private int currentTabIndex = 0;

        private int animationDuration = 1000;
        private bool isAnimating = false;
        private bool alwaysOnlyOneStep = false;
        private bool wrapAtEnd = false;
        private double depth;

        
        public Carousel()
        {

            InitializeComponent();

            NumberOfTabs = 3;
            Depth = 0.1;
        
}

        private void OnPropertyChanged(string propertyName)
        {

            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        
}

        private void Organize(int numberOfTabs)
        {

            CarouselContainer.Children.Clear();

            foreach (Tab tab in tabs)
                tab.Element = null;

            IList<Tab> newTabs = new List<Tab>();
            for (int i = 0; i < numberOfTabs; ++i)
            {

                FrameworkElement element = i < elements.Count ? elements[i] : new Label {
 Content = i, Background = Brushes.CadetBlue 
};
                Tab tab = new Tab(element, Color, Depth);
                newTabs.Add(tab);

                CarouselContainer.Children.Add(tab.Model);
            
}

            tabs = newTabs;
            currentIndex = 0;
            currentTabIndex = 0;
            CarouselContainer.Transform = new Transform3DGroup();

            RecalculateTransforms();
        
}

        private static double DegreesToRadians(double degrees)
        {

            return (degrees / 180.0) * Math.PI;
        
}

        private double CalculateRadius()
        {

            double splitAngle = 360.0 / tabs.Count;
            switch (tabs.Count)
            {

                case 1: return 0.0;
                case 2: return 0.25;
                default:
                    return 1.0 / Math.Abs(Math.Sin(DegreesToRadians(splitAngle)));
            
}
        
}

        private int GetSafeIndex(int unsafeIndex)
        {

            return unsafeIndex >= 0 ? unsafeIndex % tabs.Count : tabs.Count - (Math.Abs(unsafeIndex) % tabs.Count);
        
}

        private double CalculateCameraDistance(int index, int tabIndex)
        {

            Tab tab = tabs[tabIndex];

            double y = 0.5 / Math.Tan(DegreesToRadians(MainCamera.FieldOfView / 2.0));

            double panelWidth = tab.Element != null ? tab.Element.Width : 1.0;
            double ratio = Grid3D.ActualWidth / panelWidth;

            return CalculateRadius() + Math.Max(ratio, 1.0) * y;
        
}

        private void RecalculateTransforms()
        {

            if (tabs.Count == 0)
                return;

            double angle = 360.0 / tabs.Count;
            double radius = CalculateRadius();
            for (int i = 0; i < tabs.Count; ++i)
            {

                tabs[i].UpdateTransform(i, angle, radius);
            
}

            MainCamera.Transform = new TranslateTransform3D(0, 0, CalculateCameraDistance(currentIndex, currentTabIndex));
        
}

        private void Animate()
        {

            if (instructions.Count == 0 || isAnimating)
                return;

            SpinInstruction instruction = instructions.Peek();

            bool wrapIt = false;

            if (instruction.To < 0 || instruction.To >= elements.Count)
            {

                if (WrapAtEnd && (instruction.To == -1 || instruction.To == elements.Count))
                {

                    wrapIt = true;
                    instruction = new SpinInstruction(instruction.From, instruction.To < 0 ? elements.Count - 1 : 0);
                
}
                else
                {

                    instructions.Dequeue();
                    isAnimating = false;
                    return;
                
}
            
}
            double angle = 360.0 / tabs.Count;

            int tabToIndex = AlwaysOnlyOneStep ? GetSafeIndex(currentTabIndex + Math.Sign(instruction.To - instruction.From)) : GetSafeIndex(instruction.To);
            if (wrapIt)
            {

                if (instruction.To == 0)
                    tabToIndex = 0;
                if (instruction.To == elements.Count - 1)
                    tabToIndex = tabs.Count - 1;
            
}

            // Unhook if required
            foreach (Tab owner in (from tab in tabs where tab.Element == elements[instruction.To] || tab.Element == elements[instruction.From] select tab))
                owner.Element = null;


            tabs[currentTabIndex].Element = elements[instruction.From];
            tabs[currentTabIndex].UpdateTransform(currentTabIndex, angle, CalculateRadius());


            tabs[tabToIndex].Element = elements[instruction.To];
            tabs[tabToIndex].UpdateTransform(tabToIndex, angle, CalculateRadius());
            isAnimating = true;

            double fromAngle = currentTabIndex * angle;
            double toAngle = tabToIndex * angle;

            if (wrapIt)
            {

                if (instruction.To == 0)
                    toAngle += 360;
                if (instruction.To == elements.Count - 1)
                    toAngle -= 360;
            
}

            if (instruction.To - instruction.From > 0 && tabToIndex < currentTabIndex)
                toAngle += 360;

            if (instruction.To - instruction.From < 0 && tabToIndex > currentTabIndex)
                toAngle -= 360;

            CreateSpinAnimation(instruction, tabToIndex, fromAngle, toAngle);
        
}

        private void CreateSpinAnimation(SpinInstruction instruction, int tabToIndex, double fromAngle, double toAngle)
        {

            RotateTransform3D flipTransform = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 0, 1), 0));
            DoubleAnimation flipAnimation = new DoubleAnimation(0, 360, new Duration(new TimeSpan(0, 0, 0, 0, animationDuration)));

            RotateTransform3D spinTransform = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 1, 0), 0));
            DoubleAnimation spinAnimation = new DoubleAnimation(fromAngle, toAngle, new Duration(new TimeSpan(0, 0, 0, 0, animationDuration)));
            spinAnimation.Completed += (sender, e) =>
            {

                instructions.Dequeue();
                currentIndex = instruction.To;
                currentTabIndex = tabToIndex;

                isAnimating = false;
                Animate();
            
};

            spinTransform.Rotation.BeginAnimation(AxisAngleRotation3D.AngleProperty, spinAnimation);

            if (EnableFlip)
                flipTransform.Rotation.BeginAnimation(AxisAngleRotation3D.AngleProperty, flipAnimation);

            Transform3DGroup carouselTransform = new Transform3DGroup();

            carouselTransform.Children.Add(spinTransform);
            if (EnableFlip)
                carouselTransform.Children.Add(flipTransform);

            CarouselContainer.Transform = carouselTransform;

            double currentDistance = CalculateCameraDistance(instruction.From, currentTabIndex);
            double nextDistance = CalculateCameraDistance(instruction.To, tabToIndex);
            System.Diagnostics.Debug.WriteLine(nextDistance);
            DoubleAnimation cameraAnimation = new DoubleAnimation(currentDistance, nextDistance, new Duration(new TimeSpan(0, 0, 0, 0, animationDuration)));
            Transform3D cameraTransform = new TranslateTransform3D(0, 0, currentDistance);
            MainCamera.Transform = cameraTransform;

            cameraTransform.BeginAnimation(TranslateTransform3D.OffsetZProperty, cameraAnimation);
        
}


        #region Public properties

        public bool EnableFlip {
 get; set; 
}

        public Color Color {
 get; set; 
}

        public bool AlwaysOnlyOneStep
        {

            get {
 return alwaysOnlyOneStep; 
}
            set
            {

                alwaysOnlyOneStep = value;
                if (alwaysOnlyOneStep)
                    NumberOfTabs = Math.Min(NumberOfTabs, 4);

                Organize(NumberOfTabs);

                OnPropertyChanged("AlwaysOnlyOneStep");
            
}

        
}

        public double Depth
        {

            get {
 return depth; 
}
            set
            {

                depth = value;
                Organize(NumberOfTabs);
                OnPropertyChanged("Depth");
            
}
        
}

        public bool WrapAtEnd 
        {

            get {
 return wrapAtEnd; 
}
            set
            {

                wrapAtEnd = value;
                OnPropertyChanged("WrapAtEnd");
            
}
        
}

        public int NumberOfTabs
        {

            get {
 return tabs.Count; 
}
            set
            {

                if (v
...
...
(Not finished, please download and read the complete file)
			
...
Expand> <Close

Want complete source code? Download it here

Point(s): 1

Download
0 lines left, continue to read

File list

Tips: You can preview the content of files by clicking file names^_^
Name Size Date
Bornander.UI.TabCarousel.sln1.97 kB2009-12-26 13:54
01.96 kB
App.xaml313.00 B2009-12-26 13:42
App.xaml.cs331.00 B2009-12-26 13:38
Bornander.UI.TabCarousel.Test.csproj4.69 kB2010-01-01 20:45
Bornander.UI.TabCarousel.Test.csproj.user74.00 B2009-12-26 13:45
01.96 kB
LoginPanel.xaml1.98 kB2010-01-01 20:45
LoginPanel.xaml.cs200.00 B2010-01-01 20:45
MainWindow.xaml3.03 kB2010-01-01 21:24
MainWindow.xaml.cs2.98 kB2010-01-01 21:25
01.96 kB
AssemblyInfo.cs2.27 kB2009-12-26 13:38
Resources.Designer.cs2.82 kB2009-12-26 13:38
Resources.resx5.48 kB2009-12-26 13:38
Settings.Designer.cs1.09 kB2009-12-26 13:38
Settings.settings201.00 B2009-12-26 13:38
01.96 kB
Bornander.UI.TabCarousel.csproj3.46 kB2009-12-26 15:04
Carousel.xaml1.03 kB2009-12-28 19:39
Carousel.xaml.cs11.61 kB2009-12-28 20:57
01.96 kB
AssemblyInfo.cs1.43 kB2009-12-26 13:45
Tab.cs2.77 kB2009-12-28 20:34
01.96 kB
Bornander.Wpf.Meshes.csproj2.85 kB2009-12-26 14:15
Box.cs3.81 kB2009-12-26 14:47
Plane.cs1.65 kB2009-12-26 14:49
01.96 kB
AssemblyInfo.cs1.42 kB2009-12-26 13:51
...

Carousel.xaml.cs (22.50 kB)

Need 1 point
Your Point(s)

Your Point isn't enough.

Get point immediately by PayPal

More(Debit card / Credit card / PayPal Credit / Online Banking)

Submit your source codes. Get more point

LOGIN

Don't have an account? Register now
Need any help?
Mail to: support@codeforge.com

切换到中文版?

CodeForge Chinese Version
CodeForge English Version

Where are you going?

^_^"Oops ...

Sorry!This guy is mysterious, its blog hasn't been opened, try another, please!
OK

Warm tip!

CodeForge to FavoriteFavorite by Ctrl+D