Howto use vnkeys with TextField

vnkeys is originally designed to work with flash.text.TextField and you can feel it when typing. The replacement happens smoothly. It is easy to use and the code bellow will explain how to…

package {
	import flash.display.Sprite;
	import flash.text.TextField;
	import flash.text.TextFieldType;
 
	import org.vnmedia.vnkeys.KeyConverter;
	import org.vnmedia.vnkeys.mapping.VNIMap;
	// define swf dimension
	[SWF(width=160, height=60)]
	// this is an application class
	public class vnmedia_vnkeys extends Sprite
	{
		public function vnmedia_vnkeys()
		{
			var textinput:TextField = new TextField();
			// give this text input a size
			// and positioning it
			textinput.width = 150;
			textinput.height = 50;
			textinput.x = 5;
			textinput.y = 5;
			// use multiline, ie textarea
			textinput.multiline = true;
			textinput.type = TextFieldType.INPUT;
			// give it background white
			// so we can see what we are typing
			textinput.backgroundColor = 0xFFFFFF;
			textinput.background = true;
			// NOW create a converter
			// for this TextField instance
			var converter:KeyConverter =
				new KeyConverter(textinput,VNIMap.NAME);
			// add this text input to application
			this.addChild(textinput);
		}
	}
}

The result:

Type using VNI input method

How to bootstrap, autoload modules and classes with Zend framework

This post is for you that have read this quick start from Zend and our goal is to create a bootstrap like this one. We assume that you know how to create a project, layout, module, controller and action by using zf.bat, zf.sh or manually and further that you are able to create a helloworld application with structure as bellow (I used zf.bat)

application
   configs
      application.ini
   layouts
      scripts
         layout.phtml
   modules
      default
         controllers
            ErrorController.php
            HelloworldController.php
            IndexController.php
         forms
            HelloWorld.php
         models
         views
            filters
            helpers
            scripts
              error
                 error.phtml
              helloworld
                 hello.phtml
              index
                 index.phtml
      second
         controllers
            HelloworldController.php
            IndexController.php
         forms
            HelloWorld.php
         models
         views
            filters
            helpers
            scripts
              helloworld
                 hello.phtml
              index
                 index.phtml
   Bootstrap.php
library
   Zend
   Foo
     Bar.php
public
   index.php
tests

We have now created two modules “default” and “second”. So far I can not create a project with default module inside folder modules so you need to move controllers, forms, models, views into default (create it first). However, the main purpose here is to show how to alter the Bootstrap that generated by zf.bat so that modules will be loaded and classes within modules, such as forms, models, can be autoloaded. In this example we will test for the form HelloWorld which is loaded in controller Helloworld. Here is the content of those files

default/controllers/HelloworldController.php

<?php
 
class HelloworldController extends Zend_Controller_Action
{
 
    public function init()
    {
        /* Initialize action controller here */
    }
 
    public function indexAction()
    {
        // action body
    }
 
    public function helloAction()
    {
        $request = $this->getRequest(); 
        $form = new Default_Form_HelloWorld();
        if ($request->isPost()) {
        	print $request->getParam('hello');
        }
        $this->view->form = $form;
    }
}
?>

default/forms/HellowWorld.php

<?php
class Default_Form_HelloWorld extends Zend_Form
{
	public function init()
	{
		$this->setMethod('post');
		$this->addElement('text', 'hello', array(
            'label'      => 'Hello default:',
            'required'   => true,
            'filters'    => array('StringTrim')
		));
		$this->addElement('submit', 'submit', array(
            'ignore'   => true,
            'label'    => 'Say',
		));
 
	}
}
?>

second/controllers/HelloworldController.php

<?php
class Second_HelloworldController extends Zend_Controller_Action
{
 
    public function init()
    {
        /* Initialize action controller here */
    }
 
    public function indexAction()
    {
        // action body
    }
 
    public function helloAction()
    {
        $request = $this->getRequest();
        $form    = new Second_Form_HelloWorld();
        if ($request->isPost()) {
        	print $request->getParam('hello');
        }
        $this->view->form = $form;
    }
}
?>

second/forms/HelloWorld.php

<?php
class Second_Form_HelloWorld extends Zend_Form
{
    public function init()
    {
        $this->setMethod('post');
        $this->addElement('text', 'hello', array(
            'label'      => 'Hello second:',
            'required'   => true,
            'filters'    => array('StringTrim')
        ));
        $this->addElement('submit', 'submit', array(
            'ignore'   => true,
            'label'    => 'Say',
		));
    }
}
?>

default/views/scripts/helloworld/hello.phtml
second/views/scripts/helloworld/hello.phtml

<?php 
$this->form->setAction($this->url());
echo $this->form;
?>

The first step we will try to do is to make sure that we can load the modules. We start to alter Bootstrap.php What we need to do is telling Front Controller where our modules are located

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
	protected function _initDoctype()
	{
	}
 
	protected function _initApplication()
	{
		$this->bootstrap('FrontController');
		$front = $this->getResource('FrontController');
		$front->throwExceptions(false);
		$front->addModuleDirectory(APPLICATION_PATH . '/modules');
	}
}
 
?>

Be aware that this can also be done in bootstrap file (public/index.php). One can do that by adding follow

$frontController = Zend_Controller_Front::getInstance();
$frontController->addModuleDirectory(APPLICATION_PATH . '/modules');

Or add this line in application.ini that is generated by zf.bat

resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"

Now you should be able to navigate to http://yourserver/helloworld/hello or http://yourserver/second/helloworld/hello without any complain about “missing default module in front controller”. We got instead a fatal error which says that our form classes Default_Form_HelloWorld/Second_Form_HelloWorld is not found. The next is to enable autoloading of those form classes. To do that we start to edit Bootstrap.php again by adding init method _initAutoload() which will be called automatically

<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
 
	protected function _initDoctype()
	{
	}
 
	protected function _initApplication()
	{
		$this->bootstrap('FrontController');
		$front = $this->getResource('FrontController');
		$front->throwExceptions(false);
		$front->addModuleDirectory(APPLICATION_PATH . '/modules');
	}
 
	protected function _initAutoload()
	{
		// BLOCK 1
		// this is a fallback to autoload our own classes in library
		$autoLoader = Zend_Loader_Autoloader::getInstance();
		$autoLoader->setFallbackAutoloader(true);
 
		// BLOCK 2
		// this is for loading forms classes in default module
		$autoloader = new Zend_Application_Module_Autoloader(array(
        		'namespace' => 'Default_',
            		'basePath'  => APPLICATION_PATH . '/modules/default',
        		'resourceTypes' => array(
                		'forms'=>array('path'=>'/forms',
					'namespace'=>'Form')
				)
			)
		);
 
		// BLOCK 3
		// this is for loading form classes in second module
		$autoloader = new Zend_Application_Module_Autoloader(array(
        		'namespace' => 'Second_',
          		'basePath'  => APPLICATION_PATH . '/modules/second',
        		'resourceTypes' => array(
                 		'forms'=>array('path'=>'/forms',
					'namespace'=>'Form')
				)
			)
		);
	}
}
?>

BLOCK 1:
By default Zend_Loader_Autoloader will only load Zend classes. This code block tells Zend_Loader_Autoloader to include class files in arbitrary libraries. For instance, when you create a new “Bar”

$bar = new Foo_Bar();

It will try to include the file by looking in includepath/Foo/Bar.php and in our case it will include the file Foo/Bar.php

BLOCK 2 & 3:
Since Zend_Loader_Autoloader replaces _ in classname with / when loading the class file. But this will not work for classes in module folder. In these two code blocks we register the namespace and the corresponding path, ie if a class start with Second_ then it should look for the class file in application/modules/second/. When loading the form, in our case, it will add basePath and path, ie it will look for the class file in applicaton/modules/second/forms/.

Be aware that the namespace for your classes in forms and classes in library should distinct, for instance if I create a Foo class for module second in my library I should start with application name (helloworld) Helloworld_Second_Foo instead of Second_Foo which has the start namespace for the form, ie start-namespace conflict. I hope that this is the answer you are looking for …

How to install a .deb file

To install package called package.deb type the following command (make sure that all dependencies are installed)

sudo dpkg -i /path/to/folder/package.deb

How to provide users options to switch on/off when using vnkeys

The goal of this post is to show how we can create a radio button group so users can switch on and off when using vnkeys as the swf above. To create TextArea and TextInput we use input components that follows vnkeys (see this how to for details). Bellow is our code example where we use flex RadioButtonGroup and RadioButton to create on/off options. We use Repeater to loop through options that we get from KeyConverter.getKeyMapOptions() This is done by calling init function initOptions() which fills element “options” with an array of available mapping types. On each option we attach function onMappingTypeChange as listener for onchange event so we can update mapping type on each KeyConverter instance.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
	layout="absolute"
	 xmlns:flex="org.vnmedia.flex.*" 
	 creationComplete="initOptions();">
	<mx:Script>
		<![CDATA[
		import mx.controls.RadioButton;
		public function initOptions():void {
			options = area.getKeyConverter()
						.getKeyMapOptions();
		}
		public function onMappingTypeChange(e:Event):void {
			var radio:RadioButton = RadioButton(e.currentTarget);
			var item:Object = radio.getRepeaterItem();
			text.getKeyConverter().setMapType(item.data);
			area.getKeyConverter().setMapType(item.data);
		}
		]]>
	</mx:Script>
	<flex:FlexTextArea id="area" vnkeyType="VNI" 
		height="50" width="220" x="50" y="50">
	</flex:FlexTextArea>
	<flex:FlexTextInput id="text" y="120"
		 x="50" width="220">
	</flex:FlexTextInput>
	<mx:Array id="options"/>
   	<mx:HBox id="hb" x="50" y="150">	
        <mx:RadioButtonGroup id="radioGroup" />
        <mx:Repeater id="radioRepeater"
                dataProvider="{options}">
            <mx:RadioButton id="radioButtons"
                    label="{radioRepeater.currentItem.label}"
                    group="{radioGroup}"
                    change="onMappingTypeChange(event);" />
        </mx:Repeater>
    </mx:HBox>
</mx:Application>

how to use vnkeys with flex

In the package org.vnmedia.flex we find two subclasses of Flex controls class. FlexTextInput is extending TextInput and FlexTextArea extending TextArea. Those two inherit all functionalities from their parent. We just added some more code handling the typing since TextInput and TextArea behaves unlike TextField. It is simple to use. You just need to declare namespace for org.vnmedia.flex, I call it “flex” in example bellow.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
	xmlns:flex="org.vnmedia.flex.*"
	layout="absolute">
	<flex:FlexTextArea id="area" vnkeyType="VNI" 
		height="50" width="220" x="50" y="50">
	</flex:FlexTextArea>
	<flex:FlexTextInput id="text" y="120"
		 x="50" width="220">
	</flex:FlexTextInput>
</mx:Application>

You can type vietnamese using VNI input method (see)

vnkeys was designed to work well with Textfield. I guess that you feel that the replacement is a little bit annoying when using it with Flex TextInput and TextArea. Here is an example when using it with TextField. It runs smoothly and you experience a bit faster. This is something that we will try to improve in the future version.

How to type vietnamese with VNI input method that is implemented in vnkeys

Bellow is a table on how to hit the keyboard (left hand side) to get the vietnamese letter (right hand side)
VNI => Vietnamese
a1 => á
a2 => à
a3 => ả
a4 => ã
a5 => ạ
a6 => â
o7 => ơ
a8 => ă
d9 => đ

We do not implement all possible ways to type a vietnamese word. Example, there are many ways to type the word trường (school)

  • truong72 → trường
  • truo72ng → trường
  • truo7ng2 → trường
  • tru7o72ng → trường
  • 72truong → trường
  • t72ruong → trường
  • tr72uong → trường

But in vnkeys you can only do that with the first four ways in this list. Another word, we implemented only the “natural ways” of typing. And natural means that you type in an order as you write on paper.

How to implement singleton pattern in actionscript 3

In actionscript 3 one can not use private scope for constructor and you need a workaround to implement simgleton pattern. Following is one way that I use

package
{
	public class Singleton
	{
		private static var instance:Singleton;
		private static var isAllowedInstance:Boolean;
 
		public function Singleton() {
			if (!isAllowedInstance) {
				throw new Error("Please use " + 
						"Singleton.getInstance()" + 
						"instead of new keyword");
			}
			this.init();
		}
 
		private function init():void {
			trace("init stuffs");
		}
 
		public static function getInstance():Singleton {
			if (null == instance) {
				isAllowedInstance = true;
				instance = new Singleton();
				isAllowedInstance = false;
			}
			return instance;
		}
 
		public function singsing():void {
			trace("singsing");
		}
	}
}

This will cause an error if someone uses the new keyword

var singleton:Singleton = new Singleton();

It will work fine if you use it like this

var singleton:Singleton = Singleton.getInstance();

How to get svn revision in ant using svn or svnversion

This article is aimed to you whom use svn in linux environment. If you are using windows and Tortoise this post may be more interesting.

Here are two ways to get revision number when you build your project. The first one is a complete method to get this number and the second one will give you this number including a trailing if there is (see). In both examples I try to get the current revision number of Zend Framework …

Using svn
In this case we use “svn info” and put the data into xml file svninfo.xml. After that we load in the data using xmlproperty and select the revision number. Your target would look like this

<target name="get-revision">
	<exec executable="svn" output="svninfo.xml">
		<arg line="info --xml Zend" />
	</exec>
	<xmlproperty file="svninfo.xml" collapseattributes="true" />
	<property name="svn.revision" value="${info.entry.revision}" />
	<echo>${svn.revision}</echo>
</target>

And after running this target you get an output as bellow and the echo statement should give you 17746

<?xml version="1.0"?>
<info>
	<entry kind="dir" path="Zend" revision="17746">
		<url>
			http://framework.zend.com/svn/...
			...framework/standard/trunk/library/Zend
		</url>
		<repository>
			<root>http://framework.zend.com/svn/framework</root>
			<uuid>****</uuid>
		</repository>
		<wc-info>
			<schedule>normal</schedule>
			<depth>infinity</depth>
		</wc-info>
		<commit revision="17740">
			<author>****</author>
			<date>2009-08-22T02:53:32.295192Z</date>
		</commit>
	</entry>
</info>

Using svnversion
This case is really simple and you don’t need an output file. However, the result may contain none numeric character and you need to convert it if you do need an integer. The easiest way is to parse this as an int in your application before you start using it. In this example the echo statement should print out something like 17746M

<target name="get-version">
	<exec outputproperty="svn.revision" executable="svnversion" dir="Zend" />
	<echo>${svn.revision}</echo>
</target>

How to run php script via putty or command line

If you need to run a php script in Linux environment via putty or other clients and want to close client without terminating the running process of php script you may need to do as bellow. The keyword is nohup

nohup php policyserver.php > /dev/null 2>&1 &

How to wrap your actionscript class/application and add it to flex application

Sometimes ago I started to learn actionscript 3 and the go was to code for the game nought and crosses with a simple AI. To save time I used Flex componnents to create button and other containers. I was running on problem to add my application to flex application. Flex refused to add my objects as child in Flex application and the solution was adding my objects in an UIComponent object and added this object to flex application. Bellow is another way to code and is completely equivalent to what mensioned above.

The procedure is simple. You create a “container” class by extending Flex UIComponent. Bellow is the container class for my nought and crosses. I guess that you are familar with the code. You don’t need to pay much attention to create-method. However, newGame, playBack and addStatusListener are worth to notice. And you can find the reason on the next paragraph.

package vnmedia.games.nac
{
	import mx.controls.Text;
	import mx.core.UIComponent;
 
	import vnmedia.games.nac.ai.AiComm;
	import vnmedia.games.nac.ai.BaseAi;
 
	import vnmedia.games.nac.core.CoreComm;
	import vnmedia.games.nac.core.Game;
	import vnmedia.games.nac.gui.Client;
	import vnmedia.games.nac.gui.GuiComm;
 
	public class FlexNac extends UIComponent {
		private var client:Client;
		private var game:Game;
		private var status:Text;
 
		public function FlexNac() {
			// create client, game and other necessary
			this.create();
			try {
				this.addChild(this.client);
				// start an new game
				this.game.newGame(1);	
			} catch(e:Error) {
				trace(e);
			}
		}
 
		public function newGame():void {
			this.game.newGame(1);
		}
 
		public function playBack():void {
			this.client.playBack();
		}
 
		public function addStatusListener(t:Text):void {
			this.client.addStatusListener(t);
		}
 
		private function create():void {
			var aiCoreComm:CoreComm = new CoreComm;
			var guiCoreComm:CoreComm = new CoreComm;
			var aiComm:AiComm = AiComm.getInstance();
			var guiComm:GuiComm = GuiComm.getInstance();
			var Ai:BaseAi = new BaseAi();
			aiComm.attach(Ai);
 
			aiCoreComm.setClientComm(aiComm);
			guiCoreComm.setClientComm(guiComm);
 
			guiComm.setCoreComm(guiCoreComm);
			aiComm.setCoreComm(aiCoreComm);
 
			this.client = new Client(24);
			guiComm.attachClient(this.client);
 
			this.game = new Game('X');
			this.game.aiCoreComm = aiCoreComm;
			this.game.guiCoreComm = guiCoreComm;
			// 
			aiCoreComm.attachGame(game);
			guiCoreComm.attachGame(game);
			this.client.addStatusListener(status);
		}
	}
}

Now you know how to create a “container” class for your application. The next step is to include it in a Flex application. There are two way to add it to Flex application. You can use mx:Script and code with actionscript style (see) or just do as simple mxml example bellow where I use Flex standard box components and button component.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
   xmlns:vn="vnmedia.games.nac.*" layout="absolute">
  	<mx:Style source="beige.css"></mx:Style>
  	<mx:VBox styleName="firstVBox">
  		<mx:HBox styleName="menuHbox">
  			<mx:Button id="newGameButton" 
  			    click="nac.newGame();" 
  			    label="New game"></mx:Button>
			<mx:Button id="playback" 
			    click="nac.playBack();" 
			    label="Playback"></mx:Button>
  		</mx:HBox>
  		<mx:HBox x="10">
  			<vn:FlexNac id="nac"></vn:FlexNac>
  		</mx:HBox>
  	</mx:VBox>
	<mx:VBox styleName="secondVBox">
		<mx:HBox styleName="statusHBox">
  			<mx:Button label="Status"></mx:Button>
  			<mx:Text id="stat" styleName="status" 
  			    text="You: 0 Computer: 0" 
  			    creationComplete="nac.addStatusListener(stat);">
  			  </mx:Text>
  		</mx:HBox>
	</mx:VBox>
</mx:Application>

Now when you finished reading the code you should notice that I added my nought and crosses with a tag

<vn:FlexNac id="nac"></vn:FlexNac>

What hapened was that I created my own namespace vn. You can find it as an attribute in mx:Application element. You should get a picture how to create your own component for Flex application by now, right?! and of course if you have a reason :-p

Now we go back to those 3 methods mensioned in the beginning. I just created those public methods so I could access from Flex application, no more no less. Another way is that I could make “game” and “client” accessible. One last thing for those whom do not use mxml. The attribute id refers to the created object and you can see it in the beginning where I used in click event

<mx:Button id="newGameButton" 
  	click="nac.newGame();" 
  	label="New game"></mx:Button>
...

And finally the result