Splink http://splink.posterous.com Most recent posts at Splink posterous.com Thu, 17 Feb 2011 13:12:02 -0800 My as3 open source frameworks in action http://splink.posterous.com/43325065 http://splink.posterous.com/43325065

A few weeks ago I read an article about inventing secure passwords in the well known c't magazine. That was when the revolutionary idea to build a password manager sprang to my mind. Well, the revolutionary thing about my password manager, so I thought, was that is was an online password manager. After some google-fu I discoverd that I was not the first with that "revolutionary" idea. Nevertheless, I had some time and felt like spending the weekend writing my own password manager. The main reason to just do it against better judgement was that I wanted to test-drive my amf module for the ingenious playframework and improve my flash UI component framework uitoolkit.

After the weekend I had my first version complete, but then new ideas for features occured to me and as my current project's next iteration still is in a waiting loop I carried on with my password manager... Now, a few weeks later I finally declare the first version complete and ready for your consideration: 

Pwdsafe_-_the_password_manager

https://pwdsafe.com

* icon source: iconic and logo font source: exljbris font foundry.

Overall I'm quite happy with the result and glad that I finally managed to complete one of my spare-time projects so far that I can release it into the wild. Most fun projects just end up dead in my eclipse workspace (I'm sure you know what I mean...).

But the real cause why I'm blogging this, is that I believe it might be interesting for you to see my open source frameworks in action. I programmed the backend as I previously mentioned using the playframework in conjunction with my amf module which in fact just glues the playframework and the amf framework cinnamon

The frontend is obviously done entirely in flash. I built the core structure of the application with the aid of deepsplink, because I wanted to organize the site into pages and enjoy out of the box deeplink support: each page can be bookmarked and integrates with the browser back button. The most interesting page in regard to deepsplink features is the RetrievePage, which uses PageParameters. The RetrievePage contains a data grid whose contents can be filtered and a paginator (if there is enough data). PageParameters are used to add the page and current filter String to the url. Thus it is for instance possible, to use the filter, leave the page, return to the page via back button and still see the previously filtered data. 

Page-params

I also used deepsplink's protected pages feature. If the user requests one of the protected pages he is redirected to the login page unless the user is authenticated. Look at the deepsplink configuration file which I think depicts the application structure quite well:

<config> <page id="root" clazz="pages.RootPage" title="Root"> <page id="home" clazz="pages.home.HomePage" title="Home" /> <page id="create" clazz="pages.CreatePage" title="Create" /> <page id="retrieve" clazz="pages.retrieve.RetrievePage" title="Retrieve" /> <page id="settings" clazz="pages.settings.SettingsPage" title="Settings" /> <page id="signup" clazz="pages.SignupPage" title="Signup" /> <page id="login" clazz="pages.LoginPage" title="Login" /> <page id="logout" clazz="pages.LogoutPage" title="Logout" /> <page id="faq" clazz="pages.FAQPage" title="FAQ" /> <page id="terms" clazz="pages.overlay.TermsPage" title="Terms and Conditions" group="footer" /> <page id="privacy" clazz="pages.overlay.TermsPage" title="Privacy" group="footer" /> <page id="imprint" clazz="pages.overlay.TermsPage" title="Imprint" group="footer" /> </page> <home id="home" /> <notfound redirect="home" /> <protect redirect="login" > <page id="create" /> <page id="retrieve" /> <page id="settings" /> </protect> <overlay> <page id="terms" /> <page id="privacy" /> <page id="imprint" /> </overlay> </config>

For resource management and internationalization I employed my splinkresource framework. It is embedded in a preloader swf and loads the application's assets, fonts, the UI skin and the main application. Take a look at the configuration file:

<resourcebundles defaultLocale="en_EN"> <resourcebundle locale="en_EN"> <locales> <locale value="de_DE" /> </locales> <assets path="assets/"> <asset id="assets" src="assets.swf" filesize="24823" /> </assets> <fonts path="fonts/"> <font id="Delicious" type="text" src="delicious.swf" sizeOffset="5" filesize="92263" /> </fonts> </resourcebundle> <libraries path=""> <library filesize="21016" src="assets/skin-darkgrey.swf" id="skin" /> <library filesize="128203" src="pwdsafe.swf" id="main" /> </libraries> </resourcebundles>

The filesize attributes are automatically populated by an ant task when I publish the application. This saves the trouble to determine the filesizes of the referenced files manually. The filesizeinjector task is included in splinkresource. As my application currently supports only two languages (english and german) and both actually use the same fonts and assets, I could use the locales node shortcut instead of having to define another resourcebundle for the de_DE locale. If, sometime I add for instance a russian version, I would need to define another resourcebundle, because russian requires other (cyrillic) fonts. Speaking of fonts; by adjusting the sizeOffset attribute of a font I am able to quickly change the application's overall fontsize which I find quite handy. Within the application code the ResourceProvider provides access to the contents of the currently loaded resourcebundle: getAssetForId, getFontDataByType and getLibraryForId are the most used methods. The splinkresource wiki describes the details.

You might have noticed that a "skin-darkgrey.swf" is mentioned in the splinkresource configuration. This is the skin for the components I use on the site. Currently the site contains no switch to change the skin at runtime, but it's planned for the future. Beforehand I need to photoshop some skins :) I use several components, all of them can be quickly skinned with bitmaps, but I also put in some effort to decouple view and logic for each component. That's why it is also possible to write a new set of views, which doesn't use bitmap skins and is (for instance) completely vector drawn. The components are part of my youngest open source actionscript project called uitoolkit which is still subject to a lot of changes and far away from beeing as mature as the other frameworks. During my work on the password manager I noticed this, because I regualary improved uitoolkit while the other frameworks stayed untouched (they just worked). However, the most exiting part of uitoolkit is the layout package. I believe that there are very few open source layout managers in the pure (non flex) actionscript world and the last time I looked, none of them could satisfy my demands. So as I was tired of writing stuff like  btn.x = lastbtn.x + lastbtn.width + xspacing; all the time, I developed my own layout system which is showcased here. The layout package contains the relevant classes and there are no dependencies to the rest of uitoolkit, so if you need a layout manager but don't want any of the other stuff, you can simply use the layout package. I can't live without it anymore and the complete pwdsafe site heavily employs the layout package.

The footing of the mentioned three frameworks is splinklibrary. It contains a lot of useful stuff, and I use it on a daily basis. I think the most notable is the queue package. It makes the handeling of asyncronous processes a breeze. Just put some async tasks into the queue, start the queue and get notified when the tasks are done. But there are other handy tools, like a lightweight tween package, logging, etc.

So I hope I didn't bore you too much with my frameworks, but I thought it was a good idea to present them in light of a concrete project.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/861336/splink.gif http://posterous.com/users/YrCv4f2LjPP maxmc maxmc
Fri, 28 Jan 2011 15:45:17 -0800 An amf module for the amazing playframework http://splink.posterous.com/an-amf-module-for-the-amazing-playframework http://splink.posterous.com/an-amf-module-for-the-amazing-playframework

Ever since I discoverd the amazing playframework I waited for someone to come up with a module to let the playframework talk to actionscript via amf

But as noone came up with something until now, I took the time to investigate the matter myself. The closest solution I found before I started was a blogpost by Xavier Hanin.

I asked Xavier whether he could publish the code, but unfortunately he didn't publish it yet (he said that he had to check with his boss first). But as described in his interesting post it's not that hard to make it happen, because the probaby most difficult part is already at hand: the amf related code.

Because I know Jens and value his work, I always used his amf framework cinnamon to connect java with flash, so cinnamon was my first choice for this job, too. 

I found that the cinnamon codebase is very clean and well written, so it was pretty easy to eleminate the servlet dependencies and integrate cinnamon into play. Well actually I just had to write a simple Controller class. 

Putting the code in a playframework module was pretty easy too and so I had a working amf module in about a day.

You can find the complete module code at bitbucket. The code isn't tested very deeply yet and there are still some things to do, but it seems to work great so far.

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/861336/splink.gif http://posterous.com/users/YrCv4f2LjPP maxmc maxmc
Fri, 02 Jul 2010 09:51:00 -0700 actionscript layout framework demo http://splink.posterous.com/actionscript-layout-framework-demo http://splink.posterous.com/actionscript-layout-framework-demo

Currently I am in the process of starting another actionscript open source project. The plan is to create some sort of UI library/framework which makes the everyday UI programming tasks a more pleasant experience. The main goal is to encourage clean concise and flexible client code which can be easily maintained and changed. One part of the project is a layout framework. I created a little demo app to test it's current capabilities.

Click the image to launch the demo:

Media_httpsplinkorgwp_fzdcc
//EDIT: A friend of mine read this post and complained that it lacks a clear explanation what the demo is about. Well, the demo's purpose is to test and showcase the current state of a layout framework which I am currently working on. The 'GuiBuilder' demo enables you to create layouts visually and save/restore them to/from XML. If you start the demo it automatically loads a "default" layout. To explore this layout you can select any cell or container on the stage and change it's values by either dragging it's right and bottom border or by changing it's values in the form on the left side. You can select any cell or container by either clicking on it, or selecting it with the dropdown box on the right side. The difference between a cell and a container is that a container can contain any number of cells or containers, whereas a cell can't contain anything else. (Composite pattern) You can remove any selected cell or container exept for the "Container stage" (Some root must remain). If you remove a container, all cells and containers it contains are also removed. If you select a container you can also add cells or containers to it. If you select a cell you can only change the cell's settings, but not add anything to it. As containers can hold other containers and cells, containers allow a lot more settings then cells. Select a container and look at it's settings in the left side form. These are the actual features of the layout framework. Any value you change affects the content of the selected container. So you could for instance change the amount of columns, the alignment, and so on. But to see any change, the container needs content. As long as the container doesn't contain cells or containers, nothing happens. But as soon as you start adding cells or containers to the container you will see the settings take effect, because the container's settings are applied to it's content. If you are finally happy with your result you can click the "Save to clipboard" button and store the resulting XML on your clipboard. The next time you open the 'GuiBuilder' demo just paste the XML into the TextArea on the right side and click restore and your layout will be restored.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/861336/splink.gif http://posterous.com/users/YrCv4f2LjPP maxmc maxmc
Tue, 29 Jun 2010 11:21:00 -0700 Using Hudson CI server to build multiple projects with FlexUnit4 tests on a windows box in parallel http://splink.posterous.com/using-hudson-ci-server-to-build-multiple-proj http://splink.posterous.com/using-hudson-ci-server-to-build-multiple-proj

Recently I setup the Hudson CI server for my splink projects. As Hudson is very well documented and super-easy to use, I had it up and running within less than 5 minutes. 1. Download the latest Hudson.war 2. Run Hudson "java -jar hudson.jar" 3. Install Hudson as a windows service


My next step was to add build jobs for the splink projects. For each project (splinklibrary, splinkresource and deepsplink I did 1. Add a "Free Style" job 2. Configure the source code repository (firstly I had to install the Hudson Mercurial plugin, but for instance SVN is supported out of the box. 3. Define when to run the job (i.e. every hour, after a commit, after another build, ...) 4. Add ANT scripts and define which tasks are to be run. (i.e. compile, run-tests, package, release, ...) 5. Define what to do after the ANT scripts have been successfully run. (i.e. publish documentation, publish test results, archive releases, ...) 6. Save the job


Now I could click the 'build button' and Hudson successfully built my project. Great!

But wait,.. Next I configured the three jobs to run every hour. But almost always one of the jobs failed. After looking at the console output of the failed builds I discovered the problem: The FlexUnit tasks communicate with the swf which runs the FlexUnit tests over a socket on port 1024. So if two jobs run at a time, they interfere with each other because both jobs try to use port 1024 when they run the FlexUnit tests. So I needed to assign unique TCP ports to avoid these port collisions and the Hudson Port Allocator Plug-in seems the best tool for the job. Just install it here With the port allocator in place I could allocate one or more ports for a job. My first solution was to just define port 1024 for each job and be done. Port Allocator then queues all the jobs which use port 1024 instead of running them in parallel. On the upside: No more failed builds. But on the downside the builds take longer, as they can't execute in parallel anymore. The answer to this was to make the Hudson Port Allocator Plug-in pick a free random port and convey the port to the build script. Because if each job is assigned with it's own port for the FlexUnit socket communication, jobs can't jam each other anymore.

Media_httpsplinkorgwp_aocey

Now I could grab the PORT enviroment variable in my build file and use it to configure the Hudson ANT task.

<property environment="env"/> <condition property="PORT" value="${env.PORT}" else="1024"> <isset property="env.PORT" /> </condition> <flexunit swf="${tests}/TestRunner.swf" toDir="${report}" haltonfailure="false" headless="false" verbose="true" port="${PORT}" localTrusted="true"> </flexunit>

But as the FlexUnit CIListener class also needs to know the port, I employed ANT's echo task to write the port number into a file:

${port} core = new FlexUnitCore(); core.addListener(new CIListener(port));

And to get the port inside my TestRunner class I had to just load the "port" file:

public function TestRunner() { var loader : QUrlLoader = new QUrlLoader(new URLRequest("port")); loader.register(QEvent.COMPLETE, function(e : QEvent):void { start(loader.getContent()); }); loader.register(QEvent.ERROR, function(e : QEvent):void { start(); }); loader.start(); } private function start(port : uint = 1024) : void { core = new FlexUnitCore(); core.addListener(new TraceListener()); core.addListener(new CIListener(port)); core.run(IntegrationSuite); }

* QUrlLoader is part of the splinklibrary project.

By checking the console output after running a build job I was able to verify that Hudson Port Allocator indeed picked different ports for each job:

Media_httpsplinkorgwp_cedpc
Media_httpsplinkorgwp_jgneq

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/861336/splink.gif http://posterous.com/users/YrCv4f2LjPP maxmc maxmc
Sun, 20 Jun 2010 12:27:00 -0700 googlecode: converting svn to mercurial http://splink.posterous.com/googlecode-converting-svn-to-mercurial http://splink.posterous.com/googlecode-converting-svn-to-mercurial

Just converted the splink googlecode repositories from svn to mercurial dvcs. (including the complete commit history) It worked like a charm once I figured that I had to use TortoiseHg's hg.exe to perform the conversion on my windows machine. TortoiseHg includes all neccessary extensions (python+svn bindings) and works out of the box. 1. Convert the library:

mkdir mylibrary hg.exe convert http://mylibrary.googlecode.com/svn mylibrary cd mylibrary hg.exe push https://mylibrary.googlecode.com/hg

2. Convert the wiki: mkdir mylibrary-wiki hg.exe convert http://mylibrary.googlecode.com/svn/wiki mylibrary-wiki cd mylibrary-wiki hg.exe push https://wiki.mylibrary.googlecode.com/hg

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/861336/splink.gif http://posterous.com/users/YrCv4f2LjPP maxmc maxmc
Sun, 14 Feb 2010 00:09:00 -0800 updates http://splink.posterous.com/updates-0 http://splink.posterous.com/updates-0

1. deepsplink 0.9.0 there are various new IRequestBuilder implementations to provide different page transition orders. Here is a quick configuration excerpt:

<pages request="hide-initshow-finalize"> <page id="home" clazz="Test" /> <page id="p1" clazz="Test" /> <page id="p2" clazz="Test" /> <page id="p3" clazz="Test" request="init-show-hide-finalize"> <page id="p4" clazz="Test" /> <page id="p5" clazz="Test" /> </page> </pages>

All pages beneath a page whose request attribute has been set are processed by the configured request until a page has configured a different IRequestBuilder which then is used to process the pages beneath that page. This mechnism is very flexible and should enable to cover a lot of requirements. However, you can always add your own custom IRequestBuilder implementations if the default ones don't suffice. The deepsplink configuration data classes now have a 'toXML' method which spits out the configuration xml recursively. The boot package now provides two default bootstrappers (ExternalConfigBootstrapper, XmlConfigBootstrapper) which should cover most usecases. For special requirements it is quick and easy to write a custom bootstrapper.

new ExternalConfigBootstrapper("config.xml", new BootStrategy(this)).start()

Finally the framework and sample codebase has been updated to use the latest splinklibrary and splinkresource releases (both 1.1.0) 2. splinkresource 1.1.0 The configuration data beans now have a 'toXML' method which spits out the configuration xml recursively just like the deepsplink configuration does. Finally the time had come to change all the explicit to implicit getters because implicit getters are more concise, hide more information from the client (is it a var or a method) and thus allow more changes without affecting client code because of public API changes ;) 3. splinklibrary 1.1.0 As deepsplink makes heavy use of splinklibrarys tree package some things needed improvement: The TreeUtils class has been removed and it's static methods were shifted to the Tree class which seemed much more compact and suitable. While at it I also added a static convenience methods

visit(node : INode, fnc : Function) : void clone(node : INode) : INode

Finally, to gain more flexibility for a low level component like a Node I decided to introduce the INode interface and use implicit getters.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/861336/splink.gif http://posterous.com/users/YrCv4f2LjPP maxmc maxmc
Mon, 14 Dec 2009 12:15:00 -0800 deepsplink 0.8.0 released http://splink.posterous.com/deepsplink-080-released http://splink.posterous.com/deepsplink-080-released

Over the last weeks I put some more work into my actionscript 3 deeplink framework deepsplink. In particular I - simplified the public API - refactored a lot of the internals - enhanced comments - updated the sample application - wrote a getting started tutorial based on the sample application If you want to find out how easy it is to create a flash application with full deeplink support, asynchronous page transitions and a modular and loosely coupled application design, then check out the getting started tutorial

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/861336/splink.gif http://posterous.com/users/YrCv4f2LjPP maxmc maxmc
Wed, 27 May 2009 14:19:00 -0700 deepsplink released http://splink.posterous.com/deepsplink-released http://splink.posterous.com/deepsplink-released

I'm proud to anounce the release of deepsplink, an actionscript 3 deeplinking framework. deepsplink provides a clear, flexible and easy to use api to build a scalable actionscript 3 application very quickly. The source code, the api documentation and a simple demo application which showcases the main features can be found at googlecode

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/861336/splink.gif http://posterous.com/users/YrCv4f2LjPP maxmc maxmc
Sat, 18 Oct 2008 18:22:00 -0700 splinklibrary feature demo http://splink.posterous.com/splinklibrary-feature-demo http://splink.posterous.com/splinklibrary-feature-demo

here is a quick demo class showcasing a few splinklibrary features. Please note that this example focuses on showing some splinklibrary features and it is not considered to be a best practice approach for loading and tweening an image. Also note that the demo is just a teaser, splinklibrary has a lot more useful concepts to offer. I recommend you to checkout the source and see for yourself.

package { import org.splink.library.loading.QLoader; import org.splink.library.loading.QUrlLoader; import org.splink.library.logging.ILogger; import org.splink.library.logging.ILoggerFactory; import org.splink.library.logging.LogLevel; import org.splink.library.logging.LogRange; import org.splink.library.logging.LoggerFactory; import org.splink.library.logging.LoggerProvider; import org.splink.library.logging.logoutput.DefaultOutputFormatter; import org.splink.library.logging.logoutput.FirebugOutput; import org.splink.library.logging.logoutput.QLogOutput; import org.splink.library.queue.Queue; import org.splink.library.queue.QueueEvent; import org.splink.library.queue.QueueResultProvider; import org.splink.library.queue.ResultQueue; import org.splink.library.tween.TweenAction; import org.splink.library.tween.TweenPool; import org.splink.library.tween.sprop.FilterProp; import mx.effects.easing.Sine; import flash.display.DisplayObject; import flash.display.Sprite; import flash.filters.BlurFilter; import flash.net.URLLoaderDataFormat; import flash.net.URLRequest; /** * This class demos the usage of some of the splinklibrary classes. * * @author Max Kugland */ public class Demo extends Sprite { private var _logger:ILogger; /** * Configure the logger once for the project */ private function configureLogger():void { // we need an ILoggerFactory, which will create our ILogger instances var factory:ILoggerFactory = new LoggerFactory(); // set a factory id factory.setId("demo"); // set the range of LogLevels which will be logged factory.setRange(new LogRange(LogLevel.TRACE, LogLevel.FATAL)); // set an IOutputFormatter to format our logmessages factory.setOuputFormatter(new DefaultOutputFormatter("demo-app")); // add ILogOuputs which will send the logs to their destination, // in this case we let the logs appear in QLog and in Firebug factory.addLogOutput(new QLogOutput()); factory.addLogOutput(new FirebugOutput()); // add the factory to the LoggerProvider LoggerProvider.addLoggerFactory(factory); // get an ILogger from the LoggerProvider using the ILoggerFactory // with the id "demo" _logger = LoggerProvider.getLogger("demo", Demo); } public function Demo() { configureLogger(); // log a message with the LogLevel INFO, as INFO is within the // specified LogRange, the message will get logged _logger.log(LogLevel.INFO, "starting Demo"); // Create a ResultQueue and register listeners for error and // completion events as ResultQueue is capable of distributing // events because it extends Distributor var queue:ResultQueue = new ResultQueue; queue.register(QueueEvent.ON_COMPLETE, onComplete); queue.register(QueueEvent.ON_ERROR, onError); // add a loader to the queue which loads xml and assign it an id //(feedResult) queue.add(new QUrlLoader( new URLRequest("http://splink.org/?feed=rss2"), URLLoaderDataFormat.TEXT, "feedResult")); // add a loader to the queue which loads an image and register a // listener for its completion event, also pass the queue instance // (q) to enable it's usage within the method which is called on // it's completion, (QLoader also extends Distributor and therefore // can fire events) queue.add(new QLoader( new URLRequest( "http://splink.org/wp-content/themes/splink/img/header.jpg"))). register(QueueEvent.ON_COMPLETE, onImage, queue); // start the queue queue.start(); } /** * Called when the image loader completes * * @param e the event sent by the image loader * @param q an optional object, in this case the queue */ private function onImage(e:QueueEvent, q:Queue):void { // unregister from the event source (the image loader) e.getSource().unregister(QueueEvent.ON_COMPLETE, onImage); // cast the event source (IDistributor) to QLoader var loader:QLoader = (e.getSource() as QLoader); // add the loaded image data to the stage, and set it's alpha // value to 0 var bmp:DisplayObject = loader.getContent(); addChild(bmp).alpha = 0; _logger.log(LogLevel.TRACE, "image present: " + bmp); // create a bitmapfilter which is used for tweening var fprop:ISpecialProp = new FilterProp(new BlurFilter(0, 0, 1)); // create a TweenPool and add some TweenActions targeting the // loaded image (bmp). tween the alpha from it's current value // (0) to 1 and tween the blurX and blurY properties of the image // from 100 to 0 var t:TweenPool = new TweenPool; t.add(new TweenAction(bmp, Sine.easeOut, 500, TweenAction.ALPHA, bmp.alpha, 1)); t.add(new TweenAction(bmp, Sine.easeOut, 500, TweenAction.BLUR_X, 100, 0, 0, fprop)); t.add(new TweenAction(bmp, Sine.easeOut, 500, TweenAction.BLUR_Y, 100, 0, 0, fprop)); // add the TweenPool to the end of the queue q.add(t); } /** * If one of the queued operations fails, we get notified here */ private function onError(e:QueueEvent):void { _logger.log(LogLevel.ERROR, "Demo error " + e.getErrorMessage()); } /** * As the queue continues even if a queued operation fails onComplete * gets called in any case. */ private function onComplete(e:QueueEvent):void { // as we used a ResultQueue we can retrieve a QueueResultProvider // which carries the results of the IResultQueueable items within // the ResultQueue. Note that the TweenPool is not an // IResultQueueable but an IQueueable, as it doesn't compute any // results, so the QueueResultProvider only holds the results of // both loaders (the image loader and the xml loader) var p:QueueResultProvider = (e.getSource() as ResultQueue).getResultProvider(); // here we retrieve the result with the id "feedResult" from the // QueueResultProvider and as we know its content is xml we cast // it to xml var xml:XML = XML(p.getResultById("feedResult").getResult()); // we log the title of the loaded xml document which is a rss feed // at the TRACE LogLevel and ouput that the demo is complete at //INFO level _logger.log(LogLevel.TRACE, "xml feed title: "+xml["channel"].title); _logger.log(LogLevel.INFO, "Demo complete."); // Eventually we invoke finalize on the event source which results // in removement of all the registred listeners e.getSource().finalize(); } } }

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/861336/splink.gif http://posterous.com/users/YrCv4f2LjPP maxmc maxmc
Tue, 16 Sep 2008 11:29:00 -0700 splinklibrary 0.2.0 and QLog 1.1 releases http://splink.posterous.com/splinklibrary-020-and-qlog-11-releases http://splink.posterous.com/splinklibrary-020-and-qlog-11-releases

I just relased a new version of splinklibrary. There are a few bugfixes, some performance improvements and several new features: - the logging framework is now prepared to address the new QLog features "tabbed logging" and "navigatable tree tabs"; If you use QLog you can send the current flash displaylist or the structure of any object to QLog which opens a new tab containing a navigatable tree of the displaylist or the object. - the tween engine is now more than twice as fast, flexible and extendable - there is a new "tree" package which makes working with tree structures quite convenient. For instance it is used internally to serialize the flash displaylist or any object into xml which can be sent via QLogOutput to QLog. For more details see the splinklibrary svn changelog To download the splinklibrary-0.2.0 release directly, click here or you can get it from the google code svn QLog now supports a new kind of tab, the "tree tab" which is capable of displaying any xml structure sent by a client as a navigatable tree. Note that you need splinklibrary-0.2.0 in order to use the "tree" feature. You can grab the QLog 1.1. release here

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/861336/splink.gif http://posterous.com/users/YrCv4f2LjPP maxmc maxmc
Mon, 01 Sep 2008 17:43:00 -0700 QLog update http://splink.posterous.com/qlog-update http://splink.posterous.com/qlog-update

I just added another couple of features to QLog and also made some major refactorings under the hood. Now Qlog enables you to change the font size, it provides keyboard shortcuts for everything, there is a new useful scroll-lock toggle button which helps if you want to read the logs while new log messages arrive. QLog also exports your logfiles now as valid xhtml 1.0 strict files and saves all settings like window position, size and various other settings on exit, to spare you from the pain to adjust the settings each time you start QLog. Furthermore it enhances working with log tabs by highlighting tabs which are currently not focused but contain unread messages. Get the latest QLog version here

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/861336/splink.gif http://posterous.com/users/YrCv4f2LjPP maxmc maxmc
Wed, 27 Aug 2008 10:31:00 -0700 New QLog release http://splink.posterous.com/new-qlog-release http://splink.posterous.com/new-qlog-release

Hi folks,

I recently became aware of a couple of features I really needed in QLog so I finally sat down to implement them. Because I am currently working on an application which consits of several modules, each with it's own logger, the view of all the modules log messages in one window became quite cumbersome to read. So I wanted to see the logs of the modules each in a seperate tab to be able to better distinguish between them. Today I finally implemented this feature and QLog is now capable of creating different tabs for each logger connection. Thanks to the new tabs the information is far better structured and reading logs from different modules is now quite convenient. Sometimes it's handy to save the logs to a file. That could be for instance to be able to compare the logs later, or simply to send them to someone else.  This can now easily be done through QLog's new save file feature, which renders a html file for the currently opened log tab. I also discovered and fixed a bug which occurred only with the flash player versions 9,0,124,0 or above, because these and future flash player versions need the server to send a socket policy file to the client in order to establish a connection. read more Well, that's it. You can download the latest QLog release here. Hopefully fsteeg will add the new features to his eclipse plugin version of QLog soon.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/861336/splink.gif http://posterous.com/users/YrCv4f2LjPP maxmc maxmc
Sat, 26 Jul 2008 10:41:00 -0700 splinkresource 0.1.0 framework released http://splink.posterous.com/splinkresource-010-framework-released http://splink.posterous.com/splinkresource-010-framework-released

splinkresource aims to ease the workflow with resources in actionscript3 multilanguage applications. It supervises the processing of resources by loading and registring display assets, fonts and class libraries. During resource loadtime it offers detailed information on the load progress of the currently loading resource but also on the overall resource load progress. Moreover it provides conventient access to the processed resources within your application. In particular splinkresource simplifies the development of actionscript 3 multilanguage applications by offering the concept of localized resourcebundles. Each resourcebundle contains information on and references to resources availible within the context of a locale. So the framework loads and provides only the resources needed for the specified locale. If your need to switch to another locale during runtime, you just pass the new locale to the framework and let it process the corresponding resourcebundle. Upon completion you have access to resources within the context of the new locale. Of course splinkresource integrates well into the splinklibrary queue system. For instance you can add splinkresource easily into your application bootstrapping. Because I believe in examples The rough workflow with splinkresource is to: - create an xml file based on the resourcebundles.dtd shipped with splinkresource. The file might look like:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE resourcebundles SYSTEM "resourcebundles.dtd"> <!-- Sample xml Note that id values MUST BE UNIQUE --> <!-- defaultLocale is the locale which is loaded by default --> <resourcebundles defaultLocale="de_DE"> <!-- For multilanguage applications define a resourcebundle for each locale --> <!-- locale defines the locale for the resourcebundle package --> <resourcebundle locale="de_DE"> <!-- path is the path to the asset files, relative from your applications root directory --> <assets path="assets/"> <!-- id is the assets id src is the assets source register defines a subclass of org.quui.resource.AssetRegister in which the assets are specified --> <asset id="sample assets" src="assets.swf" register="sample.SampleAssetRegister" filesize="16375" /> </assets> <!-- path is the path to the font files, relative from your applications root directory --> <fonts path="fonts/"> <!-- id is the name of the font type is the identifier which you use within your application to access a FontData object src (optional) the fonts source isSystemFont (optional) default value is false xOffset,yOffset (optional) enables to define a x/y offset for a specific font type sizeOffset (optional) enables to define a size offset for a specific font type --> <font id="Futura LT Condensed Bold" type="headline" src="futura_western.swf" filesize="26908" /> <font id="Arial" type="text" src="arial_western.swf" filesize="104710" /> <font id="Verdana" type="system" isSystemFont="true" xOffset="5" yOffset="5" sizeOffset="-3" filesize="0" /> </fonts> <!-- path is the path to the library swf files, relative from your applications root directory a quick way to get a library swf is to generate an swc (which in fact is a zip archive) and extract the swf within. To gain autocompletion for dynamically loaded class swfs: as fdt user you can add the swc as "runtime shared code" in your "fdt sourcefolder" tab or as flex user add the swc to the "flex build path" and switch the "default link type" for your swc from "merged into code" to "runtime shared library". These steps cause the compiler not to compile the code into your swf (because the code will be loaded during application runtime), but enable the editor to use the swc for autocompletion --> <libraries path="library/"> <!-- id is the librarys id src is the librarys source --> <library id="de.polygonal.as3ds" src="as3ds.swf" filesize="43654" /> </libraries> </resourcebundle> <resourcebundle locale="en_US"> <assets path="assets/"> <asset id="assetA" src="assetA.swf" register="DefaultAssetRegister" filesize="0" /> <asset id="assetB" src="assetB.swf" register="DefaultAssetRegister" filesize="0" /> </assets> <fonts path="fonts/"> <font id="Futura LT Condensed Bold" type="headline" src="futura_western.swf" xOffset="3" yOffset="3" sizeOffset="2" filesize="26908" /> <font id="Arial" type="text" src="arial_western.swf" sizeOffset="-2" filesize="104710" /> <font id="Verdana" type="system" isSystemFont="true" filesize="0" /> </fonts> </resourcebundle> </resourcebundles>

- use the org.splink.ant.filesizeinjectortask.jar ant task and integrate it into the build process. Have a look at the sample build file:

<?xml version="1.0" encoding="UTF-8"?> <!-- @author Max Kugland --> <project name="org.splink.resource.sample" default="build_sample" basedir="../"> <property file="build/build_${user.name}.properties" /> <!-- project folders --> <property name="dependencies" value="${basedir}/dependencies" /> <property name="build" value="${basedir}/build" /> <property name="sample" value="${basedir}/sample" /> <property name="xml" value="${basedir}/xml" /> <property name="source" value="${basedir}/src" /> <taskdef name="sizeinjector" classname="org.splink.ant.SizeInjectorTask" classpath="${basedir}/build/org.splink.ant.filesizeinjectortask.jar" /> <target name="inject" description="Inject file sizes into the resources xml file"> <sizeinjector file="${resourcefile}" resourcebasedir="sample" /> </target> <target name="build_sample_assets"> <exec executable="${flex.mxmlc}"> <arg line="-default-size 1 1" /> <arg line="-default-frame-rate=30" /> <arg line="-library-path '${flex3libsdir}'" /> <arg line="-default-background-color=0xffffff" /> <arg line="-source-path ${source}" /> <arg line="-output ${sample}/assets/assets.swf" /> <arg line="${source}/sample/SampleAssetRegister.as" /> </exec> </target> <target name="build_sample" depends="build_sample_assets, inject"> <exec executable="${flex.mxmlc}"> <arg value="-debug=true" /> <arg line="-library-path '${flex3libsdir}'" /> <arg line="-library-path '${org_splink_library}'" /> <arg line="-external-library-path+='${basedir}/${as3ds}'" /> <arg line="-default-size 640 480" /> <arg line="-default-frame-rate=30" /> <arg line="-default-background-color=0xffffff" /> <arg line="-sp ${source}" /> <arg line="-o ${sample}/sample.swf" /> <arg line="${source}/sample/SampleApplication.as" /> </exec> </target> </project>

- invoke splinkresource from within your application code, register a few listeners and let it do the work. splinkresource processes your resourcebundles.xml file, loads the neccessary resources for the given locale into the given ApplicationDomain and registres the the loaded resources. Meanwhile it provides you with infomation about the loading progress and upon processing completion you can access the resources within the given ApplicationDomain through the singleton class ResourceProvider.

package sample { imports... public class SampleApplication extends Sprite { public function SampleApplication() { // pass the path to the resourcebundles.xml, also pass the locale // for which to load resources, also register for various events var processor:ResourcebundleProcessor = new ResourcebundleProcessor("../xml/resourcebundles.xml", "de_DE"); processor.register(QueueEvent.ON_ERROR, onProcessError); processor.register(QueueEvent.ON_COMPLETE, onProcessComplete); processor.register(ResourcebundleProcessorProgressEvent.PROGRESS, onProgress); processor.start(); } /** * Invoked when the resource loading progresses, as you can see you * get provided with a lot * of information on the load progress */ private function onProgress( e:ResourcebundleProcessorProgressEvent):void { var progress:ResourceProgress = e.getResourceProgress(); var br:String = "\r\n"; trace(progress.getId()+" "+progress.getCurrentItem() + " / " + progress.getTotalItems() + br); trace( Math.round(progress.getCurrentItemBytes() / 1024) + "kb / " + Math.round(progress.getCurrentItemTotalBytes() / 1024) + "kb " + progress.getCurrentItemPercent() + "%"+br); trace( Math.round(progress.getTotalLoadedBytes() / 1024) + "kb / " + Math.round(progress.getTotalBytes() / 1024) + " kb " + progress.getTotalPercent() + "%"+br); } /** * Invoked when an error occurs */ private function onProcessError(e:QueueEvent):void { trace(e.getErrorMessage()); } /** * Invoked when the ResourcebundleProcessor completed its * processing */ private function onProcessComplete(e:QueueEvent):void { e.getSource().finalize(); testAssets(); testFonts(); } /** * Renders one of the assets defined in resourcebundles.xml to * the screen * Note that you can access assets trough the * ResourceProvider.getInstance().getAssetClassById method */ private function testAssets():void { var SplinkAssetClazz:Class = ResourceProvider.getInstance().getAssetClassById( SampleAssetRegister.SPLINK_ASSET); addChild(new SplinkAssetClazz()); } /** * Renders some fonts defined in resourcebundles.xml to * the screen */ private function testFonts():void { var fontData:FontData = ResourceProvider.getInstance().getFontDataByType("headline"); var textFormat:TextFormat = new TextFormat(); textFormat.size = 20; textFormat.font = fontData.getId(); var textField:TextField = new TextField(); textField.defaultTextFormat = textFormat; textField.autoSize = TextFieldAutoSize.LEFT; textField.htmlText = fontData.getId(); if(fontData.getIsSystemFont() != true) textField.embedFonts = true; textField.x = 0; textField.y = height + 20; addChild(textField); } } }

Note that there is a quickstart sample included in the release so you can easily start trying splinkresource. You can download splinkresource here

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/861336/splink.gif http://posterous.com/users/YrCv4f2LjPP maxmc maxmc
Sat, 28 Jun 2008 16:53:00 -0700 AsBeanGen - Generate value objects for DTD driven XML files http://splink.posterous.com/asbeangen-generate-value-objects-for-dtd-driv http://splink.posterous.com/asbeangen-generate-value-objects-for-dtd-driv

Update: moved asbeangen finally to a public repository
I fixed some of the bugs mentioned in the comments: - stripping '-' and '_' chars from the bean names - handeling recursive DTD - added 'implicit getters' mode - new option to generate interfaces ..................................................................................................................................................... AsBeanGen is a class generator application written in java which generates as3 data bean classes from DTD files. Overall it shortens development time a lot, because it rids you of spending a considerable amount of time on writing data bean classes. Instead AsBeanGen can generate hunderts of classes in less than a second for you and as an added bonus it doesn't just generate the bean classes, but also the classes which transform the content of an XML file (implementing the DTD) to data bean objects. So finally you just have to write two lines of code yourself to get a strongly typed object representation of an XML file. If you never heard of DTD (Document Type Definition), I suggest you to read this. As DTD doesn't support type information natively, you also have to annotate the DTD files through simple comments to add the neccessary type information, otherwise AsBeanGen uses 'Object' as the standard type.

To give you a more specific idea how it is used, let's jump straight into an example:
This is the annotated DTD file

<?xml version="1.0" encoding="UTF-8"?> <!ELEMENT test (size,fonts+) > <!-- Sets the types for the properties of the SizeData class TYPE size.width=int TYPE size.height=int --> <!ELEMENT size EMPTY > <!ATTLIST size width CDATA #REQUIRED height CDATA #REQUIRED > <!-- Sets the types for the properties of the FontsData class TYPE fonts.path=String Generates 'getFontDataById(id:String):FontData' method into FontsData class GENERATE font.id Generates 'getFontDataByName(name:String):FontData' method into FontsData class GENERATE font.name --> <!ELEMENT fonts (font+) > <!ATTLIST fonts path CDATA #REQUIRED > <!-- Sets the types for the properties of the FontData class TYPE font.id=String TYPE font.type=String TYPE font.name=String TYPE font.src=String TYPE font.systemfont=Boolean --> <!ELEMENT font EMPTY > <!ATTLIST font id CDATA #REQUIRED type CDATA #REQUIRED name CDATA #REQUIRED src CDATA #REQUIRED systemfont (true|false) #IMPLIED >


This is an xml file based on the DTD

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE test SYSTEM "test.dtd"> <test> <size height="100" width="100"/> <fonts path="fonts/"> <font id="foo" name="Arial" src="arial.swf" type="text"/> <font id="foo2" name="Arial2" src="arial2.swf" type="text2"/> </fonts> </test>


This is the generated FontsData bean class

package data.test { /** * Class generated by AsBeanGen * http://www.splink.org */ import data.test.fonts.FontData; public class FontsData { private var _path : String; private var _fontData : Array; public function FontsData() { } public function getPath() : String { return _path; } public function setPath(value:String) : void { _path = value; } public function getFontDataById(id:String) : FontData { var data:FontData; var r:FontData = null; for (var i:int=0; i<_fontData.length; i++) { data = _fontData[i]; if(data.getId() == id) { r = data; break; } } return r; } public function getFontDataByName(name:String) : FontData { var data:FontData; var r:FontData = null; for (var i:int=0; i<_fontData.length; i++) { data = _fontData[i]; if(data.getName() == name) { r = data; break; } } return r; } /** * @return an array of FontData objects */ public function getFontDataArray() : Array { return _fontData; } /** * @param an array of FontData objects */ public function setFontDataArray(value:Array) : void { _fontData = value; } } }


This is the generated FontsDataReader class for the FontsData bean class

package data.test { /** * Class generated by AsBeanGen * http://www.splink.org */ import data.test.FontsData; import data.test.fonts.FontDataReader; public class FontsDataReader { private var _xml : XML; public function FontsDataReader(xml:XML) { _xml = xml; } public function read() : FontsData { var fontsData:FontsData = new FontsData(); fontsData.setPath(_xml.@path); fontsData.setFontDataArray(readFontData()); return fontsData; } private function readFontData() : Array { var rAr:Array = []; for each(var xml:XML in _xml['font']) { var reader:FontDataReader = new FontDataReader(xml); rAr.push(reader.read()); } return rAr; } } }
This is what the generated structure looks like:

Media_httpsplinkorgwp_rhhmc

This is how to use the generated classes in your application:

 

// TestDataReader is the root reader and expects the loaded xml file // as a parameter. var reader:TestDataReader = new TestDataReader(xml); // TestDataReader's read method returns the root object of the // generated tree, filled with values from the given xml. var data:TestData = reader.read();


AsBeanGen can be used as a commandline application (usage shown below), or, if you are eclipse user you can add it as an 'External Tool' which proves to be very convenient (at least to me).

java -jar AsBeanGen.jar test.DTD C:\your\project\src de.your.package.name.test

Note that the "test" in the package name is the name of the DTD file.


How to add AsBeanGen as an 'External Tool' in Eclipse


1) Open your annotated DTD file 2) Open the 'External Tools'

Media_httpsplinkorgwp_emsfl

3) Create a 'New Launch Configuration' 4) Fill the form (see screenshot)
Media_httpsplinkorgwp_vcffd

4) After configuring AsBeanGen, you will want it to appear in the External Tools favorites. Switch to the 'Common' tab and check 'External Tools' within the 'Display in favorites menu' box. 5) Press 'Apply' button

Media_httpsplinkorgwp_fbthb

Now you should be able to launch AsBeanGen from the 'External Tools Favorites Bar'. Just make sure that the DTD from which you wish to generate the actionscript classes is opened and focused.

Download AsBeanGen

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/861336/splink.gif http://posterous.com/users/YrCv4f2LjPP maxmc maxmc
Fri, 30 May 2008 17:04:00 -0700 QLog + splinklibrary Logging http://splink.posterous.com/qlog-splinklibrary-logging http://splink.posterous.com/qlog-splinklibrary-logging

QLog is a java application which simply displays log messages. It enables to apply a filter to these messages so you can seek for a specific log or just display log messages which apply to the filter. Because QLog is in fact a socket server it is also possible to display logs sent from an application which runs on a remote server. (This can be very handy). The greatest feature in my opionion is that messages sent to QLog can be equipped with a color for each kind of message (that is trace,info,debug,warn,error,fatal,...), so the messages look well arranged.

Media_httpsplinkorgwp_dhevg

In the whole QLog is a lot like powerflashers superb SocketOutputServer SOS but in contrast to SOS it is platform independent, it also runs on Mac Os X or Linux. (I developed it because i wanted to migrate to Ubuntu and I simply couldnt live without something like SOS) QLog also integrates very well with the logging framework from splinklibrary. The splinklibrary logging framework comes with various ILogOutput implementations, so you can configure to which output destinations your logs are sent. splinklibrary supports TraceOutput, FirebugOutput, SosOutput and QLogOutput out of the box. So you dont need to worry about any low level socket implementation details if you use QLog with splinklibrary. One very useful feature of the sprinklibrary logging system is that if you run your application within the flash debug player, it adds the class- and methodname where the log originated from and if compiled with the -debug=true flag also the line number.

/** The Logger is configured once in a project. Each class which wants to log simply needs to add something like: private static const _logger:ILogger = LoggerProvider.getLogger("default", TheClassName); */ private function configureLogger():void { var factory:ILoggerFactory = new LoggerFactory(); /** It's possible to set various logger factories, so each one needs its own id */ factory.setId("default"); /** Logs within the specified range are sent to the log outputs */ factory.setRange(new LogRange(LogLevel.TRACE, LogLevel.FATAL)); /** DefaultOutputFormatter is used to format the log messages You can easily write and use your own IOutputFormatter */ factory.setOuputFormatter(new DefaultOutputFormatter()); /** Use different output strategies, here QLog and trace splinklibrary offers QLog, SOS, trace and Firebug LogOutput implementations. If you need something else, just implement the ILogOutput interface */ factory.addLogOutput(new QLogOutput()); factory.addLogOutput(new TraceOutput()); LoggerProvider.addLoggerFactory(factory); /** Get a Logger and log something */ _logger = LoggerProvider.getLogger("default", SampleApplicationClass); _logger.log(LogLevel.INFO, "Info"); _logger.log(LogLevel.DEBUG, "Debug"); _logger.log(LogLevel.ERROR, "Error"); }

Of course it should be quite simple to use Qlog with other Logging frameworks, or just to write a simple class to use it. splinklibararys QLogOutput should give a good impression how to do it. Currently there is a stable QLog standalone version Thanks to Fabian there is also a Eclipse Plugin version (very alpha) Update site: http://quui.com/update-site/ Here is a simple log4j appender class which enables to use QLog with the apache log4j framework for java.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/861336/splink.gif http://posterous.com/users/YrCv4f2LjPP maxmc maxmc
Mon, 26 May 2008 13:33:00 -0700 splinklibrary 0.1.0 relased http://splink.posterous.com/splinklibrary-010-relased http://splink.posterous.com/splinklibrary-010-relased

Today I released my actionscript 3 code library. It is the basic toolkit which I use in my as3 projects. The splinklibrary core features are: - event distribution - queues - reflection - logging (log4j style) - tweening (queue based) - loading (queue based) If you want to have a closer look at it check out the API docs splinklibrary is hosted at google code. You can check it out from the google code svn here: http://splinklibrary.googlecode.com/svn/trunk/

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/861336/splink.gif http://posterous.com/users/YrCv4f2LjPP maxmc maxmc
Sat, 24 May 2008 15:56:00 -0700 AS2 EventDistributor http://splink.posterous.com/as2-eventdistributor http://splink.posterous.com/as2-eventdistributor

Yes, I know, this is pretty old stuff, from the time before as3. Nevertheless I want to share my actionscript 2 event system for the unlucky fellows which still have to work with actionscript 2. If you know the as3 event system you will notice that EventDistributor is a lot like it, which should help to grasp quickly how to use it. Originally I built EventDistributor to overcome the shortcomings of the way events were handled in as2. In as2 there were a couple of event systems, most well known probably the mx.EventDispatcher. Neither of these event systems could satisfy my needs, so I came up with my own solution for event distribution. EventDistributor in contrast to the mx.EventDispatcher does not rely on static methods, it is glued to the class which needs to distribute events. Therefore it is destroyed when the class utilizing it is destroyed. This is quite convenient, because if you destroy the class which fires events, every listener which is currently attached to it is removed too, so there is no need to write stuff like myEventDispatcher.removeListener("onSomeEvent", eventTargetFunction) over and over again. mx.EventDispatcher is accessed trough static methods and therefore stores listeners in a static member array, which means that if you forget to remove a listener it will live on forever, which is pretty bad. Furthermore EventDistributor encourages the usage of constants like Event.ON_COMPLETE rather then Strings like "onComplete" and is therefore much more error resistent. EventDistributor provides all neccessary information for removing eventListeners with every distributed event. So you do not need to save function variables as class members to be able to remove listeners - you can remove them immediately after catching the event or remove all listeners by finalizing the class which makes use of the distributor. EventDistributor distributes typed events, not generic objects like mx.EventDispatcher does. Because the events are typed you dont get into trouble when bubbeling events trough an application; Because EventDistributor encourages to create custom events by extending the Event base class or implementing the IEvent interface you always know about your events at compile time. Well after the theory its time to have a look at how it is actually used:

/** * The class which makes use of EventDistributor to distribute events **/ class DistributingClass implements IDistributor { private var _eventDistributor:EventDistributor; private var _targetMC:MovieClip; public function DistributingClass(targetMC:MovieClip) { _targetMC=targetMC; _eventDistributor=new EventDistributor(); _eventDistributor.initialize(this); _targetMC.onRelease=Delegate.create(this,distribute); } private function distribute():Void { // ReleaseEvent extends Event or implements IEvent distributeEvent(new ReleaseEvent(ReleaseEvent.ON_RELEASE, "event_ID")); } private function addEventListener(type:String,func:Function){}:Void private function removeEventListener(type:String,func:Function){}:Void private function distributeEvent(eventObject:IEvent){}:Void } /** * A custom event class which is distributed by DistributingClass **/ class ReleaseEvent extends Event { public static var ON_RELEASE : String="onRelease"; private var _id:String; public function ReleaseEvent(type:String,id:String) { super(type); _id=id; } public function getId():String { return _id; } } /** * A class which listens for ReleaseEvent objects distributed by * DistributingClass **/ class Listener { private var _distributingClass:IDistributor; public function Listener(distributingClass:IDistributor) { _distributingClass = distributingClass _distributingClass.addEventListener(ReleaseEvent.ON_RELEASE, Delegate.create(this, onRelease); } private function onRelease(event:ReleaseEvent,listener:EventListener) :Void { // in the case you want to unsubscribe immediately after the // event is caught: _distributingClass.removeEventListener(ReleaseEvent.ON_RELEASE, listener.getFunction()); trace("event caught: "+event.getId(); } public function finalize():Void { // in the case you want to destroy the class distributing events and // automatically remove all listeners _distributingClass.finalize(); } }

Download EventDistributor

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/861336/splink.gif http://posterous.com/users/YrCv4f2LjPP maxmc maxmc
Sat, 24 May 2008 11:09:00 -0700 DuDe http://splink.posterous.com/dude http://splink.posterous.com/dude

Recently I discovered an interesting tool called DuDe. The author Richard Wettel describes DuDe as a 'text-based, language-independent code duplication (code clones) detector, gravitating around the concept of duplication chain.'

Media_http8914919479s_tbafa
It is pretty simple to use; you start the jar, select a projects source folder and select the algorithm you want DuDe to use. Upon completion you can browse the results and learn which parts of your code could do with some optimizations. I guess there are much more powerful tools for specific languages like java, but what makes DuDe shine brightly in my opinion is that it is language independent. So it works very well for actionscript source code or any other plain text files.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/861336/splink.gif http://posterous.com/users/YrCv4f2LjPP maxmc maxmc