/Controle.Silverlight/PainelCarrossel.cs
C# | 377 lines | 316 code | 61 blank | 0 comment | 28 complexity | 9e700c50bd23c5364da1ccf3f70684bd MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Input;
- using System.Windows.Media;
-
- namespace BrasilFramework.Controle.Silverlight
- {
- public class PainelCarrossel : Panel
- {
-
- public PainelCarrossel()
- {
- Movimentou = true;
- }
-
- private void CompositionTarget_Rendering(object sender, EventArgs e)
- {
- Desenhar();
- }
-
- #region Propriedades
-
- public static readonly DependencyProperty AlturaElipsePropriedade = DependencyProperty.Register("AlturaElipse",
- typeof(double),
- typeof(PainelCarrossel),
- new PropertyMetadata(10.00));
-
- public static readonly DependencyProperty LarguraElipsePropriedade = DependencyProperty.Register("LarguraElipse",
- typeof(double),
- typeof(PainelCarrossel),
- new PropertyMetadata(200.00));
-
- public static readonly DependencyProperty DirecaoPropriedade = DependencyProperty.Register("Direcao", typeof(Direcao),
- typeof(PainelCarrossel),
- new PropertyMetadata(
- Direcao.Esquerda));
-
- public static readonly DependencyProperty ExecutarAutomaticamentePropriedade =
- DependencyProperty.Register("ExecutarAutomaticamente", typeof(bool), typeof(PainelCarrossel),
- new PropertyMetadata(true));
-
- public static readonly DependencyProperty ElementoSelecionadoPropriedade =
- DependencyProperty.Register("ElementoSelecionado", typeof(FrameworkElement), typeof(PainelCarrossel),
- new PropertyMetadata(null));
-
-
- public double LarguraElipse
- {
- get { return (double)GetValue(LarguraElipsePropriedade); }
- set { SetValue(LarguraElipsePropriedade, value); }
- }
-
- public double AlturaElipse
- {
- get { return (double)GetValue(AlturaElipsePropriedade); }
- set { SetValue(AlturaElipsePropriedade, value); }
- }
-
- public Direcao Direcao
- {
- get { return (Direcao)GetValue(DirecaoPropriedade); }
- set { SetValue(DirecaoPropriedade, value); }
- }
-
- public FrameworkElement ElementoSelecionado
- {
- get { return (FrameworkElement)GetValue(ElementoSelecionadoPropriedade); }
- set { SetValue(ElementoSelecionadoPropriedade, value); }
- }
-
- #endregion
-
- #region Constantes
-
- private const double ALFA_MAXIMO = 1;
- private const double ESCALA_MAXIMA = 1;
- private const double ALFA_MINIMO = 0.8;
- private const double ESCALA_MINIMA = 0.4;
- private const double VELOCIDADE = 0.1;
- private const double POSICAO_VISUALIZACAO = 0;
-
- #endregion
-
- #region Variáveis Internas
-
- private Dictionary<FrameworkElement, ElementoCaracteristica> listaFilhoInterno =
- new Dictionary<FrameworkElement, ElementoCaracteristica>();
-
- private int proximaAlturaProfundidade;
- private double distancia;
-
- private bool movimentou;
-
- private bool Movimentou
- {
- get { return movimentou; }
- set
- {
- if (value && !movimentou)
- CompositionTarget.Rendering += CompositionTarget_Rendering;
-
- movimentou = value;
- }
- }
- private List<double> listaAlfa;
- private List<double> listaEscala;
-
- #endregion
-
- #region Eventos
-
- public delegate void PainelCarrosselSelectedItemHandler(
- PainelCarrossel sender, PainelCarrosselSelectedItemEventArgs e);
-
- public event PainelCarrosselSelectedItemHandler SelectedItem;
-
- private void OnItemMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
- {
- var elemento = sender as FrameworkElement;
-
- if (elemento == null) return;
- ElementoCaracteristica elementoCaracteristica = listaFilhoInterno[elemento];
-
- if (elementoCaracteristica.indice == 1)
- {
- if (!Movimentou && SelectedItem != null)
- SelectedItem(this, new PainelCarrosselSelectedItemEventArgs((FrameworkElement)sender));
- }
- else if (elementoCaracteristica.transposicaoDestino.X > Centro.X)
- {
- int proximaPosicao = listaFilhoInterno.Count - elementoCaracteristica.indice + 1;
- Mover(proximaPosicao, Direcao.Direita);
- }
- else
- {
- int proximaPosicao = elementoCaracteristica.indice - 1;
- Mover(proximaPosicao, Direcao.Esquerda);
- }
- }
-
- #endregion
-
- private int quantidadeAtualizacao;
-
- private void Desenhar()
- {
- foreach (FrameworkElement element in listaFilhoInterno.Keys)
- {
- ElementoCaracteristica elementoCaracteristica = listaFilhoInterno[element];
- elementoCaracteristica.transposicaoOrigem.X = -element.ActualWidth / 2.0;
- elementoCaracteristica.transposicaoOrigem.Y = -element.ActualHeight / 2.0;
- elementoCaracteristica.transposicaoDestino.X = LarguraElipse * Math.Cos(elementoCaracteristica.tempo) + Centro.X;
- elementoCaracteristica.transposicaoDestino.Y = AlturaElipse * Math.Sin(elementoCaracteristica.tempo) + Centro.Y;
- elementoCaracteristica.tempo = elementoCaracteristica.tempo + VELOCIDADE * (elementoCaracteristica.destino - elementoCaracteristica.tempo);
- Canvas.SetZIndex(element, Convert.ToInt32(elementoCaracteristica.transposicaoDestino.Y));
- distancia = 6.283185E+000 / listaFilhoInterno.Count;
-
- if (quantidadeAtualizacao <= 1) continue;
-
- elementoCaracteristica.escalaDestino.ScaleX = elementoCaracteristica.escalaDestino.ScaleX +
- VELOCIDADE * (elementoCaracteristica.escala - elementoCaracteristica.escalaDestino.ScaleX);
- elementoCaracteristica.escalaDestino.ScaleY = elementoCaracteristica.escalaDestino.ScaleX;
- element.Opacity = element.Opacity + VELOCIDADE * (elementoCaracteristica.alfa - element.Opacity);
- }
-
- if (Movimentou) Movimentou = false;
-
- if (++quantidadeAtualizacao <= 250) return;
-
- CompositionTarget.Rendering -= CompositionTarget_Rendering;
- quantidadeAtualizacao = 0;
- }
-
- private Point Centro
- {
- get { return new Point(ActualWidth / 2, ActualHeight / 2); }
- }
-
- public void AdicionarFilho(FrameworkElement item)
- {
- TranslateTransform transposicaoDestino = new TranslateTransform();
- RotateTransform rotacaoDestino = new RotateTransform();
- ScaleTransform escalaDestino = new ScaleTransform();
- SkewTransform torcerDestino = new SkewTransform();
- TranslateTransform transposicaoOrigem = new TranslateTransform();
- item.RenderTransform = new TransformGroup
- {
- Children =
- new TransformCollection
- {
- rotacaoDestino,
- escalaDestino,
- torcerDestino,
- transposicaoDestino,
- transposicaoOrigem
- }
- };
- ElementoCaracteristica elementoCaracteristica = new ElementoCaracteristica
- {
- rotacaoDestino = rotacaoDestino,
- escalaDestino = escalaDestino,
- torcerDestino = torcerDestino,
- transposicaoDestino = transposicaoDestino,
- transposicaoOrigem = transposicaoOrigem
- };
-
- listaFilhoInterno.Add(item, elementoCaracteristica);
- item.MouseLeftButtonUp += OnItemMouseLeftButtonUp;
- proximaAlturaProfundidade++;
- Children.Add(item);
- CarregarFilhos();
- }
-
- private void CarregarFilhos()
- {
- int i = 1;
- InicializarEscalaTransparencia();
- foreach (FrameworkElement element in listaFilhoInterno.Keys)
- {
- ElementoCaracteristica elementoCaracteristica = listaFilhoInterno[element];
- elementoCaracteristica.destino = 6.283185E+000 * (i - 1) / listaFilhoInterno.Count + (1.570796E+000 + POSICAO_VISUALIZACAO);
- elementoCaracteristica.origem = elementoCaracteristica.destino;
- elementoCaracteristica.indice = i;
- elementoCaracteristica.escala = listaEscala[i - 1];
- elementoCaracteristica.alfa = listaAlfa[i - 1];
- i++;
- if (elementoCaracteristica.indice == 1)
- {
- ElementoSelecionado = element;
- }
- }
- }
-
- private void InicializarEscalaTransparencia()
- {
- listaEscala = new List<double>();
- listaAlfa = new List<double>();
- double escalaMedida = (ESCALA_MAXIMA - ESCALA_MINIMA) / (listaFilhoInterno.Count / 2.0);
- double alfaMedida = (ALFA_MAXIMO - ALFA_MINIMO) / (listaFilhoInterno.Count / 2.0);
- int indiceCentro = ((listaFilhoInterno.Count / 2.0) > Convert.ToInt32(listaFilhoInterno.Count / 2))
- ? Convert.ToInt32(listaFilhoInterno.Count / 2) + 1
- : Convert.ToInt32(listaFilhoInterno.Count / 2);
-
- for (int i = 0; i < listaFilhoInterno.Count; i++)
- {
- if (i < indiceCentro)
- {
- listaEscala.Add((ESCALA_MAXIMA - escalaMedida * i));
- listaAlfa.Add((ALFA_MAXIMO - alfaMedida * i));
- }
- else
- {
- listaEscala.Add((ESCALA_MINIMA + escalaMedida * (i - indiceCentro)));
- listaAlfa.Add((ALFA_MINIMO + alfaMedida * (i - indiceCentro)));
- }
- }
- }
-
- public void RemoverFilhos()
- {
- foreach (FrameworkElement element in listaFilhoInterno.Keys)
- {
- Children.Remove(element);
- }
- listaFilhoInterno = new Dictionary<FrameworkElement, ElementoCaracteristica>();
- }
-
- public void Mover(int posicaoItem, Direcao direcao)
- {
- Movimentou = true;
-
- foreach (FrameworkElement element in listaFilhoInterno.Keys)
- {
- ElementoCaracteristica elementoCaracteristica = listaFilhoInterno[element];
- if (direcao == Direcao.Direita)
- {
- elementoCaracteristica.destino = elementoCaracteristica.origem + 6.283185E+000 / listaFilhoInterno.Count + distancia * (posicaoItem - 1);
- elementoCaracteristica.origem = elementoCaracteristica.destino;
- for (int j = 1; j <= posicaoItem; ++j)
- {
- if (elementoCaracteristica.indice == listaFilhoInterno.Count)
- {
- elementoCaracteristica.indice = 1;
- continue;
- }
- ++elementoCaracteristica.indice;
- }
- }
- else
- {
- elementoCaracteristica.destino = elementoCaracteristica.origem - 6.283185E+000 / listaFilhoInterno.Count - distancia * (posicaoItem - 1);
- elementoCaracteristica.origem = elementoCaracteristica.destino;
- for (int j = 1; j <= posicaoItem; ++j)
- {
- if (elementoCaracteristica.indice == 1)
- {
- elementoCaracteristica.indice = listaFilhoInterno.Count;
- continue;
- }
- --elementoCaracteristica.indice;
- }
- }
- if (elementoCaracteristica.indice == 1)
- {
- ElementoSelecionado = element;
- }
-
- elementoCaracteristica.escala = listaEscala[elementoCaracteristica.indice - 1];
- elementoCaracteristica.alfa = listaAlfa[elementoCaracteristica.indice - 1];
-
- }
-
- Desenhar();
- }
-
- #region Disposição e Tamanho
-
- protected override Size ArrangeOverride(Size finalSize)
- {
- foreach (UIElement elemento in Children)
- {
- Point location = new Point();
- elemento.Arrange(new Rect(location, elemento.DesiredSize));
- }
- return finalSize;
- }
-
- protected override Size MeasureOverride(Size availableSize)
- {
- foreach (UIElement elemento in Children)
- {
- elemento.Measure(availableSize);
- }
- Clip = new RectangleGeometry { Rect = new Rect(new Point(), availableSize) };
- return availableSize;
- }
-
- #endregion
-
- #region Classes Internas - Auxiliares
-
- public class PainelCarrosselSelectedItemEventArgs : RoutedEventArgs
- {
- public readonly FrameworkElement SelectedItem;
-
- public PainelCarrosselSelectedItemEventArgs(FrameworkElement item)
- {
- SelectedItem = item;
- }
- }
-
- private class ElementoCaracteristica
- {
- internal double alfa;
- internal int indice;
- internal TranslateTransform transposicaoOrigem;
- internal double origem;
- internal double escala;
- internal double tempo;
- internal double destino;
- internal RotateTransform rotacaoDestino;
- internal ScaleTransform escalaDestino;
- internal SkewTransform torcerDestino;
- internal TranslateTransform transposicaoDestino;
- }
-
- #endregion
- }
-
- public enum Direcao
- {
- Esquerda,
- Direita
- }
- }