Techblog

Tech Blog

Our latest geek adventures!

6 November Drag’n'drop from HTML to Flash

Last week we released a new Floorplanner account, the Enterprise account. With it, companies can have an online Floorplanner solution completely branded to their wishes. It includes the Roomplanner module and a custom library of their own furniture elements.  Steelcase and Maxon are the first to have an active Enterprise account.

The interesting part of this release, from a tech point of view, is the new drag-and-drop functionality. The Roomplanner is running in the Flash Player. However, the library of furniture elements is in HTML. We chose to build the furniture library in the HTML sidebar for a couple of reasons. It’s not in the Roomplanner, so there is more space left to design. It gives us more freedom in the page layout. All items on the page are indexed and things like sorting and tags we’re easier to build in Ruby on Rails than in Flash.

Now we only needed a way to get the furniture from the sidebar to the Roomplanner. That’s where the drag’n'drop comes in, drag from HTML and drop in Flash. To drag an image of a furniture element in HTML we used the fantastic JavaScript script.aculo.us framework. The next step was to swap the image to an element in the Roomplanner and to update the position of the element while moving the cursor on the Flash content. For this we used ExternalInterface to communicate between JavaScript and ActionScript. That’s all there is to it. The theory is actually quite simple, but in practice it was very (I repeat, VERY) difficult to get it working in all the main browsers. All those nitty gritty browser details…

At this moment everything seems to work just fine, so please take a look at Steelcase and/or Maxon and let me know what you think!

Tags: , , , , , , | 1 Comment »

22 October Printing & Big Bitmaps

Last week I started working on a new version of the print functionality in Floorplanner. The problem with the previous version was that it didn’t print shadows, it was impossible to rotate the plan to landscape and textures didn’t look very well. Overall it produced a very mediocre image compared to the visual quality of a plan on the screen. As can be seen below:

Old print output

Old print output

For printing we use the AS2 PrintJob class, which works really easy, with a small disadvantage: it doesn’t print Floorplans properly. I tried all kinds of settings for this class, with as input just a MovieClip with a drawing of the plan on it. I tried setting the printAsBitmap to true and false, both giving the exact same result. So although being stuck with it, the printAsBitmap boolean inspired me to investigate the Bitmap thing. We already had an image export utility, which produces images of a Floorplan with the same quality as it is shown in the FlashPlayer. The funny thing is that when I printed this exported image, the print quality was really good, at least a lot better than our own printing functionality. So for some reason, even if I used the printAsBitmap functionality, it still didn’t produce the same quality as using a real bitmap.
Of course we could have stopped here and just tell the users of Floorplanner to print the exported image. But since we are Floorplanner, we didn’t want to introduce another step requiring user action in the printing process, after all, we are the “easiest way” :-).
So I decided to use the same BitmapData created for the image export as basis for the printing. The first results where rather disappointing, I attached the created BitmapData to a MovieClip which in turn was given to the PrintJob. The produced print was of really low quality, you could easily see pixels all over the place. I tried using more pixels but now I bumped into the pixel limit of BitmapData (2880×2880 pixels). To work around this I invented the BigBitmapData class, this is a wrapper class that mimics the functionality of the BitmapData class, but which doesn’t have an upper limit of the number of pixels which can be used. When an instance of BitBitmapData is created which is bigger than 2880 by 2880, it creates additional BitmapDatas to store the additional pixels needed. So in fact the BigBitmapData internally stores an two dimensional array of BitmapDatas to bypass the pixel limit.
So with this new class I was able to scale up the created image to unprecedented sizes. I did a lot of printing experiments with scaling of the input, I tried scaling settings from 2 times to more than 10 times! This huge bitmap was attached to a MovieClip which in turn had to be scaled to fit on one single page of the printer. These values did give a better result, but still not good enough. It turned out that I had to take the DPI of the printer into account. The optimal scale factor turned out to be (1 / 72) * 300. The 72 is the DPI of the screen, and the 300 is the DPI of the printer. Furthermore a ‘point’ (print unit of measurement) is 1/72 inch, while the size of a pixel (screen unit of measurement) is dependent on the resolution of the screen.
So what this method actually does is creating a big image (which is resized to the paper contents) with enough quality to be printable on a 300 DPI printer.

New print output

New print output

So as you can see in the second image above, the new print looks a lot better, and since the new print uses bitmaps it is really easy to rotate it to always produce a print that tries to fill the entire paper.

A disadvantage of this method is that it takes quite some computational power to compute all the pixels for the bitmap that is created in memory, so as a result the FlashPlayer and sometimes even the browser freezes for a moment. Although this isn’t very good, we thought this behavior is acceptable since the quality of the prints is much better than the previous ones and the freeze time is actually really short. If you are not convinced by the images (which is understandable since the quality difference can only be seen on paper), just check it out!

Tags: , , | No Comments »

21 September HTTP status exception handling plugin

Some time ago, I wrote about putting HTTP status code to use for your Rails application. For my reinvigorated project, I wanted to apply the same technique. Instead of re-implementing it once again, I created a Rails plugin called http_status_exceptions to easily add this functionality and I have put it on Github. For more information on how to install and use the plugin, see the project’s wiki.

Tags: , , , , , | No Comments »

20 September Batch file renaming

I just started working on an old Rails project after having neglected it for 15 months. Most of the view files still had the good old .rhtml extension. I was too lazy to rename these files by hand, both on my file system and in the git repository. I used the following Bash commands to do the job:

First, I renamed all the partials to the .erb extension. Note: I am not using .html.erb, as some of these partials are used in js-formatted responses as well:

for i in `find app/views/**/_*.rhtml`; do 
  git mv $i `echo $i | sed s/\\.rhtml$/.erb/`; 
done

The remaining files could now be renamed to .html.erb with a similar command:

for i in `find app/views/**/*.rhtml`; do 
  git mv $i `echo $i | sed s/\\.rhtml$/.html.erb/`; 
done

Note that this technique works with Subversion as well: just substitute git with svn in the command above. A regular rename is possible as well by leaving out git altogether!

Now my file names are Rails-compliant again, I can start refactoring all the code that is not up to current Rails standards anymore. Ah, the virtues of developing with a rapidly evolving framework…

Tags: , , , , , | No Comments »

16 September Converting a Rails application from Gettext to I18n

Posted by jaap in Ruby on Rails, i18n

Last week we had to convert our existing Rails application, which uses Gettext to the new I18n API in combination with the SimpleBackend. I personally never liked Gettext, there was simply not enough control over translations as PO/MO files are not native ruby or at least can be easily accessed by Ruby (like YAML files).

We therefore decided to switch to the brand new, not even released, I18n API. But now we had a serious problem, our code base isn’t small and all that code had to be converted in some way. We could do it by hand, but hey, that’s a lot of work and especially very error-prone. Some convertor had to be written. Here it is as a rails plugin: GettextToI18n. 

What does the I18n convertor do?

It scrapes your whole application and searches for gettext calls, like this:

_("to be translated")

It will convert this gettext call to the newly I18n format: 

I18n.t :message_id

Then it builds up a big hash containing all the the translations. We decided it was handy to use the scopes that are introduced in the new I18n api. So it stores the translations in the following format: 

For models:

["model"]["model_name"]={:message_1 => "to be translated"}

For controller:

["controller"]["controller_name"]={:message_1 => "to be translated"}

After this hash of translations has been built up, the convertor writes it as a YAML file to:  config/locales/template.yml.That’s all!

What’s supported?

It supports basic gettext calls. We have run it over our code base and it converts all gettext calls we use without any problem. 

A normal gettext call

_("to be translated")

converts to:

I18n.t :message_0, :scope => [:txt, :controller, :controller_name])

 

A gettext call with variables

_("My name is %{name}" % {:name => "Jaap"})

converts to:

I18n.t :message_0, :name => "Jaap", :scope => [:txt, :controller, :controller_name])

 

A gettext call with variables that contain gettext calls

_("Click %{link} to go to the homepage" % {:link => link_to(_("Here"), root_path)})

converts to:

I18n.t :message_0, :link => link_to(I18n.t(:message_1, :scope => [:txt, :controller, :controller_name]), root_path), :scope => [:txt, :controller, :controller_name])

 

Installation

./script/plugin install git://github.com/japetheape/gettext_to_i18n.git

Usage

To convert your application:
rake gettext_to_i18n:transform

Please make sure you backup your complete application as it can screw things up.

Contribution

Please contribute to this plugin and make it better, as I won’t use it anymore, cause we are not going to convert another time (I think ;-)). Things that has to be done are:

unnamed variables:

_("I play the %s" % "saxophone")

Go to the development location at github and fork this plugin!

Tags: , , | 5 Comments »

13 September Remote branches in git

I have been using git for a while now, and I believe I have the the basic workflow under control. Committing, reverting, using local branches for major refactoring work: been there, done that! ;) However, I recently got some collaborators on my github-projects, I had to start working with other remote repositories and branches.

I found this blog post, which was really helpful. I am sharing some others things that helped me in the last couple of weeks. Hopefully, this saves other people some time Googling. If you know a better ways to accomplish these tasks, please let me know!

Things to remember about remote branches

Because I had some troubles discovering how to properly work with remote repositories, I am sharing what I found. The most important things to remember:

  • Your local branches are not really connected to the remote branches. It is therefore possible to mix up branches, but this is usually not what you want :-)
  • Never forget to switch to the correct local branch (using git checkout local-branch.
  • The names of the local and remote do not need to match.
  • Before you can push changes from a local branch to a remote branch, all the commits of the remote branch have to be included in your local branch. This can be done using by executing git pull remote-name remote-branch in your local branch.

Checking out a newly created branch in a remote repository

Bart is implementing Merb log parsing for request-log-analyzer. He has put his progress in a separate branch of the github project. My local repository does not yet include this branch, but I want to check it out. Note that I am using a different name than the branch name on the github project.

$ git branch merb origin/generic_base
$ git checkout merb

When the new functionality is finished, the following commands will merge the changes in the merb branch to the master branch.

  # goto my local master branch and merge the merb-branch
$ git checkout master
$ git merge merb
 
  # push the changes to the master branch on github
$ git push origin master

Merging back a fork

Wes Hays is helping me out on the scoped_search plugin. He implemented OR in the query language in his own fork. I wanted to merge his changes back to master branch:

  # add a reference to the remote repository
$ git remote add gbdev git://github.com/gbdev/scoped_search.git
 
  # create a local branch for the fork to follow a remote branch
$ git branch gbdev-fork gbdev/master
$ git checkout gbdev-fork

Now, my local gbdev-fork branch contains Wes’s code. Because Wes’s repository was forked from my repository, git will know that most of the history of my master branch and gbdev-fork branch is the same.

After some testing, I was ready to include his changes by merging the gbdev-fork branch into my local master branch:

  # go back to my master branch, and merge the changes
$ git checkout master
$ git merge gbdev-fork
  # push the changes to the master branch at hithub
$ git push origin master

Pushing tags to a remote repository

You can create tags locally, but you probably want to send them to the remot repository as well:

  # create a local tag "tagname" with the given message.
$ git tag -a "tagname" -m "message" 
  # send your tags to the remote repository "origin"
$ git push origin --tags

Tags: , , , | No Comments »

12 September New cross domain findings

Today I learned a couple of new things about the use (and trouble) of BitmapData in combination with loading content from other domains. I thought we solved it a while ago, but it in some situations it didn’t work… I definitely hope this is my last post about the subject!

When you load content from another domain and you want to use BitmapData, then you always have to load a policy file (crossdomain.xml) from that other domain. What I discovered today is that you have to do this for ALL the content you’re loading, otherwise the BitmapData just doesn’t work. Even if it’s content you don’t want to use for the BitmapData, you still need to load the policy file. It took me quite a while of debugging to figure this out.

This is our current setup. Every server has its own domain.

The other thing I learned today is a small trick to remove the Warning in your logs. Jeffry Houser explains it in his post Fixing your CrossDomain.xml File.

Tags: , , , , | No Comments »

29 August Rails log analyzer matures

Since I announced rails-log-analyzer some weeks ago, quite a lot has happened! Apparently there is some interest in such a tool: on this blog we get a lot of traffic looking for more info, the github project already has 22 watchers and it even has been forked!

In the mean time, Bart and I worked hard to add new functionality and refactored the internal design. As a result, I have released request-log-analyzer 0.1.0 today!

Changes: 

  • The project is renamed to request-log-analyzer, because we plan to support log files from other frameworks as well; Merb is planned to be supported in the near future.
  • The tool is distributed as a gem, making it much easier to install and update.
  • More reports, colorized output, parsing progress bars, command line arguments, etc…
  • Added a tool to create a SQLite database with all the parsed info from the log file, so you can do your own analysis.

Installation:

gem sources -a http://gems.github.com
sudo gem install wvanbergen-request-log-analyzer

Usage:

request-log-analyzer  [LOG FILES*]
request-log-analyzer -c 20 -z log/production.log

Please let me know what you think! If you have any problems using the tool, do not hesitate to contact me!

Tags: , , , | 5 Comments »

15 August Rails log analyzer

My friend Bart from movesonrails.com just blogged about Rails log analyzer, a command line tool to get performance statistics for your Rails application by parsing its log file.

What started as an exercise for me to write a command line ruby program, has been extended and improved by Bart to be actually useful! We decided to release it under an MIT license. You can found the source on github. The project’s wiki contains usage information and an example of the output it will produce.

Tags: , , , | 5 Comments »

31 July Lighten up your development with Lighthouse

Posted by Gert-Jan in Development

Over the last year we’ve tried a lot of different applications to keep track of bugs and other issues, but none of those apps sticked with us. They were either not suited for the job (Basecamp) or to difficult and ugly (Trac, Bugzilla). But now I think that we finally have found a solution that just gets the job done: Lighthouse by activereload.

Lighthouse ticket scoreboardLighthouse’s tagline is “beautiful simple issue tracking” and that really sums it up perfectly. It tracks issues, not only a bugs, so you can use it for all the issues that need to be dealt with. It’s simple and it’s easy to use, it just does what it needs to do without loads of unneeded features. A great advantage for us is that our designers can (and want) to use it too. It’s also very nicely priced and it has a sweet API for us geeks to build your own scoreboard :-D (see picture).

There are some minor things that can be improved (for example, it’s somethings a little confusing to work with multiple projects) but it’s by far the best issue tracker I’ve ever worked with. To everybody at activereload, we really love your product and keep up the good work!

Tags: , , , | No Comments »