flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aha...@apache.org
Subject [34/48] git commit: [flex-utilities] [refs/heads/develop] - move locale editor under flex-installer
Date Mon, 15 Jun 2015 06:31:08 GMT
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/command/ShowLogFileRequestCommand.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/command/ShowLogFileRequestCommand.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/command/ShowLogFileRequestCommand.as
new file mode 100644
index 0000000..7cb8c5a
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/command/ShowLogFileRequestCommand.as
@@ -0,0 +1,81 @@
+package org.apache.flex.runtimelocale.command {
+	import flash.display.DisplayObject;
+	import flash.events.Event;
+	import flash.filesystem.File;
+	import flash.filesystem.FileMode;
+	import flash.filesystem.FileStream;
+	import mx.core.FlexGlobals;
+	import mx.managers.PopUpManager;
+	import mx.utils.ObjectUtil;
+	import org.apache.flex.runtimelocale.view.TextFileContentView;
+	import org.as3commons.logging.api.ILogger;
+	import org.as3commons.logging.api.getClassLogger;
+
+	public class ShowLogFileRequestCommand extends AbstractBaseCommand {
+
+		private static const logger:ILogger = getClassLogger(ShowLogFileRequestCommand);
+
+		public function ShowLogFileRequestCommand(event:Event) {
+			super(event);
+		}
+
+		override public function execute():* {
+			var logFilePath:File = getNewestLogFilePath();
+			if (logFilePath) {
+				var fileContent:String = loadLogFile(logFilePath);
+				if (fileContent) {
+					showLogFile(fileContent, logFilePath.nativePath);
+				}
+			}
+			logger.info("Executed ShowLogFileRequestCommand");
+		}
+
+		private function compareCreationDates(f1:File, f2:File):Number {
+			return ObjectUtil.dateCompare(f1.creationDate, f2.creationDate);
+		}
+
+		private function getNewestLogFilePath():File {
+			var listing:Array = File.applicationStorageDirectory.getDirectoryListing();
+			var logListing:Array = [];
+			for each (var file:File in listing) {
+				if (file.extension == "log") {
+					logListing[logListing.length] = file;
+				}
+			}
+			if (logListing.length > 1) {
+				logListing.sort(compareCreationDates, Array.NUMERIC);
+				logListing = logListing.reverse();
+			}
+			if (logListing.length > 0) {
+				return logListing[0];
+			}
+			return null;
+		}
+
+		private function loadLogFile(logFile:File):String {
+			if (logFile.exists) {
+				try {
+					var fileStream:FileStream = new FileStream();
+					fileStream.open(logFile, FileMode.READ);
+					fileStream.position = 0;
+					return fileStream.readMultiByte(fileStream.bytesAvailable, "utf-8");
+				} catch (e:Error) {
+					logger.error("Error encountered while reading log file '{0}': {0}", [logFile, e.message]);
+				} finally {
+					fileStream.close();
+					logger.info("Successfully loaded logfile: {0}", [logFile.nativePath]);
+				}
+			}
+			return null;
+		}
+
+		private function showLogFile(fileContent:String, filePath:String):void {
+			var view:TextFileContentView = new TextFileContentView();
+			view.fileContent = fileContent;
+			view.filePath = filePath;
+			PopUpManager.addPopUp(view, (FlexGlobals.topLevelApplication as DisplayObject));
+			PopUpManager.centerPopUp(view);
+			logger.info("Showing contents of '{0}' in TextFileContentView", [filePath]);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/context/MainConfiguration.mxml
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/context/MainConfiguration.mxml b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/context/MainConfiguration.mxml
new file mode 100644
index 0000000..eeff7c8
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/context/MainConfiguration.mxml
@@ -0,0 +1,238 @@
+<?xml version="1.0" encoding="utf-8"?>
+<sas:SASObjects xmlns:fx="http://ns.adobe.com/mxml/2009"
+				xmlns:s="library://ns.adobe.com/flex/spark"
+				xmlns:mx="library://ns.adobe.com/flex/mx"
+				xmlns:sas="http://www.springactionscript.org/mxml/config"
+				skipMetadata="true"
+				skipPostProcessors="true">
+	<fx:Script>
+		<![CDATA[
+			import org.apache.flex.runtimelocale.IStatusReporter;
+			import org.apache.flex.runtimelocale.command.ApplicationErrorStatusCommand;
+			import org.apache.flex.runtimelocale.command.ApplicationInfoStatusCommand;
+			import org.apache.flex.runtimelocale.command.CreateLocaleRequestCommand;
+			import org.apache.flex.runtimelocale.command.InitializeApplicationCommand;
+			import org.apache.flex.runtimelocale.command.LocaleFileLoadedCommand;
+			import org.apache.flex.runtimelocale.command.LocaleFileReadyCommand;
+			import org.apache.flex.runtimelocale.command.LocaleFileSaveRequestCommand;
+			import org.apache.flex.runtimelocale.command.LocaleFileShowRequestCommand;
+			import org.apache.flex.runtimelocale.command.NewLocaleItemRequestCommand;
+			import org.apache.flex.runtimelocale.command.NewLocaleRequestCommand;
+			import org.apache.flex.runtimelocale.command.ReferenceLocaleRequestCommand;
+			import org.apache.flex.runtimelocale.command.RemoveLocaleItemRequestCommand;
+			import org.apache.flex.runtimelocale.command.RemoveLocaleRequestCommand;
+			import org.apache.flex.runtimelocale.command.RequestAddMissingKeysCommand;
+			import org.apache.flex.runtimelocale.command.SaveConfigurationRequestCommand;
+			import org.apache.flex.runtimelocale.command.ShowHelpRequestCommand;
+			import org.apache.flex.runtimelocale.command.ShowLocaleFileSelectorViewCommand;
+			import org.apache.flex.runtimelocale.command.ShowLogFileRequestCommand;
+			import org.apache.flex.runtimelocale.controller.ApplicationController;
+			import org.apache.flex.runtimelocale.event.ApplicationStatusEvent;
+			import org.apache.flex.runtimelocale.event.LocaleDataEvent;
+			import org.apache.flex.runtimelocale.event.LocaleEvent;
+			import org.apache.flex.runtimelocale.event.LocaleFileEvent;
+			import org.apache.flex.runtimelocale.event.LocaleFileLoadedEvent;
+			import org.apache.flex.runtimelocale.event.LocaleItemEvent;
+			import org.apache.flex.runtimelocale.event.ReferenceLocaleRequestEvent;
+			import org.apache.flex.runtimelocale.event.ShowHelpRequestEvent;
+			import org.apache.flex.runtimelocale.event.ShowLocaleFileSelectorViewEvent;
+			import org.apache.flex.runtimelocale.event.ShowLogFileRequestEvent;
+			import org.apache.flex.runtimelocale.model.ApplicationModel;
+			import org.apache.flex.runtimelocale.model.IApplicationModelAware;
+			import org.apache.flex.runtimelocale.model.LocaleFileSelectorPM;
+			import org.apache.flex.runtimelocale.model.MainViewPM;
+			import org.apache.flex.runtimelocale.view.HelpView;
+			import org.apache.flex.runtimelocale.view.LocaleFileSelectorView;
+			import org.apache.flex.runtimelocale.view.LocaleView;
+			import org.apache.flex.runtimelocale.view.MainView;
+			import org.apache.flex.runtimelocale.view.NewLocaleView;
+			import org.apache.flex.runtimelocale.view.itemrenderer.LocaleItemView;
+			import org.springextensions.actionscript.stage.DefaultAutowiringStageProcessor;
+			import org.springextensions.actionscript.stage.DefaultObjectDefinitionResolver;
+		]]>
+	</fx:Script>
+	<fx:Declarations>
+		<sas:Interface id="applicationModelAware"
+					   clazz="{IApplicationModelAware}">
+			<sas:Property name="applicationModel"
+						  ref="applicationModel"/>
+		</sas:Interface>
+
+		<sas:Interface id="statusReporter"
+					   clazz="{IStatusReporter}">
+			<sas:EventRouterConfiguration eventNames="{ApplicationStatusEvent.APPLICATION_ERROR_STATUS},{ApplicationStatusEvent.APPLICATION_INFO_STATUS}"/>
+		</sas:Interface>
+
+		<sas:Object id="objectSelector"
+					clazz="{StageObjectSelector}"
+					childContextAccess="none"/>
+
+		<sas:Object id="objectDefinitionResolver"
+					clazz="{DefaultObjectDefinitionResolver}">
+			<sas:Property name="lookupByType"
+						  value="false"
+						  type="boolean"/>
+		</sas:Object>
+
+		<sas:StageObjectProcessor objectSelector="objectSelector"
+								  id="autowiringStageProcessor"
+								  clazz="{DefaultAutowiringStageProcessor}">
+		</sas:StageObjectProcessor>
+
+		<sas:Object id="localeFileSelectorPM"
+					clazz="{LocaleFileSelectorPM}"
+					isLazyInit="true">
+			<sas:Property name="applicationModel"
+						  ref="applicationModel"/>
+			<sas:EventRouterConfiguration eventNames="{LocaleFileLoadedEvent.LOCALE_FILE_LOADED}"/>
+		</sas:Object>
+
+		<sas:Object id="mainViewPM"
+					clazz="{MainViewPM}"
+					isLazyInit="true">
+			<sas:Property name="applicationModel"
+						  ref="applicationModel"/>
+			<sas:EventRouterConfiguration eventNames="{LocaleFileEvent.FILE_SAVE_REQUEST},{LocaleFileEvent.FILE_SHOW_REQUEST},{ReferenceLocaleRequestEvent.REFERENCE_LOCALE_REQUEST},{LocaleEvent.NEW_LOCALE_REQUEST},{ShowLogFileRequestEvent.SHOW_LOG_FILE_REQUEST},{ShowHelpRequestEvent.SHOW_HELP_REQUEST}"/>
+			<sas:EventHandlerMethod eventName="{LocaleEvent.LOCALE_CREATED}"
+									name="handleNewLocale"/>
+			<sas:EventHandlerMethod eventName="{LocaleEvent.LOCALE_REMOVED}"
+									name="handleRemovedLocale"/>
+		</sas:Object>
+
+		<sas:Object id="applicationController"
+					clazz="{ApplicationController}"
+					initMethod="initialize"/>
+
+		<sas:Object id="applicationModel"
+					clazz="{ApplicationModel}"
+					isLazyInit="true"/>
+
+		<!-- BEGIN: View configurations -->
+
+		<sas:Object id="selectorView"
+					clazz="{LocaleFileSelectorView}"
+					scope="stage">
+			<sas:Property name="presentationModel"
+						  ref="localeFileSelectorPM"/>
+		</sas:Object>
+
+		<sas:Object id="mainView"
+					clazz="{MainView}"
+					scope="stage">
+			<sas:Property name="presentationModel"
+						  ref="mainViewPM"/>
+		</sas:Object>
+
+		<sas:Object id="localeItemView"
+					clazz="{LocaleItemView}"
+					scope="stage">
+			<sas:Property name="applicationModel"
+						  ref="applicationModel"/>
+		</sas:Object>
+
+		<sas:Object id="localeView"
+					clazz="{LocaleView}"
+					scope="stage">
+			<sas:EventRouterConfiguration eventNames="{LocaleItemEvent.REMOVE_LOCALE_ITEM_REQUEST},{LocaleDataEvent.REQUEST_ADD_MISSING_KEYS},{LocaleItemEvent.NEW_LOCALE_ITEM_REQUEST},{LocaleEvent.REMOVE_LOCALE_REQUEST}"/>
+		</sas:Object>
+
+		<sas:Object id="newLocaleView"
+					clazz="{NewLocaleView}"
+					scope="stage">
+			<sas:EventRouterConfiguration eventNames="{LocaleEvent.CREATE_LOCALE_REQUEST}"/>
+		</sas:Object>
+
+		<sas:Object id="helpView"
+					clazz="{HelpView}"
+					scope="stage">
+			<sas:Property name="applicationModel"
+						  ref="applicationModel"/>
+		</sas:Object>
+
+		<!-- END: View configurations -->
+
+		<!-- BEGIN: Command configurations -->
+
+		<sas:Object id="localeFileLoadedCommand"
+					clazz="{LocaleFileLoadedCommand}"
+					scope="prototype">
+			<sas:EventRouterConfiguration eventNames="{LocaleFileEvent.FILE_READY},{ShowLocaleFileSelectorViewEvent.SHOW_LOCALE_FILE_SELECTOR}"/>
+		</sas:Object>
+
+		<sas:Object id="applicationErrorStatusCommand"
+					clazz="{ApplicationErrorStatusCommand}"
+					scope="prototype"/>
+
+		<sas:Object id="applicationInfoStatusCommand"
+					clazz="{ApplicationInfoStatusCommand}"
+					scope="prototype"/>
+
+		<sas:Object id="localeFileReadyCommand"
+					clazz="{LocaleFileReadyCommand}"
+					scope="prototype">
+			<sas:EventRouterConfiguration eventNames="{ReferenceLocaleRequestEvent.REFERENCE_LOCALE_REQUEST}"/>
+		</sas:Object>
+
+		<sas:Object id="localeFileSaveRequestCommand"
+					clazz="{LocaleFileSaveRequestCommand}"
+					scope="prototype"/>
+
+		<sas:Object id="referenceLocaleRequestCommand"
+					clazz="{ReferenceLocaleRequestCommand}"
+					scope="prototype"/>
+
+		<sas:Object id="removeLocaleItemRequestCommand"
+					clazz="{RemoveLocaleItemRequestCommand}"
+					scope="prototype"/>
+
+		<sas:Object id="requestAddMissingKeysCommand"
+					clazz="{RequestAddMissingKeysCommand}"
+					scope="prototype"/>
+
+		<sas:Object id="newLocaleRequestCommand"
+					clazz="{NewLocaleRequestCommand}"
+					scope="prototype"/>
+
+		<sas:Object id="createLocaleRequestCommand"
+					clazz="{CreateLocaleRequestCommand}"
+					scope="prototype">
+			<sas:EventRouterConfiguration eventNames="{LocaleEvent.LOCALE_CREATED}"/>
+		</sas:Object>
+
+		<sas:Object id="showLocaleFileSelectorViewCommand"
+					clazz="{ShowLocaleFileSelectorViewCommand}"
+					scope="prototype"/>
+
+		<sas:Object id="initializeApplicationCommand"
+					clazz="{InitializeApplicationCommand}"
+					scope="prototype"/>
+
+		<sas:Object id="saveConfigurationRequestCommand"
+					clazz="{SaveConfigurationRequestCommand}"
+					scope="prototype"/>
+
+		<sas:Object id="newLocaleItemRequestCommand"
+					clazz="{NewLocaleItemRequestCommand}"
+					scope="prototype"/>
+
+		<sas:Object id="localeFileShowRequestCommand"
+					clazz="{LocaleFileShowRequestCommand}"
+					scope="prototype"/>
+
+		<sas:Object id="removeLocaleRequestCommand"
+					clazz="{RemoveLocaleRequestCommand}"
+					scope="prototype">
+			<sas:EventRouterConfiguration eventNames="{LocaleEvent.LOCALE_REMOVED}"/>
+		</sas:Object>
+
+		<sas:Object id="showLogFileRequestCommand"
+					clazz="{ShowLogFileRequestCommand}"
+					scope="prototype"/>
+
+		<sas:Object id="showHelpRequestCommand"
+					clazz="{ShowHelpRequestCommand}"
+					scope="prototype"/>
+
+		<!-- END: Command configurations -->
+	</fx:Declarations>
+</sas:SASObjects>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/context/StageObjectSelector.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/context/StageObjectSelector.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/context/StageObjectSelector.as
new file mode 100644
index 0000000..dd33b43
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/context/StageObjectSelector.as
@@ -0,0 +1,16 @@
+package org.apache.flex.runtimelocale.context {
+	import org.apache.flex.runtimelocale.view.IInjectableView;
+	import org.as3commons.stageprocessing.IObjectSelector;
+
+	public class StageObjectSelector implements IObjectSelector {
+
+		public function StageObjectSelector() {
+			super();
+		}
+
+		public function approve(object:Object):Boolean {
+			var result:Boolean = (object is IInjectableView);
+			return result;
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/controller/ApplicationController.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/controller/ApplicationController.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/controller/ApplicationController.as
new file mode 100644
index 0000000..f983b7a
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/controller/ApplicationController.as
@@ -0,0 +1,67 @@
+package org.apache.flex.runtimelocale.controller {
+	import flash.events.Event;
+	import flash.events.EventDispatcher;
+	import org.apache.flex.runtimelocale.model.locale.LocaleDataVO;
+	import org.as3commons.async.command.ICommand;
+	import org.as3commons.async.operation.IOperation;
+	import org.as3commons.async.operation.event.OperationEvent;
+	import org.as3commons.eventbus.IEventBusAware;
+	import org.as3commons.eventbus.IEventBusListener;
+	import org.as3commons.logging.api.ILogger;
+	import org.as3commons.logging.api.getClassLogger;
+	import org.springextensions.actionscript.context.IApplicationContext;
+	import org.springextensions.actionscript.context.IApplicationContextAware;
+
+	public class ApplicationController extends EventDispatcher implements IEventBusListener, IApplicationContextAware {
+		private static const COMMAND:String = "Command";
+
+		private static const logger:ILogger = getClassLogger(ApplicationController);
+
+		public function ApplicationController() {
+			super();
+		}
+
+		private var _applicationContext:IApplicationContext;
+
+		public function get applicationContext():IApplicationContext {
+			return _applicationContext;
+		}
+
+		public function set applicationContext(value:IApplicationContext):void {
+			_applicationContext = value;
+		}
+
+		public function initialize():void {
+			if (_applicationContext is IEventBusAware) {
+				(_applicationContext as IEventBusAware).eventBus.addListener(this);
+				logger.info("ApplicationController initialized...");
+			}
+		}
+
+		public function onEvent(event:Event):void {
+			logger.info("Received event '{0}'", [event.type]);
+			var definitionName:String = event.type + COMMAND;
+			if (_applicationContext.canCreate(definitionName)) {
+				logger.info("Command definition found called '{0}' for event '{1}'", [definitionName, event.type]);
+				var command:ICommand = _applicationContext.getObject(definitionName, [event]);
+				var operation:IOperation = command.execute();
+				logger.info("Command '{0}' executed", [definitionName]);
+				if (!operation) {
+					_applicationContext.destroyObject(command);
+					logger.info("Command '{0}' destroyed", [definitionName]);
+				} else {
+					operation.addCompleteListener(operationListener);
+					operation.addErrorListener(operationListener);
+				}
+			}
+		}
+
+		private function operationListener(event:OperationEvent):void {
+			var operation:IOperation = event.operation;
+			operation.removeCompleteListener(operationListener);
+			operation.removeErrorListener(operationListener);
+			_applicationContext.destroyObject(operation.result);
+			logger.info("Command destroyed after asynchronous operation");
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ApplicationStatusEvent.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ApplicationStatusEvent.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ApplicationStatusEvent.as
new file mode 100644
index 0000000..8c221c3
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ApplicationStatusEvent.as
@@ -0,0 +1,31 @@
+package org.apache.flex.runtimelocale.event {
+	import flash.events.Event;
+
+	public class ApplicationStatusEvent extends Event {
+
+		public static const APPLICATION_ERROR_STATUS:String = "applicationErrorStatus";
+		public static const APPLICATION_INFO_STATUS:String = "applicationInfoStatus";
+
+		private var _statusMessage:String;
+		private var _caption:String;
+
+		public function ApplicationStatusEvent(type:String, message:String, caption:String=null, bubbles:Boolean=false, cancelable:Boolean=false) {
+			super(type, bubbles, cancelable);
+			_statusMessage = message;
+			_caption = caption;
+		}
+
+		public function get caption():String {
+			return _caption;
+		}
+
+		public function get statusMessage():String {
+			return _statusMessage;
+		}
+
+		override public function clone():Event {
+			return new ApplicationStatusEvent(type, _statusMessage, _caption, bubbles, cancelable);
+		}
+
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/InitializeApplicationEvent.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/InitializeApplicationEvent.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/InitializeApplicationEvent.as
new file mode 100644
index 0000000..d9aabf0
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/InitializeApplicationEvent.as
@@ -0,0 +1,11 @@
+package org.apache.flex.runtimelocale.event {
+	import flash.events.Event;
+
+	public class InitializeApplicationEvent extends Event {
+		public static const APP_INITIALIZE:String = "initializeApplication";
+
+		public function InitializeApplicationEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
+			super(type, bubbles, cancelable);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleDataEvent.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleDataEvent.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleDataEvent.as
new file mode 100644
index 0000000..0cecdbc
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleDataEvent.as
@@ -0,0 +1,27 @@
+package org.apache.flex.runtimelocale.event {
+	import flash.events.Event;
+
+	import org.apache.flex.runtimelocale.model.locale.LocaleDataVO;
+
+	public class LocaleDataEvent extends Event {
+		public static const REQUEST_ADD_MISSING_KEYS:String = "requestAddMissingKeys";
+		private var _localeData:LocaleDataVO;
+
+		public function LocaleDataEvent(type:String, data:LocaleDataVO, bubbles:Boolean=false, cancelable:Boolean=false) {
+			super(type, bubbles, cancelable);
+			_localeData = data;
+		}
+
+		public function get localeData():LocaleDataVO {
+			return _localeData;
+		}
+
+		public function set localeData(value:LocaleDataVO):void {
+			_localeData = value;
+		}
+
+		override public function clone():Event {
+			return new LocaleDataEvent(type, _localeData, bubbles, cancelable);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleEvent.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleEvent.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleEvent.as
new file mode 100644
index 0000000..dd3156e
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleEvent.as
@@ -0,0 +1,42 @@
+package org.apache.flex.runtimelocale.event {
+	import flash.events.Event;
+	import org.apache.flex.runtimelocale.model.locale.LocaleDataVO;
+
+	public class LocaleEvent extends Event {
+
+		public static const CREATE_LOCALE_REQUEST:String = "createLocaleRequest";
+		public static const LOCALE_CREATED:String = "localeCreated";
+		public static const LOCALE_REMOVED:String = "localeRemoved";
+		public static const NEW_LOCALE_REQUEST:String = "newLocaleRequest";
+		public static const REMOVE_LOCALE_REQUEST:String = "removeLocaleRequest";
+
+		public function LocaleEvent(type:String, locale:String=null, data:LocaleDataVO=null, bubbles:Boolean=false, cancelable:Boolean=true) {
+			super(type, bubbles, cancelable);
+			_localeName = locale;
+			_localeData = data;
+		}
+
+		private var _localeData:LocaleDataVO;
+		private var _localeName:String;
+
+		override public function clone():Event {
+			return new LocaleEvent(type, _localeName, _localeData, bubbles, cancelable);
+		}
+
+		public function get localeData():LocaleDataVO {
+			return _localeData;
+		}
+
+		public function set localeData(value:LocaleDataVO):void {
+			_localeData = value;
+		}
+
+		public function get localeName():String {
+			return _localeName;
+		}
+
+		public function set localeName(value:String):void {
+			_localeName = value;
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleFileEvent.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleFileEvent.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleFileEvent.as
new file mode 100644
index 0000000..83a02b7
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleFileEvent.as
@@ -0,0 +1,14 @@
+package org.apache.flex.runtimelocale.event {
+	import flash.events.Event;
+
+	public class LocaleFileEvent extends Event {
+
+		public static const FILE_READY:String = "localeFileReady";
+		public static const FILE_SAVE_REQUEST:String = "localeFileSaveRequest";
+		public static const FILE_SHOW_REQUEST:String = "localeFileShowRequest";
+
+		public function LocaleFileEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
+			super(type, bubbles, cancelable);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleFileLoadedEvent.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleFileLoadedEvent.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleFileLoadedEvent.as
new file mode 100644
index 0000000..a4860ba
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleFileLoadedEvent.as
@@ -0,0 +1,29 @@
+package org.apache.flex.runtimelocale.event {
+
+	import flash.events.Event;
+
+	public class LocaleFileLoadedEvent extends Event {
+
+		public static const LOCALE_FILE_LOADED:String = "localeFileLoaded";
+		private var _fileContent:String;
+		private var _filePath:String;
+
+		public function LocaleFileLoadedEvent(fileContent:String, filePath:String, bubbles:Boolean=false, cancelable:Boolean=false) {
+			super(LOCALE_FILE_LOADED, bubbles, cancelable);
+			_fileContent = fileContent;
+			_filePath = filePath;
+		}
+
+		public function get filePath():String {
+			return _filePath;
+		}
+
+		public function get fileContent():String {
+			return _fileContent;
+		}
+
+		override public function clone():Event {
+			return new LocaleFileLoadedEvent(_fileContent, _filePath, bubbles, cancelable);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleItemEvent.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleItemEvent.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleItemEvent.as
new file mode 100644
index 0000000..5b3e356
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/LocaleItemEvent.as
@@ -0,0 +1,34 @@
+package org.apache.flex.runtimelocale.event {
+	import flash.events.Event;
+	import org.apache.flex.runtimelocale.model.locale.LocaleDataVO;
+
+	public class LocaleItemEvent extends Event {
+		public static const NEW_LOCALE_ITEM_REQUEST:String = "newLocaleItemRequest";
+		public static const REMOVE_LOCALE_ITEM_REQUEST:String = "removeLocaleItemRequest";
+
+		public function LocaleItemEvent(type:String, key:String, locale:LocaleDataVO=null, bubbles:Boolean=false, cancelable:Boolean=false) {
+			super(type, bubbles, cancelable);
+			_itemKey = key;
+			_localeData = locale;
+		}
+
+		private var _itemKey:String;
+		private var _localeData:LocaleDataVO;
+
+		override public function clone():Event {
+			return new LocaleItemEvent(type, _itemKey, _localeData, bubbles, cancelable);
+		}
+
+		public function get itemKey():String {
+			return _itemKey;
+		}
+
+		public function get localeData():LocaleDataVO {
+			return _localeData;
+		}
+
+		public function set localeData(value:LocaleDataVO):void {
+			_localeData = value;
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ReferenceLocaleRequestEvent.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ReferenceLocaleRequestEvent.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ReferenceLocaleRequestEvent.as
new file mode 100644
index 0000000..1eece80
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ReferenceLocaleRequestEvent.as
@@ -0,0 +1,27 @@
+package org.apache.flex.runtimelocale.event {
+	import flash.events.Event;
+
+	public class ReferenceLocaleRequestEvent extends Event {
+
+		public static const REFERENCE_LOCALE_REQUEST:String = "referenceLocaleRequest";
+
+		public function ReferenceLocaleRequestEvent(type:String, locale:String, bubbles:Boolean=false, cancelable:Boolean=false) {
+			super(type, bubbles, cancelable);
+			_localeName = locale;
+		}
+
+		private var _localeName:String;
+
+		override public function clone():Event {
+			return new ReferenceLocaleRequestEvent(type, _localeName, bubbles, cancelable);
+		}
+
+		public function get localeName():String {
+			return _localeName;
+		}
+
+		public function set localeName(value:String):void {
+			_localeName = value;
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/SaveConfigurationEvent.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/SaveConfigurationEvent.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/SaveConfigurationEvent.as
new file mode 100644
index 0000000..38cc76f
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/SaveConfigurationEvent.as
@@ -0,0 +1,12 @@
+package org.apache.flex.runtimelocale.event {
+	import flash.events.Event;
+
+	public class SaveConfigurationEvent extends Event {
+
+		public static const SAVE_CONFIGURATION_REQUEST:String = "saveConfigurationRequest";
+
+		public function SaveConfigurationEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
+			super(type, bubbles, cancelable);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ShowHelpRequestEvent.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ShowHelpRequestEvent.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ShowHelpRequestEvent.as
new file mode 100644
index 0000000..5e22780
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ShowHelpRequestEvent.as
@@ -0,0 +1,12 @@
+package org.apache.flex.runtimelocale.event {
+	import flash.events.Event;
+
+	public class ShowHelpRequestEvent extends Event {
+
+		public static const SHOW_HELP_REQUEST:String = "showHelpRequest";
+
+		public function ShowHelpRequestEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
+			super(type, bubbles, cancelable);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ShowLocaleFileSelectorViewEvent.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ShowLocaleFileSelectorViewEvent.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ShowLocaleFileSelectorViewEvent.as
new file mode 100644
index 0000000..ef00005
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ShowLocaleFileSelectorViewEvent.as
@@ -0,0 +1,12 @@
+package org.apache.flex.runtimelocale.event {
+	import flash.events.Event;
+
+	public class ShowLocaleFileSelectorViewEvent extends Event {
+
+		public static const SHOW_LOCALE_FILE_SELECTOR:String = "showLocaleFileSelectorView";
+
+		public function ShowLocaleFileSelectorViewEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
+			super(type, bubbles, cancelable);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ShowLogFileRequestEvent.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ShowLogFileRequestEvent.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ShowLogFileRequestEvent.as
new file mode 100644
index 0000000..e4883ec
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/event/ShowLogFileRequestEvent.as
@@ -0,0 +1,12 @@
+package org.apache.flex.runtimelocale.event {
+	import flash.events.Event;
+
+	public class ShowLogFileRequestEvent extends Event {
+
+		public static const SHOW_LOG_FILE_REQUEST:String = "showLogFileRequest";
+
+		public function ShowLogFileRequestEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
+			super(type, bubbles, cancelable);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/ini/IniReader.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/ini/IniReader.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/ini/IniReader.as
new file mode 100644
index 0000000..5ecc539
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/ini/IniReader.as
@@ -0,0 +1,108 @@
+package org.apache.flex.runtimelocale.ini {
+	import flash.errors.IllegalOperationError;
+	import flash.filesystem.File;
+	import flash.filesystem.FileMode;
+	import flash.filesystem.FileStream;
+	import org.as3commons.logging.api.ILogger;
+	import org.as3commons.logging.api.getClassLogger;
+
+	public class IniReader {
+
+		/** Character code for the APPLE line break. */
+		public static const MAC_BREAK:String = String.fromCharCode(13);
+		/** Character used internally for line breaks. */
+		public static const NEWLINE_CHAR:String = "\n";
+
+		/** Character code for the WINDOWS line break. */
+		public static const WIN_BREAK:String = String.fromCharCode(13) + String.fromCharCode(10);
+
+		private static var logger:ILogger = getClassLogger(IniReader);
+
+		/**
+		 * Constructs a new MultilineString.
+		 */
+		public function IniReader() {
+			super();
+		}
+
+		/** Separation of all lines for the string. */
+		private var _lines:Array;
+
+		/** Original content without standardized line breaks. */
+		private var _original:String;
+
+		/**
+		 * Returns a specific line within the <code>MultilineString</code>.
+		 *
+		 * <p>It will return <code>undefined</code> if the line does not exist.</p>
+		 *
+		 * <p>The line does not contain the line break.</p>
+		 *
+		 * <p>The counting of lines startes with <code>0</code>.</p>
+		 *
+		 * @param line number of the line to get the content of
+		 * @return content of the line
+		 */
+		public function getLine(line:uint):String {
+			return _lines[line];
+		}
+
+		/**
+		 * Returns the content as array that contains each line.
+		 *
+		 * @return content split into lines
+		 */
+		public function get lines():Array {
+			return _lines.concat();
+		}
+
+		/**
+		 * Returns the amount of lines in the content.
+		 *
+		 * @return amount of lines within the content
+		 */
+		public function get numLines():uint {
+			return _lines.length;
+		}
+
+		/**
+		 * Returns the original used string (without line break standardisation).
+		 *
+		 * @return the original used string
+		 */
+		public function get originalString():String {
+			return _original;
+		}
+
+		public function readFromFile(iniFilePath:String):Object {
+			logger.debug("Reading local .ini file: " + iniFilePath);
+			var file:File = File.applicationDirectory.resolvePath(iniFilePath);
+			var stream:FileStream = new FileStream();
+			var string:String;
+			try {
+				stream.open(file, FileMode.READ);
+				stream.position = 0;
+				string = stream.readMultiByte(stream.bytesAvailable, "utf-8");
+			} finally {
+				stream.close();
+			}
+			_original = string;
+			_lines = string.split(WIN_BREAK).join(NEWLINE_CHAR).split(MAC_BREAK).join(NEWLINE_CHAR).split(NEWLINE_CHAR);
+			var properties:Object = {};
+			delete properties['prototype'];
+			for each (var line:String in _lines) {
+				if (line.substr(0, 2) != '//' && line.substr(0, 1) != '#') {
+					var parts:Array = line.split('=');
+					if (parts.length > 1) {
+						if (parts[0] in properties) {
+							throw new IllegalOperationError("Duplicate property name encountered: " + parts[0]);
+						}
+						properties[parts[0]] = parts[1];
+						logger.debug("Extracted property: " + parts[0] + ' = ' + parts[1]);
+					}
+				}
+			}
+			return properties;
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/ApplicationModel.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/ApplicationModel.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/ApplicationModel.as
new file mode 100644
index 0000000..e89b625
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/ApplicationModel.as
@@ -0,0 +1,111 @@
+package org.apache.flex.runtimelocale.model {
+	import flash.events.Event;
+	import flash.events.EventDispatcher;
+	import mx.collections.ArrayCollection;
+	import mx.core.FlexGlobals;
+	import org.apache.flex.runtimelocale.model.locale.LocaleDataVO;
+	import org.as3commons.asblocks.dom.IASCompilationUnit;
+	import org.as3commons.logging.api.ILogger;
+	import org.as3commons.logging.api.getClassLogger;
+	import spark.components.WindowedApplication;
+
+	public class ApplicationModel extends EventDispatcher {
+
+		public static const APP_INIT_STATE:String = "appInitState";
+		public static const APP_READY_STATE:String = "appReadyState";
+
+		private static const logger:ILogger = getClassLogger(ApplicationModel);
+
+		public function ApplicationModel() {
+			super();
+			logger.info("Application model created.");
+		}
+
+		private var _availableLocales:ArrayCollection;
+		private var _configurationProperties:Object;
+
+		private var _currentLocalFilePath:String;
+		private var _localeCompilationUnit:IASCompilationUnit;
+		private var _localeData:Vector.<LocaleDataVO>;
+		private var _referenceLocale:LocaleDataVO;
+
+		[Bindable(event="availableLocalesChanged")]
+		public function get availableLocales():ArrayCollection {
+			return _availableLocales;
+		}
+
+		public function set availableLocales(value:ArrayCollection):void {
+			if (_availableLocales !== value) {
+				_availableLocales = value;
+				dispatchEvent(new Event("availableLocalesChanged"));
+			}
+		}
+
+		public function get configurationProperties():Object {
+			return _configurationProperties;
+		}
+
+		public function set configurationProperties(value:Object):void {
+			_configurationProperties = value;
+		}
+
+		[Bindable(event="currentLocalFilePathChanged")]
+		public function get currentLocalFilePath():String {
+			return _currentLocalFilePath;
+		}
+
+		public function set currentLocalFilePath(value:String):void {
+			if (_currentLocalFilePath !== value) {
+				_currentLocalFilePath = value;
+				dispatchEvent(new Event("currentLocalFilePathChanged"));
+			}
+		}
+
+		public function get currentState():String {
+			return (FlexGlobals.topLevelApplication as WindowedApplication).currentState;
+		}
+
+		public function set currentState(value:String):void {
+			if (value != (FlexGlobals.topLevelApplication as WindowedApplication).currentState) {
+				(FlexGlobals.topLevelApplication as WindowedApplication).currentState = value;
+			}
+		}
+
+		[Bindable(event="localeCompilationUnitChanged")]
+		public function get localeCompilationUnit():IASCompilationUnit {
+			return _localeCompilationUnit;
+		}
+
+		public function set localeCompilationUnit(value:IASCompilationUnit):void {
+			if (_localeCompilationUnit !== value) {
+				_localeCompilationUnit = value;
+				currentState = (_localeCompilationUnit) ? APP_READY_STATE : APP_INIT_STATE;
+				dispatchEvent(new Event("localeCompilationUnitChanged"));
+			}
+		}
+
+		[Bindable(event="localeDataChanged")]
+		public function get localeData():Vector.<LocaleDataVO> {
+			return _localeData;
+		}
+
+		public function set localeData(value:Vector.<LocaleDataVO>):void {
+			if (_localeData !== value) {
+				_localeData = value;
+				dispatchEvent(new Event("localeDataChanged"));
+			}
+		}
+
+		[Bindable(event="referenceLocaleChanged")]
+		public function get referenceLocale():LocaleDataVO {
+			return _referenceLocale;
+		}
+
+		public function set referenceLocale(value:LocaleDataVO):void {
+			if (_referenceLocale !== value) {
+				_referenceLocale = value;
+				dispatchEvent(new Event("referenceLocaleChanged"));
+			}
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/IApplicationModelAware.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/IApplicationModelAware.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/IApplicationModelAware.as
new file mode 100644
index 0000000..b32ed62
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/IApplicationModelAware.as
@@ -0,0 +1,7 @@
+package org.apache.flex.runtimelocale.model {
+
+	public interface IApplicationModelAware {
+		function get applicationModel():ApplicationModel;
+		function set applicationModel(value:ApplicationModel):void;
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/LocaleFileSelectorPM.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/LocaleFileSelectorPM.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/LocaleFileSelectorPM.as
new file mode 100644
index 0000000..5ed9a5b
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/LocaleFileSelectorPM.as
@@ -0,0 +1,116 @@
+package org.apache.flex.runtimelocale.model {
+	import flash.events.Event;
+	import flash.events.EventDispatcher;
+	import flash.events.IOErrorEvent;
+	import flash.filesystem.File;
+	import flash.filesystem.FileMode;
+	import flash.filesystem.FileStream;
+	import flash.net.FileFilter;
+	import mx.managers.CursorManager;
+	import org.apache.flex.runtimelocale.IStatusReporter;
+	import org.apache.flex.runtimelocale.event.ApplicationStatusEvent;
+	import org.apache.flex.runtimelocale.event.LocaleFileLoadedEvent;
+	import org.as3commons.logging.api.ILogger;
+	import org.as3commons.logging.api.getClassLogger;
+
+	public class LocaleFileSelectorPM extends EventDispatcher implements IStatusReporter {
+
+		private static const logger:ILogger = getClassLogger(LocaleFileSelectorPM);
+
+		public function LocaleFileSelectorPM() {
+			super();
+		}
+
+		private var _applicationModel:ApplicationModel;
+		private var _localeASFile:File;
+		private var _selectedFile:String;
+
+		public function get applicationModel():ApplicationModel {
+			return _applicationModel;
+		}
+
+		public function set applicationModel(value:ApplicationModel):void {
+			_applicationModel = value;
+			if (_applicationModel) {
+				selectedFile = _applicationModel.configurationProperties['localefilepath'];
+			}
+		}
+
+		public function browseFile():void {
+			_localeASFile = new File();
+			_localeASFile.addEventListener(Event.CANCEL, cancelBrowse);
+			_localeASFile.addEventListener(Event.SELECT, fileSelected);
+			_localeASFile.browse([new FileFilter('RuntimeLocale.as', 'RuntimeLocale.as')]);
+		}
+
+		public function loadFile(filePath:String):void {
+			if (_localeASFile == null) {
+				_localeASFile = new File(filePath);
+			} else {
+				_localeASFile.nativePath = filePath;
+			}
+			var fileContent:String;
+			var errorMessage:String;
+			if (_localeASFile.exists) {
+				_applicationModel.configurationProperties['localefilepath'] = filePath;
+				logger.info("Added .as file path '{0}' to application properties", [filePath]);
+				var fileStream:FileStream = new FileStream();
+				CursorManager.setBusyCursor();
+				try {
+					fileStream.open(_localeASFile, FileMode.READ);
+					fileContent = fileStream.readUTFBytes(fileStream.bytesAvailable);
+				} catch (e:Error) {
+					logger.error("Error loading .as file '{0}': {1}", [filePath, e.message]);
+					dispatchEvent(new ApplicationStatusEvent(ApplicationStatusEvent.APPLICATION_ERROR_STATUS, e.message, "Error loading file"));
+				} finally {
+					CursorManager.removeBusyCursor();
+					fileStream.close();
+				}
+				logger.info("Successfully loaded .as file '{0}'", [filePath]);
+			} else {
+				errorMessage = "File " + filePath + " does not exist";
+				logger.error(errorMessage);
+				dispatchEvent(new ApplicationStatusEvent(ApplicationStatusEvent.APPLICATION_ERROR_STATUS, errorMessage, "File does not exist"));
+			}
+			_localeASFile = null;
+			if (fileContent) {
+				dispatchEvent(new LocaleFileLoadedEvent(fileContent, filePath));
+			}
+		}
+
+		public function get selectedFile():String {
+			return _selectedFile;
+		}
+
+		[Bindable(event="selectedFileChanged")]
+		public function set selectedFile(value:String):void {
+			if (value != _selectedFile) {
+				_selectedFile = value;
+				dispatchEvent(new Event("selectedFileChanged"));
+			}
+		}
+
+		protected function cancelBrowse(event:Event):void {
+			_localeASFile.removeEventListener(Event.CANCEL, cancelBrowse);
+			_localeASFile.removeEventListener(Event.SELECT, fileSelected);
+			_localeASFile = null;
+		}
+
+		protected function fileSelected(event:Event):void {
+			_localeASFile.removeEventListener(Event.CANCEL, cancelBrowse);
+			_localeASFile.removeEventListener(Event.SELECT, fileSelected);
+			selectedFile = _localeASFile.nativePath;
+		}
+
+		protected function loadComplete(event:Event):void {
+			_localeASFile.removeEventListener(Event.COMPLETE, loadComplete);
+			_localeASFile.removeEventListener(IOErrorEvent.IO_ERROR, loadError);
+		}
+
+		protected function loadError(event:IOErrorEvent):void {
+			_localeASFile.removeEventListener(Event.COMPLETE, loadComplete);
+			_localeASFile.removeEventListener(IOErrorEvent.IO_ERROR, loadError);
+			_localeASFile = null;
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/MainViewPM.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/MainViewPM.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/MainViewPM.as
new file mode 100644
index 0000000..e4937ec
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/MainViewPM.as
@@ -0,0 +1,116 @@
+package org.apache.flex.runtimelocale.model {
+	import flash.events.Event;
+	import flash.events.EventDispatcher;
+	
+	import org.apache.flex.runtimelocale.event.LocaleEvent;
+	import org.apache.flex.runtimelocale.event.LocaleFileEvent;
+	import org.apache.flex.runtimelocale.event.ReferenceLocaleRequestEvent;
+	import org.apache.flex.runtimelocale.event.ShowHelpRequestEvent;
+	import org.apache.flex.runtimelocale.event.ShowLogFileRequestEvent;
+	import org.apache.flex.runtimelocale.model.locale.LocaleDataVO;
+	import org.apache.flex.runtimelocale.view.LocaleView;
+	import org.apache.flex.runtimelocale.view.MainView;
+	import org.as3commons.logging.api.ILogger;
+	import org.as3commons.logging.api.getClassLogger;
+
+	public class MainViewPM extends EventDispatcher {
+
+		private static const logger:ILogger = getClassLogger(MainViewPM);
+
+		public function MainViewPM() {
+			super();
+		}
+
+		private var _applicationModel:ApplicationModel;
+		private var _mainView:MainView;
+
+		public function addLocale():void {
+			dispatchEvent(new LocaleEvent(LocaleEvent.NEW_LOCALE_REQUEST));
+		}
+
+		[Bindable(event="applicationModelChanged")]
+		public function get applicationModel():ApplicationModel {
+			return _applicationModel;
+		}
+
+		public function set applicationModel(value:ApplicationModel):void {
+			if (value !== _applicationModel) {
+				_applicationModel = value;
+				if (_applicationModel.localeData == null) {
+					_applicationModel.addEventListener("localeDataChanged", handleLocaleDataChange);
+				} else {
+					createLocaleViews(_applicationModel.localeData);
+				}
+				dispatchEvent(new Event("applicationModelChanged"));
+			}
+		}
+
+		public function handleNewLocale(event:LocaleEvent):void {
+			var view:LocaleView = createLocaleView(event.localeData);
+			_mainView.localesTab.selectedChild = view;
+			logger.info("Handled {0} event for locale '{1}'", [event.type, event.localeData.name]);
+		}
+
+		public function handleRemovedLocale(event:LocaleEvent):void {
+			var len:int = _mainView.localesTab.numChildren;
+			for (var i:int = 0; i < len; ++i) {
+				var view:LocaleView = _mainView.localesTab.getChildAt(i) as LocaleView;
+				if (view) {
+					if (view.localeData === event.localeData) {
+						_mainView.localesTab.removeChild(view);
+						logger.info("Handled {0} event, removed tab for locale '{1}'", [event.type, event.localeData.name]);
+						break;
+					}
+				}
+			}
+		}
+
+		public function initialize(view:MainView):void {
+			_mainView = view;
+			logger.info("MainViewPM initialized");
+		}
+
+		public function requestReferenceLocale(localeName:String):void {
+			dispatchEvent(new ReferenceLocaleRequestEvent(ReferenceLocaleRequestEvent.REFERENCE_LOCALE_REQUEST, localeName));
+		}
+
+		public function saveLocaleFile():void {
+			dispatchEvent(new LocaleFileEvent(LocaleFileEvent.FILE_SAVE_REQUEST));
+		}
+
+		public function showHelp():void {
+			dispatchEvent(new ShowHelpRequestEvent(ShowHelpRequestEvent.SHOW_HELP_REQUEST));
+		}
+
+		public function showLocaleFile():void {
+			dispatchEvent(new LocaleFileEvent(LocaleFileEvent.FILE_SHOW_REQUEST));
+		}
+
+		public function showLogFile():void {
+			dispatchEvent(new ShowLogFileRequestEvent(ShowLogFileRequestEvent.SHOW_LOG_FILE_REQUEST));
+		}
+
+		private function createLocaleView(localeData:LocaleDataVO):LocaleView {
+			var view:LocaleView = new LocaleView();
+			view.localeData = localeData;
+			view.percentHeight = 100;
+			view.percentWidth = 100;
+			_mainView.localesTab.addChild(view);
+			logger.info("Created tab for locale '{0}'", [localeData.name]);
+			return view;
+		}
+
+		private function createLocaleViews(localeDataCollection:Vector.<LocaleDataVO>):void {
+			for each (var localeData:LocaleDataVO in localeDataCollection) {
+				createLocaleView(localeData);
+			}
+		}
+
+		private function handleLocaleDataChange(event:Event):void {
+			if (_applicationModel.localeData != null) {
+				_applicationModel.removeEventListener("localeDataChanged", handleLocaleDataChange);
+				createLocaleViews(_applicationModel.localeData);
+			}
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/locale/LocaleDataVO.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/locale/LocaleDataVO.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/locale/LocaleDataVO.as
new file mode 100644
index 0000000..0911689
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/locale/LocaleDataVO.as
@@ -0,0 +1,141 @@
+package org.apache.flex.runtimelocale.model.locale {
+	import flash.events.Event;
+	import flash.events.EventDispatcher;
+	
+	import mx.collections.ArrayCollection;
+	
+	import org.as3commons.asblocks.dom.IASExpression;
+	import org.as3commons.asblocks.dom.IASStatement;
+	import org.as3commons.asblocks.impl.AS3FragmentParser;
+	import org.as3commons.asblocks.impl.ASTASArrayAccessExpression;
+	import org.as3commons.asblocks.impl.ASTASAssignmentExpression;
+	import org.as3commons.asblocks.impl.ASTASExpressionStatement;
+	import org.as3commons.asblocks.impl.ASTASMethod;
+	import org.as3commons.asblocks.impl.ASTASStringLiteral;
+	import org.as3commons.asblocks.impl.TokenBuilder;
+	import org.as3commons.asblocks.parser.antlr.LinkedListToken;
+	import org.as3commons.asblocks.parser.antlr.LinkedListTree;
+	import org.as3commons.collections.framework.IIterator;
+	import org.as3commons.collections.framework.IList;
+	import org.as3commons.lang.StringUtils;
+	import org.as3commons.logging.api.ILogger;
+	import org.as3commons.logging.api.getClassLogger;
+
+	public class LocaleDataVO extends EventDispatcher {
+
+		private static const logger:ILogger = getClassLogger(LocaleDataVO);
+
+		public function LocaleDataVO(method:ASTASMethod, name:String) {
+			super();
+			logger.info("Creating LocaleDataVO for locale '" + name + "'");
+			_method = method;
+			extractLocaleData(method);
+			_name = name;
+		}
+
+		private var _content:ArrayCollection;
+		private var _lookup:Object = {};
+		private var _method:ASTASMethod;
+		private var _missingKeys:ArrayCollection;
+		private var _name:String;
+
+		public function addKey(key:String):void {
+			if ((!StringUtils.hasText(key)) || (_lookup[key])) {
+				return;
+			}
+
+			logger.info("Adding translation key: {0}", [key]);
+			var code:String = 'content[' + key + ']="";';
+			logger.info("AS3 code snippet for translation key: {0}", [code]);
+
+			var newAST:LinkedListTree = AS3FragmentParser.parseExprStatement(code);
+			var statements:IList = _method.getStatements();
+
+			for (var i:int = 0; i < 3; ++i) {
+				var tab:LinkedListToken = TokenBuilder.newTab();
+				newAST.addToken(0, tab);
+			}
+			newAST.addToken(0, TokenBuilder.newNewline());
+
+			var methodAST:LinkedListTree = _method.getAST();
+			methodAST = methodAST.getChild(methodAST.childCount - 1) as LinkedListTree;
+			methodAST.addChildAtWithTokens(methodAST.childCount - 1, newAST);
+
+			var newStatement:ASTASExpressionStatement = new ASTASExpressionStatement(newAST);
+			var item:LocaleItemDataVO = addItem(newStatement);
+			_content.addItem(item);
+		}
+
+		public function get content():ArrayCollection {
+			return _content;
+		}
+
+		public function getItemByKey(key:String):LocaleItemDataVO {
+			return _lookup[key];
+		}
+
+		[Bindable(event="missingKeysChanged")]
+		public function get missingKeys():ArrayCollection {
+			return _missingKeys;
+		}
+
+		public function set missingKeys(value:ArrayCollection):void {
+			if (_missingKeys !== value) {
+				_missingKeys = value;
+				dispatchEvent(new Event("missingKeysChanged"));
+			}
+		}
+
+		public function get name():String {
+			return _name;
+		}
+
+		public function removeItem(item:LocaleItemDataVO):void {
+			removeStatement(item.statement);
+			var idx:int = _content.getItemIndex(item);
+			if (idx > -1) {
+				_content.removeItemAt(idx);
+				delete _lookup[item.key];
+				logger.info("Deleted translation key '{0}'", [item.key]);
+			}
+		}
+
+		public function removeStatement(statement:IASStatement):void {
+			var statements:IList = _method.getStatements();
+			statements.remove(statement);
+		}
+
+		private function addItem(expressionStatement:ASTASExpressionStatement):LocaleItemDataVO {
+			var asExpression:IASExpression = expressionStatement.getExpression();
+			var expression:ASTASAssignmentExpression = asExpression as ASTASAssignmentExpression;
+			if (expression != null) {
+				var leftExpression:ASTASArrayAccessExpression = expression.getLeftExpression() as ASTASArrayAccessExpression;
+				var rightExpression:ASTASStringLiteral = expression.getRightExpression() as ASTASStringLiteral;
+				if ((leftExpression != null) && (rightExpression != null)) {
+					var item:LocaleItemDataVO = new LocaleItemDataVO(leftExpression, rightExpression, expressionStatement);
+					_lookup[leftExpression.getSubscript().toString()] = item;
+					return item;
+				}
+			}
+			return null;
+		}
+
+		private function extractLocaleData(method:ASTASMethod):void {
+			logger.info("Extracting translation keys from the AST");
+			var statements:IList = method.getStatements();
+			var iterator:IIterator = statements.iterator();
+			var result:Array = [];
+			while (iterator.hasNext()) {
+				var statement:IASStatement = iterator.next();
+				if (statement is ASTASExpressionStatement) {
+					var item:LocaleItemDataVO = addItem(statement as ASTASExpressionStatement);
+					if (item) {
+						result[result.length] = item;
+						logger.info("Extracted translation from code snippet '" + statement.toString() + "'");
+					}
+				}
+			}
+			_content = new ArrayCollection(result);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/locale/LocaleItemDataVO.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/locale/LocaleItemDataVO.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/locale/LocaleItemDataVO.as
new file mode 100644
index 0000000..b1a88e0
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/model/locale/LocaleItemDataVO.as
@@ -0,0 +1,45 @@
+package org.apache.flex.runtimelocale.model.locale {
+	import flash.events.Event;
+	import flash.events.EventDispatcher;
+	import org.as3commons.asblocks.impl.ASTASArrayAccessExpression;
+	import org.as3commons.asblocks.impl.ASTASExpressionStatement;
+	import org.as3commons.asblocks.impl.ASTASStringLiteral;
+
+	public class LocaleItemDataVO extends EventDispatcher {
+
+		public function LocaleItemDataVO(left:ASTASArrayAccessExpression, right:ASTASStringLiteral, statement:ASTASExpressionStatement=null) {
+			super();
+			_left = left;
+			_right = right;
+			_statement = statement;
+		}
+
+		private var _left:ASTASArrayAccessExpression;
+		private var _right:ASTASStringLiteral;
+		private var _statement:ASTASExpressionStatement;
+
+		public function get key():String {
+			return (_left) ? _left.getSubscript().toString() : "";
+		}
+
+		public function get statement():ASTASExpressionStatement {
+			return _statement;
+		}
+
+		public function set statement(value:ASTASExpressionStatement):void {
+			_statement = value;
+		}
+
+		public function get value():String {
+			return ((_right) && (_right.getAST())) ? _right.getValue() : "";
+		}
+
+		[Bindable(event="valueChanged")]
+		public function set value(val:String):void {
+			if ((val != value) && (_right)) {
+				_right.setValue(val);
+				dispatchEvent(new Event("valueChanged"));
+			}
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/HelpView.mxml
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/HelpView.mxml b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/HelpView.mxml
new file mode 100644
index 0000000..2f23981
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/HelpView.mxml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<s:TitleWindow xmlns:fx="http://ns.adobe.com/mxml/2009"
+			   xmlns:s="library://ns.adobe.com/flex/spark"
+			   xmlns:mx="library://ns.adobe.com/flex/mx"
+			   width="800"
+			   height="600"
+			   name="helpView"
+			   title="Introductory help text"
+			   implements="org.apache.flex.runtimelocale.view.IInjectableView"
+			   close="titlewindow1_closeHandler(event)"
+			   creationComplete="titlewindow1_creationCompleteHandler(event)">
+	<fx:Script>
+		<![CDATA[
+			import mx.events.CloseEvent;
+			import mx.events.FlexEvent;
+			import mx.managers.PopUpManager;
+			import org.apache.flex.runtimelocale.model.ApplicationModel;
+			import org.as3commons.logging.api.ILogger;
+			import org.as3commons.logging.api.getClassLogger;
+
+			private static const logger:ILogger = getClassLogger(HelpView);
+
+			private var _applicationModel:ApplicationModel;
+
+			public function get applicationModel():ApplicationModel {
+				return _applicationModel;
+			}
+
+			public function set applicationModel(value:ApplicationModel):void {
+				if (value !== _applicationModel) {
+					_applicationModel = value;
+					if (_applicationModel) {
+						var showHelp:String = _applicationModel.configurationProperties['showhelp'];
+						alwaysShowHelp.selected = (showHelp.toLowerCase() == "true");
+					}
+				}
+			}
+
+			protected function alwaysShowHelp_changeHandler(event:Event):void {
+				_applicationModel.configurationProperties['showhelp'] = (alwaysShowHelp.selected) ? "true" : false;
+			}
+
+			protected function titlewindow1_closeHandler(event:CloseEvent):void {
+				PopUpManager.removePopUp(this);
+			}
+
+			protected function titlewindow1_creationCompleteHandler(event:FlexEvent):void {
+				var helpFile:File = File.applicationDirectory.resolvePath("helptext.txt");
+				if (helpFile.exists) {
+					try {
+						var fileStream:FileStream = new FileStream();
+						fileStream.open(helpFile, FileMode.READ);
+						fileStream.position = 0;
+						helpText.text = fileStream.readMultiByte(fileStream.bytesAvailable, "utf-8");
+					} catch (e:Error) {
+						logger.error("Error encountered while reading log file '{0}': {0}", [helpFile, e.message]);
+					} finally {
+						fileStream.close();
+						logger.info("Successfully loaded logfile: {0}", [helpFile.nativePath]);
+					}
+				}
+
+			}
+		]]>
+	</fx:Script>
+	<s:layout>
+		<s:VerticalLayout/>
+	</s:layout>
+	<fx:Declarations>
+		<!-- Place non-visual elements (e.g., services, value objects) here -->
+	</fx:Declarations>
+	<s:TextArea width="100%"
+				height="100%"
+				id="helpText"
+				editable="false"
+				selectable="true">
+	</s:TextArea>
+	<s:CheckBox id="alwaysShowHelp"
+				change="alwaysShowHelp_changeHandler(event)"
+				label="Always show this screen at application startup"/>
+</s:TitleWindow>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/IInjectableView.as
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/IInjectableView.as b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/IInjectableView.as
new file mode 100644
index 0000000..dfa1c1d
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/IInjectableView.as
@@ -0,0 +1,6 @@
+package org.apache.flex.runtimelocale.view {
+
+	public interface IInjectableView {
+
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/LocaleFileSelectorView.mxml
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/LocaleFileSelectorView.mxml b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/LocaleFileSelectorView.mxml
new file mode 100644
index 0000000..7aa3783
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/LocaleFileSelectorView.mxml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<s:TitleWindow xmlns:fx="http://ns.adobe.com/mxml/2009"
+			   xmlns:s="library://ns.adobe.com/flex/spark"
+			   xmlns:mx="library://ns.adobe.com/flex/mx"
+			   width="400"
+			   height="80"
+			   name="selectorView"
+			   implements="org.apache.flex.runtimelocale.view.IInjectableView"
+			   title="Select the RuntimeLocale.as file you want to edit">
+	<s:layout>
+		<s:VerticalLayout/>
+	</s:layout>
+
+	<fx:Script>
+		<![CDATA[
+			import mx.managers.PopUpManager;
+			import org.apache.flex.runtimelocale.model.LocaleFileSelectorPM;
+			import org.as3commons.logging.api.ILogger;
+			import org.as3commons.logging.api.getClassLogger;
+
+			private static const logger:ILogger = getClassLogger(LocaleFileSelectorView);
+
+			[Bindable]
+			public var presentationModel:LocaleFileSelectorPM;
+
+			protected function fileBrowser_clickHandler(event:MouseEvent):void {
+				presentationModel.browseFile();
+			}
+
+			protected function fileLoader_clickHandler(event:MouseEvent):void {
+				presentationModel.loadFile(localeFileLocation.text);
+				logger.info("Removing LocaleFileSelectorView popup");
+				PopUpManager.removePopUp(this);
+			}
+		]]>
+	</fx:Script>
+
+	<fx:Declarations>
+		<!-- Place non-visual elements (e.g., services, value objects) here -->
+	</fx:Declarations>
+	<s:HGroup width="380"
+			  height="100%"
+			  verticalAlign="middle"
+			  paddingLeft="15">
+		<s:TextInput id="localeFileLocation"
+					 width="100%"
+					 text="{presentationModel.selectedFile}"/>
+		<s:Button id="fileBrowser"
+				  label="Browse..."
+				  click="fileBrowser_clickHandler(event)"/>
+		<s:Button id="fileLoader"
+				  label="Load"
+				  click="fileLoader_clickHandler(event)"
+				  enabled="{localeFileLocation.text.length&gt;0}"/>
+	</s:HGroup>
+</s:TitleWindow>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/LocaleView.mxml
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/LocaleView.mxml b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/LocaleView.mxml
new file mode 100644
index 0000000..229473b
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/LocaleView.mxml
@@ -0,0 +1,205 @@
+<?xml version="1.0" encoding="utf-8"?>
+<s:NavigatorContent xmlns:fx="http://ns.adobe.com/mxml/2009"
+					xmlns:s="library://ns.adobe.com/flex/spark"
+					xmlns:mx="library://ns.adobe.com/flex/mx"
+					label="{localeData.name}"
+					implements="org.apache.flex.runtimelocale.view.IInjectableView"
+					name="localeView">
+	<fx:Script>
+		<![CDATA[
+			import mx.collections.ListCollectionView;
+			import mx.controls.Alert;
+			import mx.events.CloseEvent;
+			import mx.events.FlexEvent;
+			import mx.utils.ObjectUtil;
+			import org.apache.flex.runtimelocale.event.LocaleDataEvent;
+			import org.apache.flex.runtimelocale.event.LocaleEvent;
+			import org.apache.flex.runtimelocale.event.LocaleItemEvent;
+			import org.apache.flex.runtimelocale.model.locale.LocaleDataVO;
+			import org.apache.flex.runtimelocale.model.locale.LocaleItemDataVO;
+			import org.apache.flex.runtimelocale.view.itemrenderer.LocaleItemView;
+			import spark.collections.Sort;
+			import spark.collections.SortField;
+			import spark.events.IndexChangeEvent;
+			import spark.events.RendererExistenceEvent;
+			import spark.events.TextOperationEvent;
+
+			private var _localeData:LocaleDataVO;
+			private var _localeDataContent:ListCollectionView;
+			private var _nameSortField:SortField;
+
+			[Bindable(event="localeDataChanged")]
+			public function get localeData():LocaleDataVO {
+				return _localeData;
+			}
+
+			public function set localeData(value:LocaleDataVO):void {
+				if (_localeData !== value) {
+					_localeData = value;
+					if (_localeData) {
+						_localeDataContent = new ListCollectionView(_localeData.content);
+						_localeDataContent.sort = new Sort();
+						_localeDataContent.sort.compareFunction = sortKeys;
+						_localeDataContent.refresh();
+						if (localeItems) {
+							localeItems.dataProvider = _localeDataContent;
+						}
+					}
+					dispatchEvent(new Event("localeDataChanged"));
+				}
+			}
+
+			private function addLocaleKeyButton_clickHandler(event:MouseEvent):void {
+				var newKey:String = '"' + newLocaleKey.text + '"';
+				if (!localeData.getItemByKey(newKey)) {
+					dispatchEvent(new LocaleItemEvent(LocaleItemEvent.NEW_LOCALE_ITEM_REQUEST, newKey, localeData));
+					newLocaleKey.text = "";
+				} else {
+					var closeHandler:Function = function(closeEvent:CloseEvent):void {
+						newLocaleKey.selectAll();
+						newLocaleKey.setFocus();
+					}
+					Alert.show("The locale '" + localeData.name + "' already contains a key named " + newKey + ".", "Attention", 4, null, closeHandler);
+				}
+			}
+
+			private function buttonAddMissing_clickHandler(event:MouseEvent):void {
+				dispatchEvent(new LocaleDataEvent(LocaleDataEvent.REQUEST_ADD_MISSING_KEYS, localeData));
+			}
+
+			private function datagroup1_rendererAddHandler(event:RendererExistenceEvent):void {
+				if (event.renderer) {
+					event.renderer.addEventListener(LocaleItemEvent.REMOVE_LOCALE_ITEM_REQUEST, handleItemRemoveRequest);
+				}
+			}
+
+			private function datagroup1_rendererRemoveHandler(event:RendererExistenceEvent):void {
+				if (event.renderer) {
+					event.renderer.removeEventListener(LocaleItemEvent.REMOVE_LOCALE_ITEM_REQUEST, handleItemRemoveRequest);
+				}
+			}
+
+			private function deleteLocaleButton_clickHandler(event:MouseEvent):void {
+				dispatchEvent(new LocaleEvent(LocaleEvent.REMOVE_LOCALE_REQUEST, null, localeData));
+			}
+
+			private function handleItemRemoveRequest(event:LocaleItemEvent):void {
+				event.localeData = localeData;
+				dispatchEvent(event);
+			}
+
+			private function localeItems_creationCompleteHandler(event:FlexEvent):void {
+				localeItems.dataProvider = _localeDataContent;
+			}
+
+			private function newLocaleKey_changeHandler(event:TextOperationEvent):void {
+				newLocaleKey.text = newLocaleKey.text.toUpperCase();
+			}
+
+			private function sortEmptyTranslation(a:LocaleItemDataVO, b:LocaleItemDataVO, fields:Array=null):int {
+				if ((!a.value) && (b.value)) {
+					return -1;
+				} else if ((a.value) && (!b.value)) {
+					return 1;
+				} else if ((!a.value) && (!b.value)) {
+					return 0;
+				} else {
+					return sortKeys(a, b);
+				}
+			}
+
+			private function sortKeys(a:LocaleItemDataVO, b:LocaleItemDataVO, fields:Array=null):int {
+				return ObjectUtil.stringCompare(a.key, b.key);
+			}
+
+			private function sortingOptions_changeHandler(event:IndexChangeEvent):void {
+				if (_localeDataContent) {
+					if (sortingOptions.selectedIndex == 0) {
+						_localeDataContent.sort.compareFunction = sortKeys;
+					} else {
+						_localeDataContent.sort.compareFunction = sortEmptyTranslation;
+					}
+					_localeDataContent.refresh();
+				}
+			}
+			//
+			{
+				LocaleItemView;
+			}
+		]]>
+	</fx:Script>
+	<s:layout>
+		<s:VerticalLayout/>
+	</s:layout>
+	<fx:Declarations>
+		<!-- Place non-visual elements (e.g., services, value objects) here -->
+	</fx:Declarations>
+	<s:HGroup verticalAlign="middle"
+			  height="30"
+			  paddingLeft="10"
+			  paddingRight="10"
+			  width="100%">
+		<s:Label text="This locale is missing {localeData.missingKeys.length} translations"
+				 visible="{localeData.missingKeys &amp;&amp; localeData.missingKeys.length &gt; 0}"
+				 includeInLayout="{localeData.missingKeys &amp;&amp; localeData.missingKeys.length &gt; 0}"
+				 color="0xff0000"
+				 toolTip="Compared to the reference locale this locale is missing translation keys, press the button next to this label to automatically add these keys."/>
+		<s:Button id="buttonAddMissing"
+				  label="Add missing keys"
+				  visible="{localeData.missingKeys &amp;&amp; localeData.missingKeys.length &gt; 0}"
+				  includeInLayout="{localeData.missingKeys &amp;&amp; localeData.missingKeys.length &gt; 0}"
+				  click="buttonAddMissing_clickHandler(event)"
+				  toolTip="Adds all they missing translation keys as compared to the reference locale"/>
+		<s:Spacer width="50"
+				  includeInLayout="{localeData.missingKeys &amp;&amp; localeData.missingKeys.length &gt; 0}"/>
+		<s:TextInput id="newLocaleKey"
+					 width="250"
+					 change="newLocaleKey_changeHandler(event)"
+					 toolTip="Define a new translation key, the key will be automatically uppercased"/>
+		<s:Button id="addLocaleKeyButton"
+				  label="Add new key"
+				  enabled="{newLocaleKey.text.length &gt; 0}"
+				  click="addLocaleKeyButton_clickHandler(event)"
+				  toolTip="Adds a new translation key, if you are editing the current reference locale you will be prompted to add the same key to all the other locales automatically as well."/>
+		<s:Spacer width="25"/>
+		<s:Label text="Sorting:"/>
+		<s:ComboBox id="sortingOptions"
+					selectedIndex="0"
+					change="sortingOptions_changeHandler(event)"
+					width="200">
+			<s:dataProvider>
+				<s:ArrayList>
+					<fx:String>Sort by keys</fx:String>
+					<fx:String>Sort empty translations on top</fx:String>
+				</s:ArrayList>
+			</s:dataProvider>
+		</s:ComboBox>
+		<s:Spacer width="100%"/>
+		<s:Button id="deleteLocaleButton"
+				  label="Remove locale"
+				  click="deleteLocaleButton_clickHandler(event)"
+				  toolTip="Removes the entire locale from the AS3 output"/>
+		<s:Label text="Total number of translations for locale '{localeData.name}': {localeData.content.length}"/>
+	</s:HGroup>
+	<s:Line width="100%">
+		<s:stroke>
+			<s:SolidColorStroke color="0x000000"
+								weight="1"
+								caps="none"/>
+		</s:stroke>
+	</s:Line>
+	<s:Scroller width="100%"
+				height="100%">
+		<s:DataGroup itemRenderer="{new ClassFactory(LocaleItemView)}"
+					 width="100%"
+					 id="localeItems"
+					 clipAndEnableScrolling="true"
+					 rendererAdd="datagroup1_rendererAddHandler(event)"
+					 rendererRemove="datagroup1_rendererRemoveHandler(event)"
+					 creationComplete="localeItems_creationCompleteHandler(event)">
+			<s:layout>
+				<s:VerticalLayout useVirtualLayout="true"/>
+			</s:layout>
+		</s:DataGroup>
+	</s:Scroller>
+</s:NavigatorContent>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/MainView.mxml
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/MainView.mxml b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/MainView.mxml
new file mode 100644
index 0000000..81770c4
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/MainView.mxml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
+		 xmlns:s="library://ns.adobe.com/flex/spark"
+		 xmlns:mx="library://ns.adobe.com/flex/mx"
+		 implements="org.apache.flex.runtimelocale.view.IInjectableView"
+		 name="mainView">
+	<s:layout>
+		<s:VerticalLayout/>
+	</s:layout>
+	<fx:Script>
+		<![CDATA[
+			import org.apache.flex.runtimelocale.model.MainViewPM;
+			import spark.events.IndexChangeEvent;
+
+			private var _presentationModel:MainViewPM;
+
+			[Bindable(event="presentationModelChanged")]
+			public function get presentationModel():MainViewPM {
+				return _presentationModel;
+			}
+
+			public function set presentationModel(value:MainViewPM):void {
+				if (_presentationModel !== value) {
+					_presentationModel = value;
+					if (_presentationModel) {
+						_presentationModel.initialize(this);
+					}
+					dispatchEvent(new Event("presentationModelChanged"));
+				}
+			}
+
+			protected function addLocaleButton_clickHandler(event:MouseEvent):void {
+				presentationModel.addLocale();
+			}
+
+			protected function helpButton_clickHandler(event:MouseEvent):void {
+				presentationModel.showHelp();
+			}
+
+			protected function referenceLocale_changeHandler(event:IndexChangeEvent):void {
+				presentationModel.requestReferenceLocale(referenceLocale.selectedItem);
+			}
+
+			protected function saveButton_clickHandler(event:MouseEvent):void {
+				presentationModel.saveLocaleFile();
+			}
+
+			protected function showAS3Code_clickHandler(event:MouseEvent):void {
+				presentationModel.showLocaleFile();
+			}
+
+			protected function showLogFile_clickHandler(event:MouseEvent):void {
+				presentationModel.showLogFile();
+			}
+		]]>
+	</fx:Script>
+	<fx:Declarations>
+		<!-- Place non-visual elements (e.g., services, value objects) here -->
+	</fx:Declarations>
+	<s:HGroup verticalAlign="middle"
+			  height="35"
+			  width="100%"
+			  paddingLeft="15"
+			  paddingRight="15">
+		<s:Label text="Reference locale:"/>
+		<s:ComboBox width="75"
+					id="referenceLocale"
+					dataProvider="{presentationModel.applicationModel.availableLocales}"
+					change="referenceLocale_changeHandler(event)"
+					selectedItem="en_US"
+					toolTip="The reference locale is used to define the reference set of translation keys to which all the other locales are compared"/>
+		<s:Button id="addLocaleButton"
+				  label="Add locale"
+				  click="addLocaleButton_clickHandler(event)"
+				  toolTip="Show a dialog with which a new locale can be defined"/>
+		<s:Spacer width="100%"/>
+		<s:Button id="showAS3Code"
+				  label="View AS3 output"
+				  click="showAS3Code_clickHandler(event)"
+				  toolTip="Shows a popup that displays the exact Actionscript output for all the locales. I.e. the contents of the RuntimeLocale.as file."/>
+		<s:Button id="saveButton"
+				  label="Save locale file"
+				  click="saveButton_clickHandler(event)"
+				  toolTip="Saves the RuntimeLocale.as file to disk containing all the changes made using the current application"/>
+		<s:Button id="helpButton"
+				  label="Show help"
+				  click="helpButton_clickHandler(event)"
+				  toolTip="Shows the introductory help screen"/>
+		<s:Spacer width="20"/>
+		<s:Button id="showLogFile"
+				  label="View logfile (debug)"
+				  click="showLogFile_clickHandler(event)"
+				  toolTip="Shows the contents of the logfile, mainly for debugging purposes"/>
+	</s:HGroup>
+	<mx:TabNavigator id="localesTab"
+					 width="100%"
+					 height="100%"/>
+</s:Group>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/NewLocaleView.mxml
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/NewLocaleView.mxml b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/NewLocaleView.mxml
new file mode 100644
index 0000000..32e5fde
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/NewLocaleView.mxml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<s:TitleWindow xmlns:fx="http://ns.adobe.com/mxml/2009"
+			   xmlns:s="library://ns.adobe.com/flex/spark"
+			   xmlns:mx="library://ns.adobe.com/flex/mx"
+			   width="400"
+			   height="80"
+			   implements="org.apache.flex.runtimelocale.view.IInjectableView"
+			   name="newLocaleView"
+			   title="Enter new locale name"
+			   close="titlewindow1_closeHandler(event)"
+			   defaultButton="{addNewLocaleButton}"
+			   creationComplete="titlewindow1_creationCompleteHandler(event)">
+	<s:layout>
+		<s:VerticalLayout/>
+	</s:layout>
+
+	<fx:Script>
+		<![CDATA[
+			import mx.events.CloseEvent;
+			import mx.events.FlexEvent;
+			import mx.managers.PopUpManager;
+			import org.apache.flex.runtimelocale.event.LocaleEvent;
+			import spark.events.TextOperationEvent;
+
+			protected function addNewLocaleButton_clickHandler(event:MouseEvent):void {
+				var locale:String = localeNameLeft.text + '_' + localeNameRight.text;
+				var localeEvent:LocaleEvent = new LocaleEvent(LocaleEvent.CREATE_LOCALE_REQUEST, locale);
+				dispatchEvent(localeEvent);
+				if (!localeEvent.isDefaultPrevented()) {
+					closeWindow();
+				} else {
+					localeNameLeft.selectAll();
+				}
+			}
+
+			protected function localeNameLeft_changeHandler(event:TextOperationEvent):void {
+				localeNameLeft.text = localeNameLeft.text.toLowerCase();
+				if (localeNameLeft.text.length == 2) {
+					localeNameRight.setFocus();
+				}
+			}
+
+			protected function localeNameRight_changeHandler(event:TextOperationEvent):void {
+				localeNameRight.text = localeNameRight.text.toUpperCase();
+				if (localeNameRight.text.length == 2) {
+					addNewLocaleButton.setFocus();
+				}
+			}
+
+			protected function titlewindow1_closeHandler(event:CloseEvent):void {
+				closeWindow();
+			}
+
+			protected function titlewindow1_creationCompleteHandler(event:FlexEvent):void {
+				localeNameLeft.setFocus();
+			}
+
+			private function closeWindow():void {
+				PopUpManager.removePopUp(this);
+			}
+		]]>
+	</fx:Script>
+
+	<fx:Declarations>
+		<!-- Place non-visual elements (e.g., services, value objects) here -->
+	</fx:Declarations>
+	<s:HGroup width="380"
+			  height="100%"
+			  verticalAlign="middle"
+			  paddingLeft="15">
+		<s:TextInput id="localeNameLeft"
+					 width="25"
+					 maxChars="2"
+					 change="localeNameLeft_changeHandler(event)"/>
+		<s:Label text="_"/>
+		<s:TextInput id="localeNameRight"
+					 width="25"
+					 maxChars="2"
+					 change="localeNameRight_changeHandler(event)"/>
+		<s:Button id="addNewLocaleButton"
+				  label="Add"
+				  click="addNewLocaleButton_clickHandler(event)"
+				  enabled="{((localeNameLeft.text.length + localeNameRight.text.length) == 4)}"/>
+	</s:HGroup>
+</s:TitleWindow>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/bd17e63e/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/TextFileContentView.mxml
----------------------------------------------------------------------
diff --git a/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/TextFileContentView.mxml b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/TextFileContentView.mxml
new file mode 100644
index 0000000..cf3f954
--- /dev/null
+++ b/flex-installer/installerLocaleEditor/src/org/apache/flex/runtimelocale/view/TextFileContentView.mxml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<s:TitleWindow xmlns:fx="http://ns.adobe.com/mxml/2009"
+			   xmlns:s="library://ns.adobe.com/flex/spark"
+			   xmlns:mx="library://ns.adobe.com/flex/mx"
+			   width="1200"
+			   height="800"
+			   title="Showing file: {filePath}"
+			   close="titlewindow1_closeHandler(event)">
+	<fx:Script>
+		<![CDATA[
+			import mx.events.CloseEvent;
+			import mx.managers.PopUpManager;
+			import org.as3commons.logging.api.ILogger;
+			import org.as3commons.logging.api.getClassLogger;
+
+			private static const logger:ILogger = getClassLogger(TextFileContentView);
+
+			private var _fileContent:String;
+			private var _filePath:String;
+
+			[Bindable(event="fileContentChanged")]
+			public function get fileContent():String {
+				return _fileContent;
+			}
+
+			public function set fileContent(value:String):void {
+				if (_fileContent !== value) {
+					_fileContent = value;
+					dispatchEvent(new Event("fileContentChanged"));
+				}
+			}
+
+			[Bindable(event="filePathChanged")]
+			public function get filePath():String {
+				return _filePath;
+			}
+
+			public function set filePath(value:String):void {
+				if (_filePath !== value) {
+					_filePath = value;
+					dispatchEvent(new Event("filePathChanged"));
+				}
+			}
+
+			protected function titlewindow1_closeHandler(event:CloseEvent):void {
+				logger.info("Removing TextFileContentView popup");
+				PopUpManager.removePopUp(this);
+			}
+		]]>
+	</fx:Script>
+	<s:layout>
+		<s:VerticalLayout/>
+	</s:layout>
+	<fx:Declarations>
+		<!-- Place non-visual elements (e.g., services, value objects) here -->
+	</fx:Declarations>
+	<s:TextArea width="100%"
+				height="100%"
+				text="{fileContent}"/>
+</s:TitleWindow>


Mime
View raw message