Category Archives: Software

Raw text printing from Adobe AIR

Printing raw text in Adobe AIR is kinda pain, specially if the text is too large, or multipage!

After some research and gerring ideas, I derived my own version of Util class which manages basic functionality.

package
{
	import mx.utils.StringUtils;
	
	import flash.display.Sprite;
	import flash.geom.Rectangle;
	import flash.printing.PrintJob;
	import flash.printing.PrintUIOptions;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;

	public class PrintUtils
	{
		public function PrintUtils()
		{}
		
		public static function printText(textString:String, printPageCount:Boolean = false):Boolean
		{
			var marginX:Number = 10;
			var marginY:Number = 10;
			var printJob:PrintJob = new PrintJob();
			var uiOpt:PrintUIOptions = new PrintUIOptions();
			
			if (!PrintJob.supportsPageSetupDialog) 
				return false;
			
			printJob.showPageSetupDialog(); 
			if( !printJob.start2(uiOpt, true) )
			{
				printJob.terminate();
				return false;
			}
			
			try
			{
				var fontSize:int = 10;
				var fontColor:uint = 0x000000;
				var format:TextFormat = new TextFormat( null, fontSize , fontColor );
				var printableArea:Rectangle = new Rectangle(0, 0, printJob.printableArea.width, printJob.printableArea.height);
				var lastChar:Number = 1;
				var pageCounter:int = 1;
				var pageCounterLine:int = printPageCount ? 1 : 0;
				while(lastChar > 0)
				{
					var remainingTextField:TextField = new TextField();
					remainingTextField.width = printableArea.width - (marginX*2);
					remainingTextField.height = printableArea.height - (marginY*2);
					
					remainingTextField.autoSize = TextFieldAutoSize.LEFT;
					remainingTextField.defaultTextFormat = format;
					remainingTextField.multiline = true;
					remainingTextField.wordWrap = true;
					
					remainingTextField.text = textString;
					
					// text strip out logic
					var lastLineTextString:String = StringUtil.trim(remainingTextField.getLineText(remainingTextField.bottomScrollV-pageCounterLine));
					if(lastLineTextString=="")
					{
						// find next printable line
						for(var j:int=1 ; j<(remainingTextField.bottomScrollV-pageCounterLine) ; j++)
						{
							lastLineTextString = StringUtil.trim(remainingTextField.getLineText(remainingTextField.bottomScrollV - pageCounterLine - j));
							if(lastLineTextString!="")
								break;
						}
					}
					
					lastChar = textString.indexOf(lastLineTextString) + lastLineTextString.length;
					var pageString:String = StringUtil.trim(textString.substr(0, lastChar));
					textString = StringUtil.trim(textString.substr(lastChar+1));
					
					if( StringUtils.isBlankOrNull(textString) )
						lastChar = 0;
					
					// print grabbed text on one page----------------------------------------------
					var printableSprite:Sprite = new Sprite();
					printableSprite.graphics.clear();
					//printableSprite.graphics.beginFill(0x00FF00);
					//printableSprite.graphics.drawRect(marginX, marginY, printableArea.width, printableArea.height);
					//printableSprite.graphics.endFill();
					
					var textFieldPrint:TextField = new TextField();
					textFieldPrint.width = printableArea.width - (marginX*2);
					textFieldPrint.height = printableArea.height - (marginY*2);
					textFieldPrint.x = marginX;
					textFieldPrint.y = marginY;
					
					textFieldPrint.autoSize = TextFieldAutoSize.LEFT;
					textFieldPrint.defaultTextFormat = format;
					textFieldPrint.multiline = true;
					textFieldPrint.wordWrap = true;
					
					textFieldPrint.text = pageString;
					
					printableSprite.addChild(textFieldPrint);
					
					// add pageCount
					if(printPageCount)
					{
						var pgCountTextFieldPrint:TextField = new TextField();
						
						pgCountTextFieldPrint.autoSize = TextFieldAutoSize.LEFT;
						pgCountTextFieldPrint.defaultTextFormat = format;
						pgCountTextFieldPrint.multiline = false;
						pgCountTextFieldPrint.wordWrap = true;
						pgCountTextFieldPrint.text = "Page " + pageCounter;
						
						pgCountTextFieldPrint.width = printableArea.width - (marginX*2);
						pgCountTextFieldPrint.x = marginX;
						pgCountTextFieldPrint.y = printableArea.height - pgCountTextFieldPrint.height - (marginY*2);
						
						printableSprite.addChild(pgCountTextFieldPrint);
						
						pageCounter++;
					}
					printJob.addPage(printableSprite, printableArea); 
				}
			}
			catch(error:Error)
			{
				return false;
			}
			printJob.send();
			return true;
		}
	}
}

This handles multi page text based on selected page size and margin. Also has minor feature of adding page number and so. This isn’t certainly rich utility, but also is enough to get started to add more features.

Lazy Loading of Proxies

While working on a pureMVC project, I realised that there were N number of proxies registered with facade (yes, ApplicationFacade). The truth was, not all have been used during life cycle of a typical user functionality.

So what? It was merely difficult to categories the proxies for need of individual module/functionality.

The simple idea is to implement Lazy Loading / Lazy registration of proxy!

Instead of declaring statement at compile time like

facade.registerProxy(new MyProxy()); 

I overridden

retrieveProxy(...)

function in extended Facade class:

override public function retrieveProxy(proxyName:String):IProxy
{
 var proxyInstance:IProxy = super.retrieveProxy(proxyName);
 if(proxyInstance==null)
 {
 var myClass:Class = getDefinitionByName(proxyName) as Class;
 if(!myClass)
 return null;

 var proxyInstance:IProxy = new myClass();
 if(proxyInstance)
 registerProxy(proxyInstance);
 }
 return proxyInstance;
}

This also takes care of not registering duplicate proxy.
Uh oh! While doing this trick, I encountered on more problem.


ReferenceError: Error #1065: Variable myClass is not defined.

I banged my head and tried to figure out the reason. After digging for some time, I found that the (class) definition of proxy was somehow not been retrieved with

getDefinitionByName() 

.
It wasn’t possible to simply add import statements with those Proxy class names as Flex compiler ignores such unused (yes while compiling none of proxy was referenced) imports.

Simple trick worked:
in extended facade class constructer, I declared each proxy as variable, something like:

public class ApplicationFacade extends Facade
{
 public function ApplicationFacade(parameter:SingletonEnforcer)
 {
 super();

 var myProxy:MyProxy;
 }
}

and that’s all I wanted! The trick is this code doesn’t force an instance of proxy to be created, still at runtime when required, it finds definition of MyProxy class.

Infibeam Pi – a review

After using – playing with infibeam.com’s Pi, for almost about 4 months I thought to write about it. Many people have been asking me online and offline ‘How is it?’ And could simply respond with ‘Good’!

If you think this is smart device, can do much more like iPad, Galaxy Pad or so, its absolutely misconception. Its very very simple and dedicated eBook reader, and almost nothing beyond that. No wi-fi, no 3G, no browser, no touch-screen!
The device is meant for very specific purpose.

Battery:
The battery lasts long and the main reasons behind them is the way is designed – no backlight and E-ink  screen. This is indeed smart technique, absence of back light and flat simple screen provides very smooth, no eye itching experience. This definitely provides equally pleasant experience as if you were reading physical – paper book. Battery indeed lasts more than a week for me after a complete charging cycle.

Connectivity:
Connectivity is pretty simple way, charging and data transfer is possible with mini USB interface. It also has SD card  slot, so you every time do not need to connect reader via cable to transfer books.

Ebook reading / formatting:
Though it supports vast variety of formats including, TXT, EPUB, PDF, HTML, and more, the device converts – formats text on its own. For non technical reading, its indeed good. This may result into different placement of image, but is fine as long as you can link the reference!
However, for technical ebooks, this isn’t good. For instance, code snippet or some tips also gets converted and formatted with different font. This makes it little annoying to understand flow. Also, limited screen size may also split continuity. Reference to diagram involves multiple flips between few pages.
The best and i-like-most part is support for major Indian languages. Font support and formatting is really very nice when it comes to Indian regional text.

Audio:
It has very basic audio player which supports MP3 format. This player is indeed basic, don’t expect rocking sound experience! The ideal purpose, though not highlighted much anywhere, is audio ebook listening, and nothing beyond.

Screen / display:
It has simple 600 by 800 pixels of display which is sufficient for normal book reading. The landscape and full screen book reading experience is good for continuous reading.

  • Font families – changeable includes Georgia, Courier, MTX Bold
  • Size switches – increase / decrease actually changes font size and reformats text. For ebooks with scanned image type text, text recognition is not there, so can also use zoom in-out.
  • E-ink displays image in grayscale.
  • Refresh / response time is bit more, so requires patience after button press! 😀

Others:
No keyboard, very limited functional buttons, so no confusion for first time users.
Sudoku game, image viewer.

Minor bugs:

  • Landscape mode reading doesn’t show full title of ebook, even if it has sufficient space.
  • Header shows date, but not time – crazy!
  • For Indian scripts, specially with subscript characters and superscript characters, post formatting gives little annoying experience, for example a signle word is broken in such a way that first line terminates with consonant character and associated vowel goes to next line beginning! 🙂
  • About section – device says “GNU General Public License – this product contains software which applies to GPL. You may obtain and redistribute the GPL source code.” This is indeed crazy, GPL is license and not any type of source code. And the company – infibeam doesn’t mention which software (under GPL) is used, and from where! (consider it major, if you’re also open source promoter, like me.)

The bottom line:
This is dedicated ebook reader for India, but not as per ‘Indian Price’ – bit more expensive considering set of features. However the available options are good enough for non technical or semi technical reading.

Couple of one liners from my friends when they played with my reader.
“Please remove paper placed on screen and switch it on, I want to see!” (though actually it was on with some book opened)

“If this is offered around Rs.5000, I shall get one.”

“This is a book only, and is thinner than our technical books.” (when I handed over with leather case)
Bonus for readers of this post –

Get your favorite newspaper delivered to your e-mailbox, daily and read using this reader

  • Grab copy of Calibre Ebook Management software. It’s free and open source, supports multiple operating systems.
  • Install and open
  • Click on Fetch newsSchedule news download and you will see a window like below:Schedule news download
  • search for your favorite newspaper / magazine and click on the name. Of course, you can also add your own way – own news feed. But this requires little technical knowledge.
  • When you select – highlight the item, Schedule option on right side will be enabled, just select preferred time and frequency and save.
  • Now click on Connect / Share icon and setup your email account, make sure you enabled auto send option.
  • That’s it!

Note, this trick requires software to be open and internet to be connected, for the time you have scheduled. You can use scheduled activity to start / wake up your computer before the schedule and hibernate / shutdown post schedule.

I also recommend Calibre Ebook Management software as it has vast options to convert ebook to multiple formats.

Update:

infibeam Pi is just a wrapper and Indian branding of netronix ebook device! I was bit surprised to find this. Also, firmware upgrade is also not smooth. Post upgrade, you may expect some bugs as new gifts! 😀

Auto fare Calculator for Indian cities

Many people either carry copy of auto fare card with them or do remember formula. However, it becomes difficult when you are roaming in multiple cities frequently.

A lot many similar apps available, however they are either platform specific, outdated or requires GPRS or other network connection. Few others are city specific.

This is a very simple attempt to overcome a couple of situations.

The application:

  • Works on almost any mobile with basic browser (internet browsing software)
  • Does not require any GPRS or other connection to run the app
  • Has support for multiple cities of India
  • Support for night fare calculation – based on device time
  • No installation required, just copy to mobile and run
  • No advertisement, no license fee – free and open source
  • Can be very easily updated
  • Has very basic and simple interface, executes and works simply

Grab it : Download http://harit.kotharee.com/app/fareCalc.htm . (Right click to the link and select ‘Save As…’ and save to your computer / or save the copy on your mobile.)

Use it : Open the saved copy of fareCalc.htm from your mobile or equivalent device, in most cases, it should open with default available browser. That’s it. No need to explain further. 🙂

Why HTMLand JavaScript?

  • Most mobile browser supports
  • No formatting / styling required
  • Widest compatibility across mobile platforms
  • No rebuild, easy to update
  • No installation required
  • Easy to share

Chrome and popup policy

Google Chrome has different policy to detect and block popup window.

Generally, a browser blocks popup if it’s automated, i.e. with some JavaScript call on page load or so. Moreover the way state of popup can be known by browsers using JavaScript only.

Chrome is bit smarter in this.

window.open(); is expected to return reference to opened popup window, or null / undefined if popup is blocked.

But, chrome holds reference of so called popup as non null value and still blocks popup.

Below snippet is perfect example to test:

<script language="JavaScript">
<!--
function showpopup()
{
	setTimeout ( "showpopupAfterTime();", 1000 );
}

function showpopupAfterTime()
{
 var popwin = window.open("http://harit.kotharee.com/", "popupwindow",
   "width=400,height=300,resizable,status,menubar,scrollbars");
 popwin.focus();
}
//-->
</script>

<a href="javascript:showpopup()">Click for a pop-up window!</a>

Chrome allows popup only if opened directly, i.e. without any kind of delay through JavaScript or any other means of delay.

So, in the above example, it will work only if showpopupAfterTime(); is called on hyperlink!

Adobe Flash Player & KeyboardEvent – FullScreenEvent relation explored

Since Adobe Flash player has allowed limited keyboard support for full screen mode (application), the feature also comes with a strange cost.

When KeyboardEvent.KEY_DOWN event listener is registered on stage, KeyboardEvent with keycode 32 (equivalent to Space key) is fired always when the application goes from normal state to full screen state!

To make sure, I made a sample test application as under:

package 
{
	import flash.display.*;
	import flash.events.*;
	import flash.text.TextField;
	import flash.net.URLRequest;
	import flash.ui.Keyboard;

	public class fullScreenTest extends Sprite
	{
		private var loader:Loader;
		private var player:Object;
		public function fullScreenTest()
		{
			super();
			if(stage)
				onAddedToStage();
			else
				addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
		}
		
		private function onAddedToStage(event:Event = null):void
		{
			if(hasEventListener(Event.ADDED_TO_STAGE))
				removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
			var changeScreenState:TextField = new TextField();
			changeScreenState.text = "Change Screen State";
			changeScreenState.selectable = false;
			changeScreenState.addEventListener(MouseEvent.CLICK, onChangeScreenState);
			addChild(changeScreenState);
			
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			
			stage.addEventListener(FullScreenEvent.FULL_SCREEN, onToggleFullScreen);
			stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
		}
		
		private function onChangeScreenState(event:Event = null):void
		{
			if(stage.displayState == StageDisplayState.NORMAL)
				stage.displayState = StageDisplayState.FULL_SCREEN;
			else
				stage.displayState = StageDisplayState.NORMAL;
		}
		
		private function onToggleFullScreen(event:FullScreenEvent):void
		{
			trace("is app in full screen? "+event.fullScreen);
		}
		
		private function onKeyDown(event:KeyboardEvent):void
		{
			if(event.keyCode == Keyboard.SPACE)
			{
				trace("event target : " + event.target +
						"\n\tevent keycode : " + event.keyCode);
			}
		}
	}
}

Up to surprise, KeyboardEvent.KEY_UP listener does the same job, perfectly fine, without sending extra KeyboardEvent with SPACE keyCode! Of course, this doesn’t apply when application state changes to normal, from full.

So, in a way the solution to this is either only use KeyboardEvent.KEY_UP event listener(s) or, remove event listener registered with KeyboardEvent.KEY_DOWN while switching from normal screen state of application to full screen, after some dummy time, (re)register listener for KeyboardEvent.KEY_DOWN !

I am yet not sure why FullScreenEvent event comes with KeyboardEvent event instance propagating through!

alpha & rotation issue for textArea with htmlText

I had been playing with this for one of a project requirement.

Description of scenario:

  • Embedded fonts ‘Times New Roman’ both, using default font manager (Batik) as well as AFE
  • The application consists of two text area components
  • For 1st textarea, I am setting text using ‘text’ property and setting font family, size and color using setStyle().
  • For second, I am providing text related information via ‘htmlText’ property.
  • Using a slider I should be able to change alpha value of both textArea components.

Behavioral problems:

  • When I change value using slider, the alpha effect is applied and visible for 1st textarea, but in case of second, alpha value gets applied but text has no visible impact of alpha.
  • When I rotate both textArea components using, 1st gets rotated, but not second. In case of both textareas, I am referring and using embedded font only. (font family ‘TNR’ in example)

I expect both textAreas behave identical.

As far as I know and received primary feedback from a famous flexer guy, my code is right. If I consider this, there is definitely a limitation / bug in flex SDK. Hence I suggested a new task in SDK.

Here is a code I had written to simulate the SDK limitation / bug:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()">
	<mx:Style>
		@font-face
		{
			src: url('/assets/fonts/times-new-roman.ttf');
			fontFamily: "TNR";
			font-weight:normal;
			font-style:normal;

			advancedAntiAliasing: true;
		}
	</mx:Style>
	<mx:Script>
		<![CDATA[
			import mx.events.SliderEvent;

			private function init():void
			{
				basicTxt.text = "This is a sample text!";
			}

			private function onChange(event:SliderEvent):void
			{
				basicTxt.alpha = event.value;
				htmlTxt.alpha = event.value;
			}

			private function doRotate(event:MouseEvent):void
			{
				basicTxt.rotation = 20;
				htmlTxt.rotation = 20;
			}
		]]>
	</mx:Script>
	<mx:VBox width="100%" height="100%">
		<mx:HBox width="70%" height="50%">
			<mx:TextArea id="basicTxt" width="80%" backgroundColor="blue" fontSize="36" height="100%" fontFamily="TNR"/>
			<mx:TextArea id="htmlTxt" width="80%" backgroundColor="blue" height="100%">
			<mx:htmlText>
					<![CDATA[<TEXTFORMAT LEADING="2"><P ALIGN="LEFT"><FONT FACE="TNR" SIZE="36" COLOR="#000000" LETTERSPACING="0" KERNING="0">This is a sample text!</FONT></P></TEXTFORMAT>]]>
				</mx:htmlText>
			</mx:TextArea>
		</mx:HBox>
		<mx:HSlider minimum="0" maximum="1" value="1" change="onChange(event)" />
		<mx:Button label="Rotate" click="doRotate(event)" />
	</mx:VBox>
</mx:Application>

I will appreciate if anyone can give some ideas / pointers to work around.

Flex Formatter

Flex Builder 3, an eclipse~ IDE for flex and actionscript based project development lacks few primary code indentation and refactoring functionalities by itself.

Searching for some other technical requirement drove me to Flex Formatter, a third party project on source! Cheers, its BSD license! 🙂

This tool is really small but very essential and useful plugin

Flex Formatter tools

Flex Formatter tools

Many times it happens that code is written in hurry to achieve some short term goal. Either some efforts need to invest to refactor and indent the code, or else go for Flex Formatter.

Built in capability to generate ASDoc is also impressive! However, I suppose, all these features, of flex formatter have been covered with Flash Builder 4.

How to read Mobile Feed / QR Code?

QR Code requires special software installed on your mobile to interpret the matrix / image.

The content of mobile feed are encoded and represented in 2 dimensional image in a small area.

You can get suitable QR Reader for your mobile device from Kaywa Reader.  or search google for similar softwares.

This is a good option to store contents on mobile very quickly and use as offline read.

Holi – color-full festival

Let’s play Holi the Mozilla way…..

Let’s see the colors of the world from an eye of Mozilla (Firefox)

Let’s greet by a postman from Mozilla (Thunderbird)

*

Let’s play Holi in simple, safe way….. with only gulaal, no artificial color / paint.

%d bloggers like this: