Archiv der Kategorie: Adobe Flex

Adobe Flex 3: mx:DataGrid in die Zwischenablage / Clipboard kopieren (z.B. für Excel)

Aufgabenstellung

Der Inhalt eines mx:DataGrid soll in die Zwischenablage kopiert werden, um ihn z.B. in Excel einzufügen.

Anmerkung: Für AdvancedDataGrid mit Baum siehe auch

Ansatz

Verwendung von System.setClipboard(…); und Iteration über den DataProvider.

Lösung

public function clipData( dg:DataGrid ):void
{
var totalExport:String = new String();
var colList:Array = new Array();
for(var i:int = 0; i < dg.columnCount; i++) { colList.push(dg.columns[i].dataField); totalExport += dg.columns[i].headerText + "\t"; } totalExport += "\r"; for(var yp:int = 0; yp < dg.dataProvider.length; yp++) { for(var xp:int = 0; xp < colList.length; xp++) { totalExport += dg.dataProvider[yp][colList[xp]] + "\t"; } totalExport += "\r"; } System.setClipboard(totalExport); Alert.show('Copied to clipboard, you can paste it now to excel...'); } [/javascript]

Adobe Flex 3: Multi-FilterFunction auf mx:ArrayCollection

Aufgabenstellung

Es wird eine Datenstruktur benötigt, die mehrere FilterFunctions unterstützt und mit der mx:ArrayCollection kompatibel ist.

Problem

mx:ArrayCollection besitzt nur die Eigenschaft für eine einzige Filter-Funktion. Möchte man mehrere Filter setzen, muss man komplexe Funktionen mit Filter-Logik implementieren.

Ansatz

Durch die Erweiterung der mx:ArrayCollection wird eine Methode filterFunctions implementiert, welche mehrere Filter entgegennehmen kann. Die erweiterte BjoernsArrayCollection kann in ArrayCollection gecastet oder ggfs. (z.B. durch eine Schleife) befüllt werden.

Lösung

Folgende Klasse erweritert die normale ArrayCollection um mehrere Filter-Funktionen:

package components
{
  import mx.collections.ArrayCollection;
 
  public class BjoernsArrayCollection extends ArrayCollection
  {
      private var _filterFunctions:Array;
 
      public function BjoernsArrayCollection( source:Array = null )
      {
         super(source);
      }
	
       public function set filterFunctions( filtersArray:Array ):void
       {
         _filterFunctions = filtersArray;
         this.filterFunction = complexFilter;
        }
		
       public function get filterFunctions():Array
       {
         return _filterFunctions;
       }
 
       protected function complexFilter( item:Object ):Boolean
       {
         var filterFlag:Boolean = true;
         var filter:Function;

         for each(filter in filterFunctions)
         {
            filterFlag = filter( item );
            if( !filterFlag ) break;
         }
         return filterFlag;
      }
    }
}

Der Filterfunktionen werden so deklariert:

// Result-Methode von Service liefert eine mx:ArrayCollection, die 
// anhand mehrerer Kriterien gefiltert wird.
public function getResetableOrganizationsHandler(event:ResultEvent):void
{
   // Instanzieren des neuen Objektes
   resetableorgas = new BjoernsArrayCollection();

   // Deklaration der Filter 
   resetableorgas.filterFunctions = 
   [
       filterByProductGroup,
       filterByCompcode,
       filterBySalesdiv,
       filterByMarket
   ];	
		
    // Umsortierung in BjoernsArrayCollection
    resetableorgas.removeAll();
			
    for each(var item:ResetableOrganizationsVO in event.result)
    {
       resetableorgas.addItem(item);				
    }
    
     resetableorgas.refresh();	
}

Der Aufbau der Filter-Funktion:

...
// Rückgabe ist true wenn der Vergleich des Eingegebenen (txtCompcode.text) 
// mit einem Element der ArrayCollection (item.compcode) passt
private function filterByCompcode( item:Object ):Boolean
{
   if( String(item.compcode).indexOf(txtCompcode.text)>-1 )return true;
   return false;
}
...

Ggfs. (z.B. in einem mx:TextInput) die Refresh-Methode aufrufen:

     <mx:TextInput change="{resetableorgas.refresh()}" id="txtCompcode" width="100%"/>

Adobe Flex 3: Rekursive Iteration über alle Controls eines Canvas

Aufgabenstellung

Gelegentlich ist es nötig über alle Komponenten eines mx:Canvas-Elements, einem Container oder einer UIComponent zu iterieren.

Beispiele:
* Deaktivieren von allen Controls eines bestimmten Typs (alle Textfelder ausgrauen)
* Neuschriftung von allen Labels
* Deaktivieren aller Reiter

Ansatz

Durch den Typecast in einen DisplayObjectContainer lässt sich über jedes UI-Element iterieren. Eine Startmethode übergibt das Canvas, bzw. das UI-Urelement. Die Rekursionsmethode castet in den kompatiblen Supertyp DisplayObjectContainer und verfügt über Möglichkeiten der Iteration über seine Eigenschaften.

Lösung

// Startmethode übergibt Urelement der Rekursion
public function startSearch():void
{
searchRecursion(this);
}

// Rekursionsmethode ruft sich selbst auf wenn Child-Elemente v.h.
public function searchRecursion(current:DisplayObjectContainer):void
{
for ( var i:Number=0; i< current.numChildren; i++) { var child:DisplayObject = current.getChildAt(i); trace(getQualifiedClassName(child)); var childContainer:DisplayObjectContainer = child as DisplayObjectContainer; if(childContainer) { searchRecursion(childContainer); } } } [/javascript]

Adobe Flex 3: Charaktere aus Flash Professional CS4 exportieren und einbinden

Aufgabenstellung

Es wird ein Grundgerüst für eine Flex-Anwendung erstellt, auf dessen Basis Animationen und Charaktere, die aus Flash CS4 exportiert worden, gesteuert werden können.

Intention

Da Adobe Flex als Entwicklungsumgebung für Programmierungen wesentlich mehr Features bietet als Flash (Context-Hilfe, Syntax-Highlighting, Design-Time-Prüfungen), wird versucht die Vorteile von Beiden Umgebungen zu nutzen und ein Flashspiel mit Flex, dessen Focus auf der Entwicklung mit Eclipse liegt, zu implementieren.

Ziel

Ziel ist das Auffinden von Bests Practices bei der Spieleentwicklung mit Flash/Flex.

Vorgehensweise 1

Erstellen von Animationen

Es werden 2 Loop-fähige Animationen erstellt, die nachher als Symbol konvertiert werden
Hier:
– Moving Landscape
– Character

Export aus Flash / Import in Flex

  • Flash schließen
  • Adobe Account anlegen
  • Flex Component Kit bei Adobe runterladen
  • Flex Component Kit mit Adobe Extension Installer installieren
  • Nur bei Problem mit Deutschen Versionen: Das in C:\User … … AppData … Adobe Flash CS4 … !!!DE!!! … Configuration-Verzeichnis in das auf der gleichen Ebene befindliche !!!EN!!! Verzeichnis kopieren
  • Flash neu starten
  • Die auf der Stage befindlichen Ebenen markieren
  • Menülieste: Modify -> Convert to Symbol
  • In Library (STRG+L) Symbol anklicken
  • Neues Menü: Command – Convert to Flex Component aufrufen
  • File->Publish aufrufen
  • In der Library auf dem neuen Flex Symbol -> Rechte Maustaste -> Convert to SWC (vorher auch unter Properties die Classnamen angeben)
  • In das Flex Projekt (lib-Verzeichnis) kopieren
  • Die Komponente steht in MXML zur Verfügung, wenn man den unter Properties angegebenen Classnamen aufruft

Versuch die Komponenten über Flex zu steuern

<?xml version="1.0" encoding="utf-8"?>
<mx:Application horizontalScrollPolicy="off" verticalScrollPolicy="off" 
          creationComplete="{onCreationComplete()}" 
         xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:local="*" >
  <mx:Script>
  	<!&#91;CDATA&#91;
  		public function onCreationComplete():void
  		{
  			test3.scaleX=-1;
  		}
  	&#93;&#93;>
  </mx:Script>
 <local:landscape x="1400" y="600" height="600">
 </local:landscape>
 <local:MeinTest id="test3" height="300"  y="370" x="200" >
 </local:MeinTest>	
 <mx:ApplicationControlBar x="0" y="0" width="100%" height="50">
  <mx:Button click="{test3.gotoAndStop(0)}" label="Stop"/>
  <mx:Button click="{test3.gotoAndPlay(0)}" label="Start"/>
  <mx:Button click="{test3.scaleY*=-1;test3.scaleX*=-1}" label="Drehen"/>
 </mx:ApplicationControlBar>
</mx:Application>

Ergebnis

Problem

Die UIMovieClips lassen sich zwar rotieren, aber nicht per scaleX um die eigene Achse drehen.

Abhilfe

Wird noch gesucht

Adobe Flex 3: Composite Pattern für Charakter-Animation mit inverser Kinematik

Aufgabenstellung

Es wird eine Flex-Anwendung entwickelt, die das Grundgerüst für ein 360 Grad Flex-Spiel mit einer Schlange erstellt.

Ansatz

Unter der Verwendung des Composite-Patterns werden die Teile der Schlange zusammengesetzt. Die Teile interagieren über „inverse Kinematik“ miteinander, d.h. jedes Teil ist Autonom, wird aber von seinem Verbindungsteil gezogen.

Die Schlange verfügt über die Eigenschaften:
– gleichmäßig beschleunigte Bewegung (Up-Taste am Keyboard)
– gleichmäßig verzögerte Bewegung (Up-Taste loslassen)
– Rückimpuls (Kollision mit Button)
– Lenkung in der Beschleunigung (Left- und Right-Button)
– Jedes vordere Verbindungsstütz zur Schlange bestimmt die Position des hinteren (inverse Kinematik)

Der Code ist minimal, die Main-Datei besteht lediglich aus der Schlange selbst und der Angabe, welches UI-Objekt eine Barriere (hier „Der böse Button“) sein soll. Diese Barriere verfügt über die Eigenschaften des Back-Impulses bei einer Kollision in der Beschleunigung.

Main-Code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application backgroundColor="#ffffff" xmlns:mx="http://www.adobe.com/2006/mxml" 
                         layout="absolute" xmlns:snake="org.actionscript.snake.*">
  <snake:Snake barrier="{boeserButton}" height="100" width="100" snakelength="100" />
  <mx:Button x="10" y="256" id="boeserButton" width="400" label="Der böse Button" />
</mx:Application>

Lösung

In neuem Browser öffnen (bitte 1x anklicken und dann Pfeiltasten benutzen)

Code

Der Code wurde im Flex-Builder 3 entwickelt und ist als Flex 3-Projekt gezippt.
Adobe Flex 3 Projekt downloaden

Adobe Flex 3: Event-Reihenfolge mit Methode testen

Problem

Adobe Flex 3 definiert eine Reihe von Standard-Events, die über die Kontext-Hilfe bei der Quellcodeingabe mit einem gelbem Blitz gekennzeichnet werden. Häufig nutzt man die Kontext-Hilfe im Flex-Builder (STRG+SPACE ruft sie beim Deklarieren/in der Deklaration eines MXML-Tags auf) um die definierten Events anzuzeigen.

Bei Event-Namen wie creationComplete, applicationComplete, InitializationComplete usw… stellt sich häuft die Frage nach der Reihenfolge

Ansatz

Es werden alle Events, die mit einem gelben Blitz versehen sind, an die deklarierte Methode „eventListener“ übergeben. Diese Methode listet im Debug-Modus über die TRACE-Funktion die Reihenfolge und das Auftreten der Events auf.

Lösung

<?xml version="1.0" encoding="utf-8"?>
<mx:Application added="eventListener(event)"
  addedToStage="eventListener(event)"
  applicationComplete="eventListener(event)"
  creationComplete="eventListener(event)"
  initialize="eventListener(event)"
  preinitialize="eventListener(event)"
  layout="absolute"
  xmlns:mx="http://www.adobe.com/2006/mxml">
 <mx:Script>
    <!&#91;CDATA&#91;
      import flash.utils.getQualifiedClassName;
      import mx.events.FlexEvent;
      
      private function eventListener(event:Event):void 
      {
         if (
              (event.target == this) || 
              (event.target == this.myDataGrid) ||
              (event.target == this.myPanel)
          ) 
         {
            trace(getQualifiedClassName(this) + ".eventListener: " +
	       getQualifiedClassName(event) + "." + event.type);
            trace("\ttarget: " + getQualifiedClassName(event.target));
          }
    }
 &#93;&#93;>
  </mx:Script>
  <mx:Panel added="eventListener(event)"
      addedToStage="eventListener(event)"
      creationComplete="eventListener(event)"
      id="myPanel"
      initialize="eventListener(event)"
      preinitialize="eventListener(event)">
  <mx:DataGrid  added="eventListener(event)"
           addedToStage="eventListener(event)"
           creationComplete="eventListener(event)"
           id="myDataGrid"
           initialize="eventListener(event)"
           preinitialize="eventListener(event)"/>
  </mx:Panel>
</mx:Application>

Adobe Flex 3: Drag and Drop API

Aufgabenstellung

UI-Komponenten sollen per Drag and Drop verschoben werden können.

Ansatz

Dieser Artikel beschreibt die notwendigen Flex-APIs (DragManager) für die Implementierung einer Drag and Drop-Funktionalität am Beispiel der (siehe Nachfolgeartikel) eLearning-Anwendung für das V-Modell.

Lösung

1.) Definition der verschiebbaren Komponenten und der Behälter-Komponenten.

<!-- WIRD VERSCHOBEN -->
<mx:Button dragComplete="dragCompleteHandler(event);" 
label="System-Entwurf" id="btnSystementwurf"  />
<mx:Button dragComplete="dragCompleteHandler(event);" 
label="Software-Entwurf" id="btnSoftwareentwurf"  />
..

<!-- WIRD HINEINGESCHOBEN -->
<mx:HBox verticalAlign="middle" verticalScrollPolicy="off" 
horizontalScrollPolicy="off" id="dropField1" />
<mx:HBox verticalAlign="middle" verticalScrollPolicy="off" 
horizontalScrollPolicy="off" id="dropField2" />

2.) Registrierung der Eventlistener


<mx:Application creationComplete="{onCreationComplete()} ...

public function onCreationComplete():void
{
   // Registrierung des Buttons "Anforderungsanalyse" für das Verschieben in ein Feld
   this.btnAnforderungsnanalyse.addEventListener( MouseEvent.MOUSE_DOWN, beginDrag );

   // Registrierung des Buttons "AbnahmeEntwurf" für das Verschieben in ein Feld
   this.btnAbnahmeEntwurf.addEventListener( MouseEvent.MOUSE_DOWN, beginDrag );

...

   // Die DropListener werden an die UI-Komponten, bzw. die Komponeten, in die 
   // die Objekte geschoben werden können, angehängt
   this.dropField1.addEventListener( DragEvent.DRAG_ENTER, acceptDrop );
   this.dropField2.addEventListener( DragEvent.DRAG_ENTER, acceptDrop );
   ..
   this.dropField1.addEventListener( DragEvent.DRAG_DROP, handleDrop );
   this.dropField2.addEventListener( DragEvent.DRAG_DROP, handleDrop );
}
&#91;/actionscript3&#93;

3.) Implementierung der Logik - Hier: Überprüfung ob alles richtig verschoben ist
&#91;actionscript3&#93;
private function dragCompleteHandler(event:DragEvent):void {
     var draggedButton:Button = event.dragInitiator as Button;
     var dragInitCanvas:HBox = event.dragInitiator.parent as HBox;

     var stimmt1:Boolean = getButtons(dropField1).indexOf('btnAnforderungsnanalyse')>-1;
     var stimmt2:Boolean = getButtons(dropField2).indexOf('btnSystemarchitektur')>-1;
               	
     if(stimmt1&&stimmt2) 
     {
          Alert.show('Congratulations you did it!'); 
     }                	 
}  

4.) Welche Buttons sind in den Container? (Hier HBOX)

private function getButtons(box:HBox):String
{
var btnString:String=“;
var numChildren:Number = box.numChildren;

for (var i:int = 0; i < numChildren; i++) { if(box.getChildAt(i)["id"]) { btnString=box.getChildAt(i)["id"]; } } return btnString; } [/actionscript3] 5.) Management der Drag and Drop Funktionalität [actionscript3] public function beginDrag( mouseEvent:MouseEvent ):void { // the drag initiator is the object being dragged (target of the mouse event) var dragInitiator:IUIComponent = mouseEvent.currentTarget as IUIComponent; // the drag source contains data about what's being dragged var dragSource:DragSource = new DragSource(); // add some information to the drag source dragSource.addData( "name", dragInitiator.name ); dragSource.addData( "parent", dragInitiator.parent.name ); // ask the DragManger to begin the drag DragManager.doDrag( dragInitiator, dragSource, mouseEvent, null ); } public function handleDrop( dragEvent:DragEvent ):void { var dragInitiator:Button = Button( dragEvent.dragInitiator ); var dropTarget:HBox = dragEvent.currentTarget as HBox; HBox(dropTarget).addChild(dragInitiator); } public function acceptDrop( dragEvent:DragEvent ):void { var dropTarget:IUIComponent = dragEvent.currentTarget as IUIComponent; var dragSource:DragSource = dragEvent.dragSource; // accept the drop DragManager.acceptDragDrop( dropTarget ); // show feedback DragManager.showFeedback( DragManager.MOVE ); } [/actionscript3]

Flex 3: Bemalbares mx:Canvas mit FluorineFX-Messaging (Montagsmaler)

Aufgabenstellung

Unter Verwendung der FluorineFX Messaging-API soll eine Montagsmaler-Anwendung implementiert werden. Dies bedeutet dass ein User auf eine Leinwand zeichnet und die anderen Seitenbesucher in Echtzeit eine Aktualisierung auf dem Bildschirm erhalten. Dies kann auch als Grundlage für weitere Kollaborationsanwendungen genutzt werden, in denen man gemeinsam ein Dokument konstruieren möchte.

Ansatz

Nachdem die Zeichnenfunktionalität implementiert ist, werden die Bildpunkte beim loslassen der Maustaste (MOUSE_RELEASE_EVENT) an alle Clients übertragen. Die Clients reagieren bei einer einkommenden Menge an Bildpunkten und zeichnen sofort auf die Leinwand. Es wird immer die komplette Leinwand mit allen Bildpunkten beim Mouse-Release gesendet.

Durch das Publisher/Subscriber-Prinzip abonniert die Flex-Anwendung beim Start sofort die Datenquelle „painter„. Die Datenquelle erhält Bildpunkte und verteilt sie an alle Abonennten, wenn diese nach dem zeichnen die Maus gesehn lassen.

Vorraussetzungen

Die FluorineFX-Konfigurationsdatei wird angepasst, so das es eine neue Messaging Quelle „painter“ existiert.

Konfiguration des Backends

services-config.xml:

<?xml version="1.0" encoding="utf-8" ?> 
<services-config>
    <services>
        <service-include file-path="remoting-config.xml" />
        <service-include file-path="messaging-config.xml" />
    </services>
    
    <!-- Custom authentication -->
    <security>
    </security>
    
    <channels>
        <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
           <endpoint uri="http://{server.name}:{server.port}/{context.root}/Gateway.aspx" 
             class="flex.messaging.endpoints.AMFEndpoint"/> 
            <properties>
            </properties>
        </channel-definition>

        <channel-definition id="my-rtmp" class="mx.messaging.channels.RTMPChannel">
            <endpoint uri="rtmp://{server.name}:2037" 
            class="flex.messaging.endpoints.RTMPEndpoint"/>
            <properties>
                <idle-timeout-minutes>20</idle-timeout-minutes>
            </properties>
        </channel-definition>

    </channels>
</services-config>

messaging-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<service id="message-service" class="flex.messaging.services.MessageService" 
    messageTypes="flex.messaging.messages.AsyncMessage">

     <!-- DO NOT CHANGE <adapters> SECTION-->
    <adapters>
	<adapter-definition id="messagingAdapter" 
             class="FluorineFx.Messaging.Services.Messaging.MessagingAdapter" 
             default="true"/>
    </adapters>
    <destination id="chat">
	<adapter ref="messagingAdapter"/>
        <properties>
            <network>
                <session-timeout>0</session-timeout>
            </network>
        </properties>
        <channels>
            <channel ref="my-rtmp"/>
        </channels>
    </destination>
    <destination id="textchat">
	<adapter ref="messagingAdapter"/>
        <properties>
            <network>
                <session-timeout>0</session-timeout>
            </network>
        </properties>
        <channels>
            <channel ref="my-rtmp"/>
        </channels>
    </destination>
    <destination id="painter">
	<adapter ref="messagingAdapter"/>
        <properties>
            <network>
                <session-timeout>0</session-timeout>
            </network>
        </properties>
        <channels>
            <channel ref="my-rtmp"/>
        </channels>
    </destination>
    <destination id="opminboxrefresher">
	<adapter ref="messagingAdapter"/>
    	<properties>
	    <network>
            	<session-timeout>0</session-timeout>
            </network>
    	</properties>
    	<channels>
         	<channel ref="my-rtmp"/>
    	</channels>
    </destination> 
</service>

Konfiguration des Frontends

Bei den Frontend Konfigurationsdateien kann einfach die Datei services-config.xml und die Datei messaging-config.xml kopiert werden. Es können aber absolute Pfade anstelle der Platzhalter wie {server.name},{server.port},{context.root} genutzt werden. Hierdurch ist eine lokale Entwicklung der Flex-Anwendungen mit einem entfernten IIS Server möglich.

Lösung

PaintMessaging.mxml (Projektdatei)

<?xml version="1.0" encoding="utf-8"?>
<mx:Application creationComplete="{init()}" xmlns:mx="http://www.adobe.com/2006/mxml" 
	layout="absolute" xmlns:components="components.*">
	<mx:Script>
		<!&#91;CDATA&#91;
			import models.ModelLocator;
			import mx.controls.Alert;
			import mx.messaging.events.MessageFaultEvent;
			import mx.messaging.events.MessageEvent;
			import mx.messaging.messages.AsyncMessage;
			import mx.managers.CursorManager;
			&#91;Bindable&#93;
            &#91;Embed(source="../assets/stiftklein.png")&#93;
            private var stift:Class;
            
            public var cursorID:int;
            
            public function init():void 
            {
            	consumer.subscribe();
            }
            
            public function mouseOverHandler(event:MouseEvent):void
            {
            	
            }
            
            public function downEvent(event:MouseEvent):void 
            {
            	
            } 
            
            public function upEvent(event:MouseEvent):void
            {
            	
            }
            
	private function messageHandler(event:MessageEvent):void
    	{
    	    ModelLocator.getInstance().lines=event.message.body as Array;
    	    dc_main.invalidateDisplayList();
    	}
   
   	private function messagefaultHandler(event:MessageFaultEvent):void
   	{ 
   	   Alert.show(event.faultCode+' '+event.faultDetail+' '+event.faultString); 
   	}     		
            
	&#93;&#93;>
	</mx:Script>
	<mx:Consumer id="consumer" destination="painter" 
		message="messageHandler(event)" fault="messagefaultHandler(event)"/>
    <mx:Producer id="producer" destination="painter" 
    	fault="messagefaultHandler(event)"/>		

    <mx:Panel mouseOver="{ cursorID = CursorManager.setCursor(stift); }" 
    	mouseOut="{CursorManager.removeCursor(cursorID);}" 
    	layout="absolute" 
    	title="Montagsmaler by Björn Karpenstein" 
    	backgroundColor="#ffffff" 
    	borderThicknessBottom="10" left="20" 
    	right="20" top="20" bottom="20">
       <components:DrawableCanvas id="dc_main" backgroundColor="#ffff80" 
       	backgroundAlpha="0" width="100%" height="100%" y="0" x="0">
       </components:DrawableCanvas>
    </mx:Panel>
		
</mx:Application>

DrawableCanvas.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300" 
       creationComplete="init()">
    
    <mx:Script>
        <!&#91;CDATA&#91;
            
            public var lineWidth:Number = 5;
            
            public var lineColour:uint = 1;
            
            public var lineAlpha:Number = 1;
            
            
            private var enabler:DrawingEnabler;
            
            private function init():void
            {
                enabler = new DrawingEnabler(this);
            }            
            
            protected override function updateDisplayList(unscaledWidth:Number,
                            unscaledHeight:Number):void
            {
                super.updateDisplayList(unscaledWidth, unscaledHeight);
            
                if( enabler != null ) enabler.drawLines(graphics, lineWidth, 
                lineColour, lineAlpha);
            }
        &#93;&#93;>
    </mx:Script>
</mx:Canvas>

DrawingEnabler.as

package components
{
import flash.display.Graphics;
import flash.events.MouseEvent;

import models.ModelLocator;

import mx.core.Application;
import mx.core.UIComponent;
import mx.messaging.messages.AsyncMessage;

public class DrawingEnabler
{
private var _target:UIComponent;

private var _curentLine:Array;

public function DrawingEnabler( target:UIComponent ):void
{
_target = target;
_target.addEventListener(MouseEvent.MOUSE_DOWN, downEvent);
_target.addEventListener(MouseEvent.MOUSE_UP, upEvent);
_target.addEventListener(MouseEvent.MOUSE_OUT, upEvent);
}

public function sendMessage(stream:Array):void
{
var message:AsyncMessage = new AsyncMessage();
message.body = stream;
Application.application.producer.send(message);
}

public function newLine():void
{
_curentLine = new Array();
ModelLocator.getInstance().lines.push( _curentLine );

if( ModelLocator.getInstance().lines.length > 10 )
ModelLocator.getInstance().lines.shift();
}

public function addPoint(xIN:int, yIN:int):void
{
_curentLine.push( { x:xIN, y:yIN } );
_target.invalidateDisplayList();
}

public function drawLines(graphics:Graphics,lw:Number,lc:uint,la:Number):void
{
graphics.clear();
graphics.lineStyle(lw,lc,la);

for( var j:int = 0; j

Flex 3 und Google Maps API

Aufgabenstellung

In eine Flex-Anwendung soll Google Maps integriert werden.

Ansatz

1.) Aufruf der Seite http://code.google.com/intl/de/apis/maps/documentation/flash/
2.) Runterladen der Flash-Bibliothek (SWC-Datei) und einfügen in das LIBS-Verzeichnis der Flex-Anwendung
3.) Anfordern des Schlüssels unter „Wie beginne ich…“ und eintragen in den Code unten.

Lösung

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
	<!&#91;CDATA&#91;
		import com.google.maps.overlays.Marker;
		import com.google.maps.controls.ZoomControl;
		import com.google.maps.geom.Attitude;
		import mx.controls.Alert;
		import com.google.maps.*;
		import com.google.maps.geom.*;
		import com.google.maps.services.GeocodingEvent;
		import com.google.maps.services.ClientGeocoder;
		import com.google.maps.controls.NavigationControl;
		import com.google.maps.controls.MapTypeControl;
		import com.google.maps.MapEvent;
		
		public function onMapReady(event:MapEvent):void
		{
			// Die Bedienelemente der Karte hinzufügen
			map.addControl(new MapTypeControl());
			map.addControl(new NavigationControl());
			this.geocodeLocation('Fulda, Am Rinnweg 15');
		}
		
		public function onMapPreinitialize(event:MapEvent):void
		{
			var myMapOptions:MapOptions = new MapOptions();
			myMapOptions.viewMode = View.VIEWMODE_2D;
			myMapOptions.mapType=MapType.NORMAL_MAP_TYPE;
			//myMapOptions.zoom=0;
			map.setInitOptions(myMapOptions);
		}
		
		private function geocodeLocation(location:String=''):void
		{
			var geocoder:ClientGeocoder = new ClientGeocoder();
			geocoder.addEventListener(GeocodingEvent.GEOCODING_SUCCESS,
			geoCodeSuccess);
			geocoder.addEventListener(GeocodingEvent.GEOCODING_FAILURE, 
			geoCodeFailure);

			if(location!='')
			{
				geocoder.geocode(location);
			}
			else
			{
				geocoder.geocode(search.text);
			}
		}
		
		private function geoCodeSuccess(event:GeocodingEvent):void
		{
			var placemarks:Array = event.response.placemarks;
			map.flyTo(placemarks&#91;0&#93;.point, 18, new Attitude(35,60,35), 
			3);
			var marker:Marker = new Marker(placemarks&#91;0&#93;.point); 
			map.addOverlay(marker); 
		}
		
		private function geoCodeFailure(event:GeocodingEvent):void
		{
			Alert.show('Also wissense, das find ich einfach ned....',
                                       'Ähm...');			
		}		
	&#93;&#93;>
</mx:Script>
	<mx:TitleWindow layout="vertical" width="100%" height="100%" 
              title="Finde versteckte Schätze... 
             (c) die 1st-level-caches Schludi&amp;Mephi ">
		<maps:Map3D xmlns:maps="com.google.maps.*" 
			  id="map" 
			  mapevent_mapready="onMapReady(event)" 
			  mapevent_mappreinitialize="onMapPreinitialize(event)"
			  width="100%" 
			  height="100%"
    		  key="HIER KOMMT DER BEANTRAGTE GOOGLE KEY REIN"/>
    	<mx:HBox horizontalAlign="center" width="100%" height="30">
			<mx:Label x="70" y="524" text="Da will ich hin:" 
                                        width="120" fontWeight="bold"/>
			<mx:Button x="421" y="520" label="Suchen ..." 
                                        click="{geocodeLocation()}"/>
			<mx:TextInput id="search" x="167" y="520" 
                                       width="246"/>
    	</mx:HBox>
	</mx:TitleWindow>
</mx:Application>

Beispiel

http://baugebiete.fulda.de