PageRenderTime 26ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/Controle.Silverlight/PainelCarrossel.cs

#
C# | 377 lines | 316 code | 61 blank | 0 comment | 28 complexity | 9e700c50bd23c5364da1ccf3f70684bd MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Windows;
  4. using System.Windows.Controls;
  5. using System.Windows.Input;
  6. using System.Windows.Media;
  7. namespace BrasilFramework.Controle.Silverlight
  8. {
  9. public class PainelCarrossel : Panel
  10. {
  11. public PainelCarrossel()
  12. {
  13. Movimentou = true;
  14. }
  15. private void CompositionTarget_Rendering(object sender, EventArgs e)
  16. {
  17. Desenhar();
  18. }
  19. #region Propriedades
  20. public static readonly DependencyProperty AlturaElipsePropriedade = DependencyProperty.Register("AlturaElipse",
  21. typeof(double),
  22. typeof(PainelCarrossel),
  23. new PropertyMetadata(10.00));
  24. public static readonly DependencyProperty LarguraElipsePropriedade = DependencyProperty.Register("LarguraElipse",
  25. typeof(double),
  26. typeof(PainelCarrossel),
  27. new PropertyMetadata(200.00));
  28. public static readonly DependencyProperty DirecaoPropriedade = DependencyProperty.Register("Direcao", typeof(Direcao),
  29. typeof(PainelCarrossel),
  30. new PropertyMetadata(
  31. Direcao.Esquerda));
  32. public static readonly DependencyProperty ExecutarAutomaticamentePropriedade =
  33. DependencyProperty.Register("ExecutarAutomaticamente", typeof(bool), typeof(PainelCarrossel),
  34. new PropertyMetadata(true));
  35. public static readonly DependencyProperty ElementoSelecionadoPropriedade =
  36. DependencyProperty.Register("ElementoSelecionado", typeof(FrameworkElement), typeof(PainelCarrossel),
  37. new PropertyMetadata(null));
  38. public double LarguraElipse
  39. {
  40. get { return (double)GetValue(LarguraElipsePropriedade); }
  41. set { SetValue(LarguraElipsePropriedade, value); }
  42. }
  43. public double AlturaElipse
  44. {
  45. get { return (double)GetValue(AlturaElipsePropriedade); }
  46. set { SetValue(AlturaElipsePropriedade, value); }
  47. }
  48. public Direcao Direcao
  49. {
  50. get { return (Direcao)GetValue(DirecaoPropriedade); }
  51. set { SetValue(DirecaoPropriedade, value); }
  52. }
  53. public FrameworkElement ElementoSelecionado
  54. {
  55. get { return (FrameworkElement)GetValue(ElementoSelecionadoPropriedade); }
  56. set { SetValue(ElementoSelecionadoPropriedade, value); }
  57. }
  58. #endregion
  59. #region Constantes
  60. private const double ALFA_MAXIMO = 1;
  61. private const double ESCALA_MAXIMA = 1;
  62. private const double ALFA_MINIMO = 0.8;
  63. private const double ESCALA_MINIMA = 0.4;
  64. private const double VELOCIDADE = 0.1;
  65. private const double POSICAO_VISUALIZACAO = 0;
  66. #endregion
  67. #region Variáveis Internas
  68. private Dictionary<FrameworkElement, ElementoCaracteristica> listaFilhoInterno =
  69. new Dictionary<FrameworkElement, ElementoCaracteristica>();
  70. private int proximaAlturaProfundidade;
  71. private double distancia;
  72. private bool movimentou;
  73. private bool Movimentou
  74. {
  75. get { return movimentou; }
  76. set
  77. {
  78. if (value && !movimentou)
  79. CompositionTarget.Rendering += CompositionTarget_Rendering;
  80. movimentou = value;
  81. }
  82. }
  83. private List<double> listaAlfa;
  84. private List<double> listaEscala;
  85. #endregion
  86. #region Eventos
  87. public delegate void PainelCarrosselSelectedItemHandler(
  88. PainelCarrossel sender, PainelCarrosselSelectedItemEventArgs e);
  89. public event PainelCarrosselSelectedItemHandler SelectedItem;
  90. private void OnItemMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
  91. {
  92. var elemento = sender as FrameworkElement;
  93. if (elemento == null) return;
  94. ElementoCaracteristica elementoCaracteristica = listaFilhoInterno[elemento];
  95. if (elementoCaracteristica.indice == 1)
  96. {
  97. if (!Movimentou && SelectedItem != null)
  98. SelectedItem(this, new PainelCarrosselSelectedItemEventArgs((FrameworkElement)sender));
  99. }
  100. else if (elementoCaracteristica.transposicaoDestino.X > Centro.X)
  101. {
  102. int proximaPosicao = listaFilhoInterno.Count - elementoCaracteristica.indice + 1;
  103. Mover(proximaPosicao, Direcao.Direita);
  104. }
  105. else
  106. {
  107. int proximaPosicao = elementoCaracteristica.indice - 1;
  108. Mover(proximaPosicao, Direcao.Esquerda);
  109. }
  110. }
  111. #endregion
  112. private int quantidadeAtualizacao;
  113. private void Desenhar()
  114. {
  115. foreach (FrameworkElement element in listaFilhoInterno.Keys)
  116. {
  117. ElementoCaracteristica elementoCaracteristica = listaFilhoInterno[element];
  118. elementoCaracteristica.transposicaoOrigem.X = -element.ActualWidth / 2.0;
  119. elementoCaracteristica.transposicaoOrigem.Y = -element.ActualHeight / 2.0;
  120. elementoCaracteristica.transposicaoDestino.X = LarguraElipse * Math.Cos(elementoCaracteristica.tempo) + Centro.X;
  121. elementoCaracteristica.transposicaoDestino.Y = AlturaElipse * Math.Sin(elementoCaracteristica.tempo) + Centro.Y;
  122. elementoCaracteristica.tempo = elementoCaracteristica.tempo + VELOCIDADE * (elementoCaracteristica.destino - elementoCaracteristica.tempo);
  123. Canvas.SetZIndex(element, Convert.ToInt32(elementoCaracteristica.transposicaoDestino.Y));
  124. distancia = 6.283185E+000 / listaFilhoInterno.Count;
  125. if (quantidadeAtualizacao <= 1) continue;
  126. elementoCaracteristica.escalaDestino.ScaleX = elementoCaracteristica.escalaDestino.ScaleX +
  127. VELOCIDADE * (elementoCaracteristica.escala - elementoCaracteristica.escalaDestino.ScaleX);
  128. elementoCaracteristica.escalaDestino.ScaleY = elementoCaracteristica.escalaDestino.ScaleX;
  129. element.Opacity = element.Opacity + VELOCIDADE * (elementoCaracteristica.alfa - element.Opacity);
  130. }
  131. if (Movimentou) Movimentou = false;
  132. if (++quantidadeAtualizacao <= 250) return;
  133. CompositionTarget.Rendering -= CompositionTarget_Rendering;
  134. quantidadeAtualizacao = 0;
  135. }
  136. private Point Centro
  137. {
  138. get { return new Point(ActualWidth / 2, ActualHeight / 2); }
  139. }
  140. public void AdicionarFilho(FrameworkElement item)
  141. {
  142. TranslateTransform transposicaoDestino = new TranslateTransform();
  143. RotateTransform rotacaoDestino = new RotateTransform();
  144. ScaleTransform escalaDestino = new ScaleTransform();
  145. SkewTransform torcerDestino = new SkewTransform();
  146. TranslateTransform transposicaoOrigem = new TranslateTransform();
  147. item.RenderTransform = new TransformGroup
  148. {
  149. Children =
  150. new TransformCollection
  151. {
  152. rotacaoDestino,
  153. escalaDestino,
  154. torcerDestino,
  155. transposicaoDestino,
  156. transposicaoOrigem
  157. }
  158. };
  159. ElementoCaracteristica elementoCaracteristica = new ElementoCaracteristica
  160. {
  161. rotacaoDestino = rotacaoDestino,
  162. escalaDestino = escalaDestino,
  163. torcerDestino = torcerDestino,
  164. transposicaoDestino = transposicaoDestino,
  165. transposicaoOrigem = transposicaoOrigem
  166. };
  167. listaFilhoInterno.Add(item, elementoCaracteristica);
  168. item.MouseLeftButtonUp += OnItemMouseLeftButtonUp;
  169. proximaAlturaProfundidade++;
  170. Children.Add(item);
  171. CarregarFilhos();
  172. }
  173. private void CarregarFilhos()
  174. {
  175. int i = 1;
  176. InicializarEscalaTransparencia();
  177. foreach (FrameworkElement element in listaFilhoInterno.Keys)
  178. {
  179. ElementoCaracteristica elementoCaracteristica = listaFilhoInterno[element];
  180. elementoCaracteristica.destino = 6.283185E+000 * (i - 1) / listaFilhoInterno.Count + (1.570796E+000 + POSICAO_VISUALIZACAO);
  181. elementoCaracteristica.origem = elementoCaracteristica.destino;
  182. elementoCaracteristica.indice = i;
  183. elementoCaracteristica.escala = listaEscala[i - 1];
  184. elementoCaracteristica.alfa = listaAlfa[i - 1];
  185. i++;
  186. if (elementoCaracteristica.indice == 1)
  187. {
  188. ElementoSelecionado = element;
  189. }
  190. }
  191. }
  192. private void InicializarEscalaTransparencia()
  193. {
  194. listaEscala = new List<double>();
  195. listaAlfa = new List<double>();
  196. double escalaMedida = (ESCALA_MAXIMA - ESCALA_MINIMA) / (listaFilhoInterno.Count / 2.0);
  197. double alfaMedida = (ALFA_MAXIMO - ALFA_MINIMO) / (listaFilhoInterno.Count / 2.0);
  198. int indiceCentro = ((listaFilhoInterno.Count / 2.0) > Convert.ToInt32(listaFilhoInterno.Count / 2))
  199. ? Convert.ToInt32(listaFilhoInterno.Count / 2) + 1
  200. : Convert.ToInt32(listaFilhoInterno.Count / 2);
  201. for (int i = 0; i < listaFilhoInterno.Count; i++)
  202. {
  203. if (i < indiceCentro)
  204. {
  205. listaEscala.Add((ESCALA_MAXIMA - escalaMedida * i));
  206. listaAlfa.Add((ALFA_MAXIMO - alfaMedida * i));
  207. }
  208. else
  209. {
  210. listaEscala.Add((ESCALA_MINIMA + escalaMedida * (i - indiceCentro)));
  211. listaAlfa.Add((ALFA_MINIMO + alfaMedida * (i - indiceCentro)));
  212. }
  213. }
  214. }
  215. public void RemoverFilhos()
  216. {
  217. foreach (FrameworkElement element in listaFilhoInterno.Keys)
  218. {
  219. Children.Remove(element);
  220. }
  221. listaFilhoInterno = new Dictionary<FrameworkElement, ElementoCaracteristica>();
  222. }
  223. public void Mover(int posicaoItem, Direcao direcao)
  224. {
  225. Movimentou = true;
  226. foreach (FrameworkElement element in listaFilhoInterno.Keys)
  227. {
  228. ElementoCaracteristica elementoCaracteristica = listaFilhoInterno[element];
  229. if (direcao == Direcao.Direita)
  230. {
  231. elementoCaracteristica.destino = elementoCaracteristica.origem + 6.283185E+000 / listaFilhoInterno.Count + distancia * (posicaoItem - 1);
  232. elementoCaracteristica.origem = elementoCaracteristica.destino;
  233. for (int j = 1; j <= posicaoItem; ++j)
  234. {
  235. if (elementoCaracteristica.indice == listaFilhoInterno.Count)
  236. {
  237. elementoCaracteristica.indice = 1;
  238. continue;
  239. }
  240. ++elementoCaracteristica.indice;
  241. }
  242. }
  243. else
  244. {
  245. elementoCaracteristica.destino = elementoCaracteristica.origem - 6.283185E+000 / listaFilhoInterno.Count - distancia * (posicaoItem - 1);
  246. elementoCaracteristica.origem = elementoCaracteristica.destino;
  247. for (int j = 1; j <= posicaoItem; ++j)
  248. {
  249. if (elementoCaracteristica.indice == 1)
  250. {
  251. elementoCaracteristica.indice = listaFilhoInterno.Count;
  252. continue;
  253. }
  254. --elementoCaracteristica.indice;
  255. }
  256. }
  257. if (elementoCaracteristica.indice == 1)
  258. {
  259. ElementoSelecionado = element;
  260. }
  261. elementoCaracteristica.escala = listaEscala[elementoCaracteristica.indice - 1];
  262. elementoCaracteristica.alfa = listaAlfa[elementoCaracteristica.indice - 1];
  263. }
  264. Desenhar();
  265. }
  266. #region Disposição e Tamanho
  267. protected override Size ArrangeOverride(Size finalSize)
  268. {
  269. foreach (UIElement elemento in Children)
  270. {
  271. Point location = new Point();
  272. elemento.Arrange(new Rect(location, elemento.DesiredSize));
  273. }
  274. return finalSize;
  275. }
  276. protected override Size MeasureOverride(Size availableSize)
  277. {
  278. foreach (UIElement elemento in Children)
  279. {
  280. elemento.Measure(availableSize);
  281. }
  282. Clip = new RectangleGeometry { Rect = new Rect(new Point(), availableSize) };
  283. return availableSize;
  284. }
  285. #endregion
  286. #region Classes Internas - Auxiliares
  287. public class PainelCarrosselSelectedItemEventArgs : RoutedEventArgs
  288. {
  289. public readonly FrameworkElement SelectedItem;
  290. public PainelCarrosselSelectedItemEventArgs(FrameworkElement item)
  291. {
  292. SelectedItem = item;
  293. }
  294. }
  295. private class ElementoCaracteristica
  296. {
  297. internal double alfa;
  298. internal int indice;
  299. internal TranslateTransform transposicaoOrigem;
  300. internal double origem;
  301. internal double escala;
  302. internal double tempo;
  303. internal double destino;
  304. internal RotateTransform rotacaoDestino;
  305. internal ScaleTransform escalaDestino;
  306. internal SkewTransform torcerDestino;
  307. internal TranslateTransform transposicaoDestino;
  308. }
  309. #endregion
  310. }
  311. public enum Direcao
  312. {
  313. Esquerda,
  314. Direita
  315. }
  316. }