UI design for my PaperCrop clone (Thanks to Balsamiq!!!)

Trying to find some inspiration for my UI I reached http://www.balsamiq.com/. These guys have an impressive Mockup generator program called Balsamiq Mockups. It is quite easy to create mockup interfaces for your applications, and pretty easy to use. The best thing is that they offer a free license to oen source contributors (do-gooders as they call us ^^).  I asked for one and they sent me a license in one day!!!!

Now I will start developing a mockup UI and publish it to have some comments about it.

If you want more info about balsamiq, click on the image below.

balsamiq_logo

Javascript support added to AlivePDF Template

UPDATE: AlivePDF 1.5 will support Javascript!!!!! It seems that the method will be quite equivalent to the one that I use here, so hopefully no change will be needed. Way to go AlivePDF!!!!!

My second step in creating an application like PaperCrop was to display the PDF inside Adobe Air. As you may know, to do that you must have installed Adobe Acrobat Reader 9 or higher (or was it 8?). After installing the reader you can see the PDF using the browser of adobe air, by navigating to the page with the PDF embedded on it. A very nice example is “Cross-scripting PDF content in an Adobe Air application”

The main issue: you cannot control a PDF file unless it has the javascript code embedded. This was a problem, as there was no way to add javascript in a PDF file in Adobe Air…until now ^^

I added javascript support to AlivePDF Template, so now you can add the required scripts to control the file, as shown in the webpage above.

You can download the source code from the google code webpage of the project.

An example on how to use it is shown below. Enjoy!!!!

	var myPDF : PDFi = new PDFi ( Orientation.PORTRAIT, Unit.MM, Size.LETTER );
	myPDF.setViewerPreferences("true", "true", "true");
	myPDF.javascript = "" +
		"var msgHandlerObject = new Object();\n" +
		"msgHandlerObject.onMessage = myOnMessage;\n" +
		"msgHandlerObject.onError = myOnError;\n" +
		"msgHandlerObject.onDisclose = myOnDisclose;\n" +
		"\n" +
		"function myOnMessage(aMessage)\n" +
		"{\n" +
		"	if (aMessage.length==1) {\n" +
		"		switch(aMessage[0]) \n" +
		"		{\n" +
		"			case 'ZoomIn':  \n" +
		"			    zoom *= 2; \n" +
		"				break;\n" +
		"			case 'ZoomOut': \n" +
		"			    zoom /= 2; \n" +
		"				break;\n" +
		"			case 'PageUp': \n" +
		"			    pageNum--; \n" +
		"				break;\n" +
		"			case 'PageDn': \n" +
		"			    pageNum++; \n" +
		"				break;\n" +
		"			default: \n" +
		"				app.alert('Unknown message: ' + aMessage[0]);\n" +
		"		}\n" +
		"	}\n" +
		"	else\n" +
		"	{\n" +
		"	    app.alert('Message from hostContainer: \\n' + aMessage);\n" +
		"	}\n" +
		"}\n" +
		"\n" +
		"function myOnDisclose(cURL,cDocumentURL)\n" +
		"{\n" +
		"	return true;\n" +
		"}\n" +
		"\n" +
		"function myOnError(error, aMessage)\n" +
		"{\n" +
		"	app.alert(error);\n" +
		"}\n" +
		"\n" +
		"this.hostContainer.messageHandler = msgHandlerObject;\n" +
		"\n";

	var pagecount:Number = myPDF.setSourceFile(File.desktopDirectory.nativePath + File.separator + "PDFControlFlex" + File.separator + "src" + File.separator + "test.pdf" ); //"H:/readings/thesisStatement/p263-jain_challenges_environmental_design_for_pervasive_computing_systems.pdf");
	for(var i:Number = 1; i<=pagecount; i++) {
		var tplidx:Number = myPDF.importPage(i, '/MediaBox');
		myPDF.addPage();
		myPDF.useTemplate(tplidx, 0, 0, Math.ceil(myPDF.getTemplateSize(i).w));
	}

	var f : FileStream = new FileStream();
	var file : File = new File(File.desktopDirectory.nativePath + File.separator + "PDFControlFlex" + File.separator + "src" + File.separator + "MyPDFi.pdf");
	f.open( file, FileMode.WRITE);
	var bytes : ByteArray = myPDF.save(Method.LOCAL);
	f.writeBytes(bytes);
	f.close();

AlivePDF Template now available at Google code

Check it out at:

http://code.google.com/p/alivepdf-template/

A PDF import library for AlivePDF

Sometime ago I decided to create a PDF converter that allowed users to select the sections of PDF to be included in the final PDF. The idea is quite similar to PaperCrop, and actually I modified PaperCrop first to extract text and not only create images (if you want a version of my modified version contact me ^^). Anyway, I felt that PaperCrop was an excellent software (I still does), but it is too difficult to manage C++ code for me, and the lack of versions for Linux and MacOSX, motivated me to create a new software to do that.

Due to my background, my first thought was Java. I am (modestly apart) an expert in Java, and I feel quite comfortable using it. However, the PDF rendering tools available for Java where not good at all. I tried three: Multivalent, SUN’s PDF-Renderer and JPedal. All of them presented some problems at rendering, so I drop them… what to do then, go back to PaperCrop and C++ or try something different? I decided to try something different. I always liked the idea of mixing the desk and the web, so I decided to do it in Adobe AIR. Why AIR and not SilverLight or JavaFX? Well, as I already discussed, Java’s PDF renderers are not good. And I’m not familiar to Silverlight. Actionscript is quite similar to Java in structure, and I already programmed some stuff in Flash long time ago. So there we go, Adobe AIR was selected.

Now, my problem was what to use to develop such software. My first trouble, how to generate PDF files from actionscript. AlivePDF is THE solution for this in Adobe AIR (and Flex). And actually is quite good, and very simple to use. The only problem was that AlivePDF does not accept an existing PDF as input for a new one. The solution: to program a PDF importer ^^

AlivePDF is based on FPDF, a PHP PDF library, which is quite easy to extend. One of the extension, FPDi, allows you to import existing PDF files into a new PDF as a template. I decided to port this extension into AlivePDF, and it took me a couple of days to do so. You can download the AlivePDFTemplate library here:

Please be aware that this is a beta release. I tested with few cases only. It is licensed under the Apache 2.0 license, so you can use it and modify it the way you want.

To use it, you can use the following example as a reference, or check the FPDi website for more examples.

//Must create a new PDFi instance (not PDF)
	var myPDF : PDFi = new PDFi ( Orientation.PORTRAIT, Unit.MM, Size.LETTER );
				
// Import a file!!!! Just set the source file to an existing PDF
	var pagecount:Number = myPDF.setSourceFile(File.desktopDirectory.nativePath + File.separator + "FPDF_TPL-Manual-1.1.pdf" );
// Import a page. The first argument is the page number, the second the way it will be imported
	var tplidx:Number = myPDF.importPage(1, '/MediaBox'); 

//This is important, you MUST add a page first!!!!
	myPDF.addPage();
//Use the template in the current page
	myPDF.useTemplate(tplidx, 10, 10, 90);

// This is not part of the original PDF. Just a test ^^
	myPDF.setFont( FontFamily.ARIAL, Style.BOLD );
	myPDF.setFontSize ( 18 );
	myPDF.setXY( 10, 40 );
	myPDF.addMultiCell ( 300, 1, "This is my PDF Headline" );

//Save the file
	var f : FileStream = new FileStream();
	var file : File = File.desktopDirectory.resolvePath("MyPDFi.pdf");
	f.open( file, FileMode.WRITE);
	var bytes : ByteArray = myPDF.save(Method.LOCAL);
	f.writeBytes(bytes);
	f.close();  

I will upload this as a new project in google code or some other place, to have a better development control. I hope you enjoy it!!!!