Posts Tagged ‘ Flex

Fabrication Framework 0.8.7 released!!!

Mój blog od bardzo długiego czasu pozostawał bez nowych treści. Nadszedł jednak czas, chęci i okazja ku temu by to zmienić.

Jestem jednym z Commiter-ów frameworka Fabrication wykorzystywanego do budowy aplikacji Flash/Flex. Zachęcony dynamicznym rozwojem Flex-a pod skrzydłami Apache Teamu postanowiłem wydać wersję frameworka w której będą używane tylko sparkowe komponenty Flex-a.

Oto co zmieniłem:

Fabrication www: Fabricaiton Framework

Dostęp do itemrenderer-ów w Spark DataGroup

Czwarta odsłona Flex SDK przyniosła ze sobą nowe rodzaje kontenerów ułatwiających rozmieszczanie komponentów w aplikacjach flex-owych. Jednym z nich jest DataGroup. Nie chcę tutaj opisywać możliwości kontenera tylko przedstawić sposób w jaki uzyskałem dostęp do utworzonych w moim DataGroup itemrenderer-ów.

Mój itemrenderer wyświetla imię i nazwisko na podstawie danych zawartych w obiekcie "PersonVo".

Klasa PersonVo.

public dynamic class PersonVo
{
		public var firstName:String;
		public var surname:String;

		public function PersonVo(firstName:String = null,
					surname:String = null)
		{
			this.firstName = firstName;
			this.surname =surname;
		}
}

Kod itemrenderer-a

<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
		xmlns:s="library://ns.adobe.com/flex/spark"
		xmlns:mx="library://ns.adobe.com/flex/mx"
		autoDrawBackground="true">
	<s:HGroup gap="5"
			  height="100%">
		<s:Label id="firstName"
			 text="{data.firstName}"/>
		<s:Label id="surname"
			 text="{data.surname}"/>
	</s:HGroup>
</s:ItemRenderer>

Dostęp do każdego utworzonego obiektu itemrenderera uzyskuję rejestrując metodę dla zdarzenia "rendererAdd". W jej argumencie zostaje dostarczony obiekt "event" typu "RendererExistenceEvent", który to zawiera instancję itemrenderera. Wszystkie obiekty itemrenderer-ów umieszczam w tablicy i udostępniam na zewnątrz kontenera DataGroup poprzez publiczną właściwość.

DataGroup z przechowanymi obiektami itemrenderer-ów.

<s:DataGroup xmlns:fx="http://ns.adobe.com/mxml/2009"
	        xmlns:s="library://ns.adobe.com/flex/spark"
	        xmlns:mx="library://ns.adobe.com/flex/mx"
                   itemRenderer="dgControls.DgControlRenderer"
	        rendererAdd="onRendererAdd(event)">
	<fx:Script>
		<![CDATA[
			import spark.events.RendererExistenceEvent;
			private var _itemRenderers:Array = [];

			/**
			 * Array of itemrenderers
			 * */
			public function get itemRenderers():Array
			{
				return _itemRenderers;
			}

			/**
			 * Add renderer to array
			 * */
			protected function onRendererAdd(event:RendererExistenceEvent):void
			{
				_itemRenderers.push(event.renderer);
			}
		]]>
	</fx:Script>
</s:DataGroup>

Do dataprovidera kontenera DataGroup dostaczyłem następującą tablicę oraz przeprowadziłem prostą iterację wraz ze zmianą właściwości wewnątrz itemrenderera. W zasadzie było to dość proste, ale czy to jedyne rozwiązanie? ;)

Tablica elementów "dataProvidera" w DataGroup.

var dpDataGroup:ArrayCollection = new ArrayCollection([
						new PersonVo("Piotr", "Zarzycki"),
						new PersonVo("Marian", "Zakrzewski"),
						new PersonVo("Damian", "Zarzycki")
					]);

Zmiana właściwości obiektów itemrenderer-ów.

var count:int = dg.itemRenderers.length;

for(var i:int = 0; i < count; i++)
{
					var dgRenderer:DgControlRenderer = dg.itemRenderers[i];
					dgRenderer.firstName.text = "Ola";
					dgRenderer.surname.text = "O.";
}

FlexPaginator Released! ;)

Chyba każdy programista zetknął się z problemem paginacji czy to na tworzonej przez siebie stronie internetowej, czy też(jak w moim przypadku) w aplikacji flex-owej.
W rozwiązaniach tworzonych w pracy zazwyczaj duże ilości danych prezentowałem za pomocą kontrolki DataGrid w połączeniu z paginatorem udostępnionym pod adresem – link. Jednak wciąż rosnąca ich ilość szybko sprawiła, że wygrzebana w czeluściach internetu kontrolka przestała spełniać oczekiwania. Postanowiłem zmierzyć się z paginacją i stworzyć samodzielnie komponent, który znacznie ułatwił by, a w szczególności przyśpieszył poruszanie się po tysiącach stron udostępnianych danych. Właściwie żeby być szczerym do rozpoczęcia pracy nad kontrolką zachęcił mnie Redliquid, a jej obecny wygląd-funkcjonalność jest w 100% jego pomysłem. :) Zaprezentowany flex-paginator jest zbudowany jeszcze na bazie kontrolek udostępnianych we Flex-ie 3 – planuję jednak jego dalszy rozwój, a więc poprawę wszelkich znalezionych błędów ;), a przy odrobinie większej ilości wolnego czasu przepisanie całości z wykorzystaniem dobrodziejstw Flex-a 4.

Diabeł tkwi w szczegółach, a więc poniżej prezentuję opis kilku najważniejszych opcji FlexPaginator-a.

Do pliku swc paginatora niezbędne jest dołączenie pliku css o nazwie StyleButtons.css, który odpowiada za wygląd wszystkich przycisków. Najważniejsze właściwości paginatora, które powinny zostać ustawione
w kodzie ActionScript lub po stronie mxml-a to:

  • totaItems – ilość wszystkich elementów
  • itemsPerPage – ilość elementów wyświetlanych na stronie
  • pageToDisplay – ilość wyświetlonych przycisków z numerami stron – ustawienie parzystej liczby wyświetlanych stron, skutkuję zamianę jej na nieparzystą ich ilość (takie „zachowanie” wynika z działania paginatora)

Opcjonalna jest natomiast właściwość:

  • selectedPage – numer zaznaczonej strony, po utworzeniu kontrolki domyślnie zostaje zanaczona środkowa strona/przycisk spośród aktualnie wyświetlonych.

Moja kontrolka paginacji zawiera przyciski umożliwiające odpowiednio:

  • skok o jedną stronę do przodu lub do tyłu
  • skok o wybraną ilość stron – wartości w wyświetlonym menu są wygenerowane automatycznie, ta para przycisków pojawia się tylko w przypadku gdy całkowita ilość stron przekracza 50.
  • skok na koniec i początek.

Dodatkowo obsługa zdarzenia „selectedPageChanged” daje możliwość odczytu aktualnie zaznaczonej strony. Wygenerowany paginator wyświetla nieparzystą liczbę stron,
a aktualnie zanaczony numer strony jest podkreślony

Przykładowy kod z zaznaczoną stroną nr 3 oraz plik css odpowiadający za poniższy wygląd paginatora pod linkiem

Wszelkiego rodzaju błędy, sugestię co mogę poprawić lub co zrobiłem tragicznie proszę zgłaszać na code-google (gdzie udostępnie kod projektu oraz plik swc – zakładka Download) lub w komentarzach pod tym czy też kolejnymi wpisami dotyczącymi FlexPaginator-a. ;)

DataGrid z pogrubioną zawartością wierszy

Podczas pracy nad pewną funkcjonalnością musiałem pogrubić zawartość wybranych wierszy w datagrid-zie. „Decyzja” o pogrubieniu zawartości danego wiersza miała być zawarta w każdym pojedyńczym obiekcie dostarczonym do datagrid-a w postaci tablicy (Array). Wewnątrz takiego obiektu zawarta zostanie właściwość „mówiąca” o pogrubieniu.

Przykładowa klasa zawierająca informację każdego wiersza w datagrid-zie mogła by wyglądać następnująco (właściwość „isSpecial” decyduję o pogrubieniu):

public dynamic class PersonVo
{
		public var name:String;
		public var surname:String;
		public var email:String;

  /**
		 * If this property is true, row in DataGrid is bold
		 *
		 * @var Boolean
		 * */
		public var isSpecial:Boolean;

		private var _date:Date;

		/**
		 * Get formatted date
		 *
		 * @retrun String
		 * */
		public function get dateStr():String
		{
			var dateFormatter:DateFormatter = new DateFormatter();
			dateFormatter.formatString = "DD-MM-YYYY";

			return dateFormatter.format(_date);
		}

		public function set dateStr(value:String):void
		{
			_date = DateFormatter.parseDateString(value);
		}

		public function PersonVo(name:String = null, surname:String = null,
					date:Date = null, email:String = null, isSpecial:Boolean = false)
		{
			this.name = name;
			this.surname = surname;
			this._date = date;
			this.email = email;
			this.isSpecial = isSpecial;
		}
}

Następnie należy utworzyć DataGrid-a wraz z kolumnami wyświetlającymi informację, którymi jesteśmy zainteresowani oraz itemrenderer w którym obsłużone zostanie pogrubienie poszczególnych wierszy. Kod mojego przykładowego datagrid-a zawiera kolumnę „Imię i nazwisko” łączącą dwie właściwości z klasy PersonVo za pomocą funkcji anonimowej, email oraz sformatowaną datę urodzenia.

<?xml version="1.0" encoding="utf-8"?>
<mx:DataGrid xmlns:fx="http://ns.adobe.com/mxml/2009"
				 xmlns:s="library://ns.adobe.com/flex/spark"
				 xmlns:mx="library://ns.adobe.com/flex/mx"
				 itemRenderer="{new ClassFactory(DGItemRenderer)}">
	<mx:columns>
		<!--This simple anonymous function in DataGridColumn concatenates two string: name and surname from value object-->
		<mx:DataGridColumn headerText="Imię i Nazwisko"
		labelFunction="{function(personVo:PersonVo,
									dgColumn:DataGridColumn):String
						{return personVo.name + ' ' + personVo.surname; }}"
						   width="200"/>
		<mx:DataGridColumn headerText="Email"
						   dataField="email"
						   width="250"/>
		<mx:DataGridColumn headerText="Data urodzenia"
						   dataField="dateStr"
						   width="120"/>
	</mx:columns>
	<fx:Script>
		<![CDATA[
			import dataGridItermRenderers.DGItemRenderer;
			import vo.PersonVo;
		]]>
	</fx:Script>
</mx:DataGrid>

Najważniejsza część całej zabawy-jest klasa itemrenderera zawierająca przesłoniętą właściwość „data”. W jej wnętrzu sprawdzany jest typ dostarczonej wartości ponieważ podczas tworzenia DataGrida przekazywane są do niej obiekty poszczególnych kolumn, którymi nie byłem zainteresowany. W dalszej kolejności właściwość wykonuję się przy wypełnieniu każdej komórki poszczególnych kolumn co jak widać daję możliwość sterowania wyglądem ich zawartości poprzez ręczne ustawienie styli.

public class DGItemRenderer extends DataGridItemRenderer
{
		public function DGItemRenderer()
		{
			super();
		}

		/**
		 * Property is execute on each column in each row
		 *
		 * @param PersonVo|Object value Object using in item renderer
		 */
		override public function set data(value:Object):void
		{
			if (value is PersonVo && value)
			{
				//In this property i check if PersonVo is special
				//When isSpecial == true i bold cell in this column
				var boldValue:String = (PersonVo)(value).isSpecial == true ? "bold" : "normal";
				setStyle("fontWeight", boldValue);
			}
			super.data = value;
		}
}

Wynikiem tych zabiegów są oczekiwane pogrubione zawartości wierszy w DataGridzie. link