poniedziałek, 24 września 2007

"Pożegnanie" z technologią Adobe Flex.

Ostatni weekend przesiedziałem nad swoją nową komórką. Ma ona system operacyjny Symbian 9.1 (Series 60 3 edycja). Zastanawiam się nad tym co można zrobić z taką komórka. Oczywiście, że należałoby ją dobrze poznać. I rozwijać się razem z rozwojem technologii.
Czy przeciętny informatyk zechce od razu poznawać tajniki programowania C++ pod Symbianem? Nie za bardzo. Coraz więcej z nich jest przyzwyczajonych do programowania w PHP czy JavaScript. Ostatnio duża popularność zaczynają zyskiwać takie języki programowania jak Python czy Ruby.

Myślę, że warto rozwijać się. Więc skoro na razie "wypalam" się z programowania w ActionScript 3 i Flex 2. Informacji przybywa coraz więcej (na początku miałem ok 50 RSS o Flex 2 a teraz chyba ponad 500). Potrzebuję czegoś nowego i niszowego. Tak jak było kiedyś z moim blogiem o Blink 3D. To teraz uważam, że zmienię kierunek na Pythona i FlashLite. A dokładniej zamierzam pisać na tym blogu o PyS60. Może kiedyś powstanie AIR Mobile, wtedy łatwiej będzie tworzyć aplikacje mobilne. Symbian + Python + AIR Mobile to jest to w którym kierunku chcę dalej się rozwijać.

Gdybym miał możliwość pisania książki o tym to prawdopodobnie miałaby taki spis treści.

  • Symbian - system operacyjny XXI wieku
    • Historia
    • Stan obecny
    • Nowe możliwości w poszczególnych wersjach
    • Programowanie pod Symbianem
      • C++
      • PhoneME (kiedyś J2ME)
      • Python
      • Open C
      • Ruby
    • Możliwości telefonów komórkowych
      • Producenci
      • Rynek
  • Python - język programowania dla każdego
    • Historia
    • Ewolucja
    • Podstawowe informacje o programowaniu w Pythonie
  • Pierwsze kroki
    • Przygotowywanie środowiska pracy
      • Instalacja SDK Series 60
      • Instalacja dodatku PyS60 do emulatora w SDK
      • Instalacja edytora PyDev
      • Instalacja PyS60 w komórce
      • Konfiguracja środowiska pracy z komórką
    • Praca z interpretatorem w komórce
    • Piszemy pierwszy programik "witaj świecie"
      • Problem z polskimi znakami - używanie unikodu
  • Kurs Pythona na przykładzie PyS60
    • Liczby
    • Zmienne
    • Typy danych
    • Instrukcje
    • Funkcje
    • Klasy i obiekty
    • Moduły i pakiety
  • Wprowadzenie do Symbiana
    • Budowa systemu Symbian
    • Modularyzacja Symbiana
    • GUI w Symbianie
    • Bezpieczeństwo w Symbianie
      • Podpisywanie aplikacji
    • Tworzenie pakietów instalacyjnych
  • Programowanie Symbiana z PyS60
    • szkielet aplikacji
    • interfejs graficzny Symbiana
      • interakcja z użytkownikiem
      • wprowadzanie tekstu
      • menu
      • okna dialogowe
      • listy wyboru
      • zakładki
    • obsługa klawiatury
      • używanie klawiatury
    • rysowanie
      • API do rysowania
      • obsługa grafiki
    • obsługa plików
    • komunikacja sieciowa
      • ładowanie plików
      • wysyłanie plików
      • komunikacja przez gniazda
    • Bluetooth
      • komunikacja z PC
    • Obsługa komunikacji
      • SMSy
      • MMSy
      • email
    • Obsługa danych
      • bazy danych
      • kontakty
      • kalendarz
    • Programowanie dźwięku
      • nagrywanie
      • odtwarzanie rożnych formatów
      • komponowanie muzyki
    • Obsługa kamery
      • tworzenie filmów
    • Grafika 3D
      • 3D Graphics OpenGL ES
      • modele 3D
  • Współpraca Pythona z FlashLite
    • FlashLite - historia
    • FlashLite - instalacja
    • Pierwsza aplikacja w FlashLite
    • Instalacja frameworka Flyer
    • Flyer od środka
    • Omówienie przykładów zawartych w pakiecie Flyer
    • Rozszerzanie Flyera
      • Gry
      • Aplikacje typu chat
  • Mobile Web Server
    • Tworzenie aplikacji internetowych opierających się na MWS
  • Tworzenie rozszerzeń do PyS60 w C++
  • Przyszłość - AIR Mobile.
Jak widać książka może być dość duża. Chciałbym, żeby była dość przystępna dla każdego, co oznacza że trzeba pisać instrukcje krok po kroku. Zastanawiam się czy nie przyjąć konwencji dialogu pomiędzy uczniem a mentorem. Jak wiadomo dialogi szybciej sie czytają. A nauka programowania szybciej idzie w zespole niż w pojedynkę.

sobota, 15 września 2007

Programowanie pod Symbianem w Pythonie.

Coraz bardziej zaczynam się interesować możliwościami jakie daje programowanie pod Symbianem. Powód: coraz więcej usług internetowych powstaje z myślą o użytkownikach komórek. Co to oznacza? Tworzenie serwisów internetowych i zawartości dodanej pod kątem użytkowników komórek.

Istnieją spore możliwości biznesowe i jak korzyści dla programistów wchodzących w ten rynek.
Można zauważyć, że jest sporo pośredników którzy chcą dostarczać zawartość do komórek. W Polsce takim pośrednikiem znanym z reklamy prasowej jest Wapster. A na świecie Handango.

Większość tam zawartości to masowe oprogramowanie, gry, zawartość graficzna i jak multimedialna. Ale prawdziwy interes tkwi w tworzeniu oprogramowania wspomagającego użytkowników komórek w korzystaniu z serwisów i usług internetowych Web 2.0 ( a także w usprawnianiu procesów biznesowych).

Przykłady? Google pozwala na pisanie bloga z poziomu urządzeń mobilnych, przeglądać Gmail czy przeglądać RSS przez Google Readera. Yahoo pozwala na korzystanie z ich serwisu internetowego użytkownikom urządzeń mobilnych. W Polsce dopiero w świadomości webmasterów i jak ich klientów zaczyna się pojawiać potrzeba tworzenia zawartości serwisów internetowych skierowanych do użytkowników urządzeń mobilnych. Więcej informacji można o tym można przejrzeć na blogu Tomasza Wieczorka i na blogu Mariana Witkowskiego.

Z perspektywy czasu można by powiedzieć że możliwości jakie daje internet w komórkach dopiero zaczyna być zauważany przez użytkowników komórek. Dla większości z nich komórka to urządzenie do wysyłania SMS-ów, a także rozmów głosowych. Funkcjonalności komórek zaczynają kreować nowe potrzeby wśród użytkowników. Aparat fotograficzny, odtwarzacz multimedialny czy bluetooth, a także obsługa internetu sprawiają, że ludzie zaczynają obeznajmiać sie z tymi funkcjonalnościami. Więcej informacji o funkcjonalnościach komórek można przeczytać na blogu Karoliny Lis

Podobnie rzecz sie ma z rozwojem oprogramowania dla tworzenia programów pod komórki. Można powiedzieć że standardowym systemem operacyjnym dla komórek staje się Symbian.
Najbardziej znanym językiem programowania pod komórki jest Java a szczególnie to co jest w J2ME. Adobe od pewnego czasu masowo rozwija FlashLite. - wersję Flash Playera dla użytkowników komórek. Natomiast Nokia zauważyła, że programowanie w Javie czy w C++ dla Symbiana jest zbyt trudne dla większości ludzi, którzy zechcieliby programować we własnym zakresie, więc wprowadziła interpreter Pythona dla Symbiana. W przyszłości być może programiści .NET będą programować pod Symbiana dzięki obsłudze CompactFramework.NET poprzez silnik wykonawczy jaki dostarczy im firma z RPA Red Five Labs . Tak więc pod Symbianem mamy spory zestaw języków programowania. Od "niskopoziomowego" programowania w C++ poprzez masowe tworzenie oprogramowania na komórki w Javie, skończywszy na niszowych zastosowaniach ActionScriptu w FlashLite. oraz w pisaniu skryptów w Pythonie.

Uważam, że dla kogoś kto chce szybko zobaczyć jak się programuje pod Symbianem, a także do tworzenia własnych skryptów polecam Pythona. Programowanie w Pythonie nie jest trudne. Można na początek przejrzeć wątek (po polsku) o programowaniu w Pythonie w Symbianie. Potem można spokojnie przerobić materiał "Python for Series 60" Jurgena Scheible. Kolejnym krokiem jest zapoznanie sie z zbiorem informacji dla programistów Pythona na Nokii, a także na Forum Nokii. bądź poczytać forum dyskusyjne dla programistów Pythona. Myślę, że Ci którzy zaczną poznawać Pythona pewnie znajdą czas na wykorzystanie Frameworka Flyer (kod źródłowy i przykłady).

niedziela, 9 września 2007

Ewolucja Flash Playera

Ted Patrick zapowiedział że na Adobe MAX 2007 30 września w Chicago zostanie zaprezentowana kolejna wersja Flash Playera 10 o nazwie kodowej "Astro".

Trzeba jeszcze zwrócić uwagę na to, że w Adobe jeszcze rozwijają Adobe Integrated Runtime, oraz Adobe Media Player (odtwarzacz multimedialny bazujący na AIR). A w tym w cieniu pozostaje Adobe Shockwave Player - odtwarzacz multimedialny plików *.dxr tworzonych przy pomocy Adobe Directora. Natomiast rozwój wtyczek takich jak Adobe SVG Viewer czy Adobe Atmosphere oraz Adobe Authorware Player, Macromedia Central został zakończony. Pozostaje jeszcze to co umożliwia instalowanie oprogramowania za pomocą Flash Playera. Z tego mechanizmu korzystaja m.in. Adobe Digital Editions. Można by powiedzieć, że teoretycznie można już tworzyć zawartość XHTML dla przyszlej wersji Flash Playera. Jeśli założymy, że Adobe Digital Editions jest wtyczką bazującą na Flash Player to mozna stwierdzić ze jest to kierunek rozwoju dla Flash Playera - tworzenie wtyczek i programów bazujacych na Flash Playerze.

21 sierpnia Adobe ogłosiło wprowadzenie do testów Flash Playera 9 Update 3 Beta 2 o nazwie kodowej "Moviestar" (build 9.0.60.184 dla Windows).



A tak całkiem niedawno już wprowadzono Flash Player Update 3 Beta 1 o nazwie kodowej "Frogstar" (build 9.0.60.120 dla Windows).

Warto czasami rozejrzeć się za oficjalną listą Flash Playerów 9
Polecam listę Flash Playerów Active X

Flash Player 9.0.47.0 (IE)
Flash Player 9.0.60.120 Beta (IE)
Flash Player 9.0.45.0 (IE)
Flash Player 9.0.28.0 (IE)
Flash Player 9.0.21.75 Beta (IE)
Flash Player 9.0.16.0 (IE)
Flash Player 9.0.7.0 Beta (IE)
Flash Player 9.0.2.0 Beta (IE)
Flash Player 9.0.0.296 Beta (IE)
Flash Player 8.0.24 (IE)
Flash Player 8.0.22 (IE)
Flash Player 8.0.15 Beta (IE)
Flash Player 7.0.19 (IE)


A takźe liste wtyczek pod Operę, Firefoxa

Flash Player 9.0.47.0 (Non-IE)
Flash Player 9.0.45.0 (Non-IE)
Flash Player 9.0.28.0 (Non-IE)
Flash Player 9.0.21.75 Beta (Non-IE)
Flash Player 9.0.16.0 (Non-IE)
Flash Player 9.0.7.0 Beta (Non-IE)
Flash Player 9.0.2.0 Beta (Non-IE)
Flash Player 9.0.0.296 Beta (Non-IE)
Flash Player 8.0.24 (Non-IE)
Flash Player 8.0.22 (Non-IE)
Flash Player 8.0.15 Beta (Non-IE)
Flash Player 7.0.19 (Non-IE)

A takze wtyczki/ActiveX Adobe Shockwave Player pod Windows

Shockwave Player 10.2.0.022
Shockwave Player 10.2.0.021
Shockwave Player 10.1.4.020
Shockwave Player 10.1.3.018
Shockwave Player 10.1.0.11


A tak na marginesie dlaczego Director nie przyjął się (pomijając kwestie ceny za soft) ? Ostatnio prawie nikt nie pisze o tym programie. Czy jak Adobe dostarczy darmowy kompilator dla plików dxr to wróci jego popularność?

sobota, 1 września 2007

Cairngorm 2.2 - czytnik RSS

Framework aplikacyjny pozwala na tworzenie aplikacji, koncentruje się także na interfejsie użytkownika. Natomiast frameworki architektoniczne służą do opisywania i organizowania struktury powstającej aplikacji. Są wewnętrzna częścią aplikacji. Często bazują na wzorcach projektowych. Różnicą w projektowaniu aplikacji internetowych opartych na architekturze klient-serwer a aplikacjami internetowymi z bogatym interfejsem użytkownika jest to, że te pierwsze wymuszają obsługę stanów aplikacji i jak zarówno interakcję użytkownika na serwerze, natomiast te drugie aplikacje ograniczają się do obsługi danych z serwera ale cała interakcja użytkownika spoczywa na kliencie.

Wzorzec ValueObject – obiekty danych
Trzeba zaprojektować klasę, której obiekt będzie przechowywał dane. Co oznacza, że dane będą miały reprezentację obiektową. Dane zostaną dostarczone z zewnątrz. Takie dostarczone dane muszą załadowane do obiektu. Dzięki takiemu podejściu unika się operowania bezpośrednio na strukturze danych. Dane mogą być dostarczone w równy sposób i przyjmować różną strukturę na przykład dokumentu XML czy zestawu danych binarnych. Drugą zaletą stosowania obiektów do przechowywania danych jest lepsza kontrola typów danych w aplikacji. W Cairngormie tworzenie obiektów danych wymaga implementacji interfejsu IValueObject:


package info.malaj.readerrss.vo
{
import com.adobe.cairngorm.vo.IValueObject;
[Bindable]
public var title:String;
public var link:String;
public var description:String;

public class ItemVO implements IValueObject
{ }
}

Klasa ItemVO posiada zbiór składowych dzięki któremu obiekty mogą opisywać wpis z bloga. Gdy dane zostaną pobrane z tej klasy tworzy się obiekty klasy ItemVO. Następnie te obiekty zostają zarejestrowane w modelu aplikacji. To pozwala na dostęp do tych obiektów z danymi z dowolnego miejsca aplikacji.

Wzorzec ModelLocator
Model jest singletonem to oznacza, że może być tylko jeden obiekt tego typu w aplikacji. Model przechowuje informacje o obiektach danych. Jest jakby centrum zarządzania danym

package info.malaj.readerrss.model
{
import com.adobe.cairngorm.model.IModelLocator;
import com.adobe.cairngorm.CairngormError;
import com.adobe.cairngorm.CairngormMessageCodes;
import info.malaj.readerrss.vo.ItemVO;
import mx.collections.ArrayCollection;

[Bindable]
public class Model implements IModelLocator
{
private static var instance:Model;
public var feedVOList:ArrayCollection;
public var itemVO:ItemVO;
public var feedURI:String;
public var feedTitle:String = "Czytnik RSS";
public var feedTitleLink:String;
public var syndicate:String;

public function Model(access:Private)
{
if (access != null)
{
if (instance == null)
{
instance = this;
}
}
else
{
throw new CairngormError(CairngormMessageCodes.SINGLETON_EXCEPTION, "Model" );
}
}

public static function getInstance():Model
{
if (instance == null)
{
instance = new Model( new Private );
}
return instance;
}
}
}
internal class Private {}

Z tego kodu można się nauczyć obsługi kilku rzeczy. Jak tworzy się singletona, wywoływanie wyjątków Cairngorm. Rejestrujemy w nim obiekt danych typu ItemVO i jak listę wpisów z bloga jako typ ArrayCollection .Pozostałe dane służą widokom i poleceniom To oznacza że widok korzysta z danych zarejestrowanych przez Model. A polecenia mogą zmieniać dane zarejestrowane w tym Modelu. Zmiana danych w obiekcie danych typu ItemVO przez polecanie zostanie automatycznie przekazana do obiektu widoku typu DetailView.

Service Locator – delegacje usług sieciowych.
ServiceLocator to miejsce w którym są wywoływane różnego rodzaju połączenia z zewnętrznym światem za pomocą żądań HTTP czy usług sieciowych WebService bądź Flash Remoting. ServiceLocator jest centralnym miejscem gdzie trzeba wstawiać informacje dotyczące obsługi połączeń. Ponieważ opiera sie to komponentach RPC więc programista nie musi znać szczegółów implementacji wywołań. ServiceLocator jest singletonem więc można rozszerzyć tą klasę Services w kodzie MXML

<?xml version="1.0" encoding="utf-8"?>
<cairngorm:ServiceLocator xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:cairngorm="com.adobe.cairngorm.business.*">
<mx:Script>
<![CDATA[
import info.malaj.readerrss.model.Model;

public static const SERVICE:String = "service";
[Bindable]
public var model:Model = Model.getInstance();
]]>
</mx:Script>
<mx:HTTPService id="rss" url="{model.feedURI}" />
</cairngorm:ServiceLocator>


Delegaty są to metody, które odpowiadają za wykonanie pobrania danych i ewentualnie wywoływania zdalnych metod usług przez żądań internetowych do serwisów w celu pobrania tych danych. W tej aplikacji żądanie polega na pobraniu wpisów z bloga z kanałów RSS. Metody delegata są wywoływane przez odpowiedni obiekt polecenia.
Kod klasy GetFeedDelegate.as:

package info.malaj.readerrss.business
{
import mx.rpc.IResponder;
import mx.rpc.http.HTTPService;
import com.adobe.cairngorm.business.ServiceLocator;
import mx.rpc.AsyncToken;
import mx.rpc.events.ResultEvent;

public class GetFeedDelegate implements IResponder
{
private var responder:IResponder;
private var service:HTTPService;
private var token:AsyncToken;

public function GetFeedDelegate(responder:IResponder):void
{
this.responder = responder;
this.service = ServiceLocator.getInstance().getHTTPService("rss");
}

public function getFeed() : void
{
this.token = this.service.send();
this.token.addResponder(this);
}

public function result(data:Object):void
{
this.responder.result(data);
}

public function fault(info:Object):void
{
this.responder.fault(info);
}
}
}

Zdarzenia

Klasy zdarzeń rozszerzają klasę bazowa CairngormEvent. Ta klasa bazowa pozwala na tworzenie specyficznych zdarzeń dla aplikacji. W naszej aplikacji mamy 3 zdarzenia i odpowiadające im klasy ShowPageEvent, SelectItemEvent, GetFeedEvent. Każda z tych klas musi być zarejestrowana w kontrolerze. Kiedy obiekt zdarzenia jest wyzwalany to składowe są przekazywane do konstruktora. Zdarzenie jest przekazywane z widoku za pomocą metody dispatch. Kod klasy GetFeedEvent.

package info.malaj.readerrss.events
{
import com.adobe.cairngorm.control.CairngormEvent;
import info.malaj.readerrss.control.ApplicationController;
public class GetFeedEvent extends CairngormEvent
{
public var selecteduri : String;

public function GetFeedEvent(type:String)
{
super(ApplicationController.GET_FEED);
this.selecteduri = type;
}
}
}

Kod klasy SelectItemEven

package info.malaj.readerrss.events
{
import com.adobe.cairngorm.control.CairngormEvent;
import info.malaj.readerrss.control.ApplicationController;

public class SelectItemEvent extends CairngormEvent
{
public var selectedItem : Object;

public function SelectItemEvent(selectedItem:Object)
{
super(ApplicationController.SELECT_ITEM);
this.selectedItem = selectedItem;
}
}
}

Kod klasy ShowPageEvent

package info.malaj.readerrss.events
{
import com.adobe.cairngorm.control.CairngormEvent;
import info.malaj.readerrss.control.ApplicationController;

public class ShowPageEvent extends CairngormEvent
{
public var link:String;

public function ShowPageEvent()
{
super(ApplicationController.SHOW_PAGE);
this.link = link;
}
}
}

Wzorzec Command - polecenia
W tej aplikacji są tylko 3 interakcje – pobranie RSS, wyświetlenie listy wpisów i wyświetlenie wpisu. Trzeba napisać klasy do obsługi tych interakcji. Każda funkcjonalność wymaga napisania klasy bazującej na klasie Command. Z funkcjonalnościami powiązane są zdarzenia. Każdy obiekt typu Command ma metodę execute(). Użytkownik poprzez swoją interakcję może wywołać zdarzenie, a ono wykona tą metodę. Każda wywołana metoda execute() w obiekcie typu Command wymaga podania jako argumentu zdarzenia typu CairngormEvent, którego można rzutować na typ własnego zdarzenia. Każdy typ zdarzenia ma odpowiednik w typie klas Command. Metody result i jak fault są wymagane przez interfejs IResponder te metody służą do obsługi asynchronicznego przekazywania wyników z serwera. Metoda result zadziała w przypadku gdy wywołanie się uda a fault w przypadku gdy się nie uda. W tej aplikacji jest klasa GetFeedCommand odpowiedzialną za pobranie RSS. Klasa ta korzysta z delegacji, która obsługuje sam proces pobierania danych RSS, natomiast sama zajmuje się wypełnianiem danych obiektu Model

package info.malaj.readerrss.commands
{
import com.adobe.cairngorm.control.CairngormEvent;
import mx.rpc.IResponder;
import com.adobe.cairngorm.commands.ICommand;
import info.malaj.readerrss.business.GetFeedDelegate;
import info.malaj.readerrss.model.Model;
import info.malaj.readerrss.events.GetFeedEvent;
import mx.collections.ArrayCollection;
import mx.utils.StringUtil;
import mx.controls.Alert;

public class GetFeedCommand implements ICommand, IResponder
{
private var delegate:GetFeedDelegate;
private var model:Model;
private var feedEvent:GetFeedEvent;
private var feedFactory:FeedFactory;

public function GetFeedCommand()
{
this.delegate = new GetFeedDelegate(this);
this.model = Model.getInstance();
}

public function execute(event:CairngormEvent):void
{
this.feedEvent = GetFeedEvent(event);
this.model.feedURI = this.feedEvent.selecteduri;
this.delegate.getFeed();
}

public function result(data:Object):void
{
if(data.result.rss)
{
this.model.syndicate = "RSS";
this.model.feedVOList = data.result.rss.channel.item as ArrayCollection;
this.model.feedTitle = StringUtil.trim(data.result.rss.channel.title);
this.model.feedTitleLink = StringUtil.trim(data.result.rss.channel.link);
}
if(data.result.feed)
{
this.model.syndicate = "Atom";
this.model.feedVOList = data.result.feed.entry as ArrayCollection;
this.model.feedTitle = StringUtil.trim(data.result.feed.title);
this.model.feedTitleLink = StringUtil.trim(data.result.feed.link[0].href);
}
}

public function fault(info:Object):void
{
Alert.show("wystąpił bład " + info.message);
}
}
}

Podobnie rzecz się ma z klasą SelectItemCommand odpowiedzialną za pobranie informacji o wpisie

package info.malaj.readerrss.commands
{
import com.adobe.cairngorm.control.CairngormEvent;
import mx.rpc.IResponder;
import com.adobe.cairngorm.commands.ICommand;
import info.malaj.readerrss.model.Model;
import info.malaj.readerrss.vo.ItemVO;
import info.malaj.readerrss.events.SelectItemEvent;

public class SelectItemCommand implements ICommand, IResponder
{
private var model:Model;
private var newItemVO:ItemVO;
private var feed:SelectItemEvent;

public function SelectItemCommand():void
{
this.model = Model.getInstance();
}

public function execute(event:CairngormEvent):void
{
this.newItemVO = new ItemVO;
this.feed = SelectItemEvent(event);
this.newItemVO.title = this.feed.selectedItem.title;
if(this.model.syndicate=="RSS")
{
this.newItemVO.description = this.feed.selectedItem.description;
}
if(this.model.syndicate=="Atom")
{
this.newItemVO.description = this.feed.selectedItem.content;
}

if(this.model.syndicate=="RSS")
{
this.newItemVO.link = this.feed.selectedItem.link;
}
if(this.model.syndicate=="Atom")
{
this.newItemVO.link = this.feed.selectedItem.link[0].href;
}

this.model.itemVO = this.newItemVO;
}

public function result(data:Object):void
{}

public function fault(info:Object):void
{}
}
}

Kod klasy ShowPageCommand odpowiedzialnej za otwarcie strony internetowej ze wpisem.

package info.malaj.readerrss.commands
{
import com.adobe.cairngorm.control.CairngormEvent;
import com.adobe.cairngorm.commands.ICommand;
import info.malaj.readerrss.model.Model;
import info.malaj.readerrss.events.ShowPageEvent;
import flash.net.URLRequest;
import flash.net.navigateToURL;

public class ShowPageCommand implements ICommand
{
private var model:Model;
private var showPageEvent:ShowPageEvent;
private var link:String = "http://flex2.blogspot.com";

public function ShowPageCommand()
{
this.model = Model.getInstance();
}

public function execute(event:CairngormEvent):void
{
this.showPageEvent = ShowPageEvent(event);
try
{
var v:URLRequest = new URLRequest(this.model.itemVO.link);
navigateToURL(v,"_blank");
}
catch(err:Error)
{
var u:URLRequest = new URLRequest(this.link);
navigateToURL(u,"_blank");
}
}
}
}

Wzorzec Controller – kontrolera
Kontroler jest miejscem gdzie obiekty poleceń są powiązane z odpowiadającymi im zdarzeniami. Gdy zdarzenie jest wywołane to kontroler przekonuje je odpowiedniemu obiektowi polecenia.

package info.malaj.readerrss.control
{
import com.adobe.cairngorm.control.FrontController;
import info.malaj.readerrss.commands.GetFeedCommand;
import info.malaj.readerrss.commands.SelectItemCommand;
import info.malaj.readerrss.commands.ShowPageCommand;
public class ApplicationController extends FrontController
{
public static const GET_FEED : String = "getFeed";
public static const SELECT_ITEM : String = "selectItem";
public static const SHOW_PAGE : String = "showPage";

public function ApplicationController()
{
this.addCommand(ApplicationController.GET_FEED, GetFeedCommand);
this.addCommand(ApplicationController.SELECT_ITEM, SelectItemCommand);
this.addCommand(ApplicationController.SHOW_PAGE, ShowPageCommand);
}
}
}

Po pierwsze wszystkie zdarzenia murzą być zarejestrowane jako stałe w obiekcie kontrolera, pozwala to na uniknięcie problemów podczas kompilacji. W konstruktorze kontrolera dodaje sie klasy poleceń do powiązanych z nimi zdarzeń. Taka klasa może być bardzo duża w przypadku jak doda się wiele poleceń i zarejestruje sie wiele zdarzeń. Metoda addCommand () wymaga podania jako argumentu nazwy zdarzenia i nazwy klasy polecenia. Jak można zauważyć klasa ApplicationController rozszerza klasę FrontController. Poprzez rozszerzenie ma się dostęp do wszystkich dodanych poleceń i powiązanych z nimi zarejestrowanymi zdarzeniami. Obiekt kontrolera tworzy sie w głównym pliku aplikacji. To oznacza że aplikacja ma FrontController który odpowiada na zdarzenia i wywołuje wszystkie polecania które są powiązane z tymi zdarzeniami.

Wzorzec View - widoku
Widok jest częścią aplikacji, która odpowiada za interfejs użytkownika i jak jego interakcję. Dzięki wbudowanej w Flex obsłudze wiązania danych. obiekt Model aktualizuje dane w obiektach widoku. Użycie wiązania danych wymaga wskazania źródła i celu dla danych . Źródłem jest obiekt danych a celem jest obiekt widoku który potrzebuje tych danych.

Główny plik aplikacji RSS.mxml zawiera informacje o widokach, kontrolerze i jak o usłudze sieciowej wymaganej przez delegata w celu pobrania danych.


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
xmlns:view="info.malaj.readerrss.views.*"
xmlns:business="info.malaj.readerrss.business.*"
xmlns:control="info.malaj.readerrss.control.*">
<business:Services id="rss" />
<control:ApplicationController id="control" />
<view:MainPanelView id="mainPanel" width="800" height="500" layout="vertical" horizontalAlign="center">
<view:URIView id="uriTextinput" paddingTop="10"/>
<view:ListView id="listDatagrid" width="750"/>
<view:DetailView id="detailTextarea" width="750" height="100%"/>
</view:MainPanelView>
</mx:Application>
Kod MainPanelView.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" title="{model.feedTitle}">
<mx:Script>
<![CDATA[
import info.malaj.readerrss.model.Model;
[Bindable]
private var model:Model = Model.getInstance();
]]>
</mx:Script>
</mx:Panel>

Kod ListView.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:DataGrid xmlns:mx="http://www.adobe.com/2006/mxml"
dataProvider="{model.feedVOList}"
itemClick="handleItemClick(event.currentTarget.selectedItem)"
fontSize="12"
>
<mx:Script>
<![CDATA[
import info.malaj.readerrss.model.Model;
import info.malaj.readerrss.events.SelectItemEvent;

[Bindable]
private var model:Model = Model.getInstance();
private var event:SelectItemEvent;
private function handleItemClick(feed:Object):void{
event = new SelectItemEvent(feed);
event.dispatch();
}
]]>
</mx:Script>
<mx:columns>
<mx:DataGridColumn headerText="Tytuł wpisu na blogu" dataField="title" width="450" />
</mx:columns>
</mx:DataGrid>
Kod URIView.mxm
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="handleCreationComplete()">
<mx:Script>
<![CDATA[
import info.malaj.readerrss.events.GetFeedEvent;
import info.malaj.readerrss.model.Model;

[Bindable]
private var model:Model = Model.getInstance();
private var event:GetFeedEvent;
private function geturi(selecteduri:String):void{
event = new GetFeedEvent(selecteduri);
event.dispatch();
}

private function handleCreationComplete():void{
model.feedURI = "http://flex2.blogspot.com/feeds/posts/default";
geturi(model.feedURI);
}
]]>
</mx:Script>
<mx:Label text="Wprowadz adres RSS lub Atom" fontSize="12" paddingTop="4" fontWeight="bold"/>
<mx:TextInput id="uritext" width="400" text="{model.feedURI}" fontSize="12"/>
<mx:Button id="uributton" label="Pobierz" click="geturi(uritext.text)" fontSize="12"/>
</mx:HBox>
Kod DetailView.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" horizontalAlign="right">
<mx:Script>
<![CDATA[
import info.malaj.readerrss.model.Model;
import info.malaj.readerrss.events.ShowPageEvent;
[Bindable]
private var model:Model = Model.getInstance();
private var event:ShowPageEvent;

private function handleShowPage():void
{
event = new ShowPageEvent();
event.dispatch();
}
]]>
</mx:Script>
<mx:TextArea id="details" htmlText="{model.itemVO.description}" fontSize="12" width="100%" height="80%"/>
<mx:LinkButton id="goToStory" label="Pokaż stronę wpisu" click="handleShowPage();"/>
</mx:VBox>

Przyzwyczaiłem się do dość wygodnego pisania aplikacji opartych na frameworku Cairngorm między innymi na mechanizmy auto uzupełniania kodu. w edytorach kodu.

Najpierw pisze klasy dla danych w folderze vo, następnie piszę klasę Model w folderze model. Potem piszę w folderze business plik ServiceLocator.mxml i klasy delegatów. Kolejnym krokiem jest utworzenie szablonu klasy ApplicationControl w folderze control. W tej klasie wpisuję nazwę funkcjonalności, potem odpowiednio w folderach commands i events tworzę odpowiednie klasy zdarzeń i poleceń a w końcu uzupełniam klasę ApplicationControl Ostatnim etapem jest pisanie klas czy komponentów widoków w folderze views i klasy głównej aplikacji.