Wednesday, December 14, 2011

Doing that cool reflection thing....

We've all seen applications, websites, tv advertising, logos, etc. that have a reflection under them. It's the new cool thing to do. I'm sure there are probably many ways to do this, but I'll share in this blog one way that I did it with my GWT based application.

I'll start with the end result that I achieved...our login dialog box:



First, I built a panel that has a background gradient and rounded edges on the border. It's a GWT FlexTable with a css style setup.

final FlexTable loginFlex = new FlexTable();
loginFlex.setStyleName("my-DialogStyle");

Inside my CSS file, I have:

.my-DialogStyle {
background: #FFFFFF;

filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFF', endColorstr='#999999'); /* IE compatible */
background: -webkit-gradient(linear, left top, left bottom, from(#FFFFFF), to(#999999)); /* Webkit compatible */
background: -moz-linear-gradient(top, #FFFFFF, #999999); /* Firefox compatible */

border:1px solid #666666;
border-radius: 8px 8px 8px 8px;
-moz-border-radius: 8px 8px 8px 8px;
-webkit-border-radius: 8px 8px 8px 8px;

padding: .5em 2em .5em 2em;
}

Once I had this working and appearing on the screen, I then needed to make the reflection. To do this, I found this web site:


http://www.generateit.net/reflection/index.htm

You load up your image, which for me was a screen shot of my login dialog. You pick how much reflection you want (I picked 20%) and your background color (which for me was white). The web site generates a PNG file that you can save.

In my case, I only wanted the reflection part of my image, so using a graphics tool (like Photoshop, or PaintShopPro or Gimp) I captured the reflection part into a new PNG file:




The last step was to draw my reflection on my screen "attached" to the bottom of my login dialog box and center this on my screen too. I used a LayoutPanel to hold my FlexTable and my reflection image:

final Image reflection = new Image(loginreflection());
final LayoutPanel mainPanel = new LayoutPanel();
mainPanel.add(flexPanel);
mainPanel.setWidgetTopHeight(flexPanel, (Window.getClientHeight() / 2) - (flexPanel.getOffsetHeight() / 2), Unit.PX, flexPanel.getOffsetHeight(), Unit.PX);
mainPanel.setWidgetLeftWidth(flexPanel, (Window.getClientWidth() / 2) - (flexPanel.getOffsetWidth() / 2), Unit.PX, flexPanel.getOffsetWidth(), Unit.PX);

mainPanel.add(reflection);
mainPanel.setWidgetTopBottom(reflection, (Window.getClientHeight() / 2) + (flexPanel.getOffsetHeight() / 2) + 1,Unit.PX, 0, Unit.PX);
mainPanel.setWidgetLeftWidth(reflection, (Window.getClientWidth() / 2) - (flexPanel.getOffsetWidth() / 2), Unit.PX, flexPanel.getOffsetWidth(), Unit.PX);

For a really cool effect, you can also add:

mainPanel.animate(1000);

but animation is for another blog. Enjoy!

Saturday, October 1, 2011

GWT Tricks #2

I want to have a dialog box or a display on my screen where the user can just hit the "Return" key and not have to click on my OK button. It might be a data entry form and they are typing, tabbing, typing, tabbing and should not have to take their hands off the keyboard to finish...just hit Enter or Return.

To do this, you'll need to create a class for your button that listens for a Key down. Here's how:

1. First create a class that you can reuse on any form or display you like:

public class ButtonPressListener implements KeyDownHandler
{
private final Button button;

public ButtonPressListener(final Button button)
{
this.button = button;
}

@Override
public void onKeyDown(final KeyDownEvent key)
{
if (key.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER)
{
button.click();
}
}

}
This class will see a KeyDown event, check that it was the Enter key and then press your button. So if you pass in your default button or OK button, it gets activated when the user presses enter. Here's how:

First create your button -
private final Button    okButton     = new Button();
okButton.setText("OK");
Now create your listener, passing the button you want activated when the user hits Enter -
final ButtonPressListener listener = new ButtonPressListener(okButton);
Now, if your dialog box or form has other input fields, you want each of them to see an Enter key press and activate your OK button. In this example, we have a username and password field on our screen:
usernameTextBox.addKeyDownHandler(listener);
passwordTextBox.addKeyDownHandler(listener);

Now that you know how to setup a key listener, you can create all sorts of conveniences for your user and let them fly through your UI screens.

Thursday, September 22, 2011

GWT Tricks #1

I've decided to post any "tricks" or common GWT mistakes that I've run into, researched and fixed. Hopefully these will be helpful to the next person who sees the same errors, researches the same information and wonders which fix to "try".

The SafeHTML warning

Ever see these warnings when running your GWT application?
[WARN] Template with variable in CSS context: The template code
generator cannot guarantee
HTML-safety of the template -- please inspect manually
What does this mean? How do I fix it?

Basically, it is telling you that you have inserted an "include" in your code to something in a .css file. Look for something like this:
sb.appendHtmlConstant("<div class=<\"myapp-CellSelect\">");

Where the myapp-CellSelect happens to be defined in your myapp.css file. Since you are bringing something in from "outside", the code generator can't insure it's going to work. That "outside" thing may be broken, missing, or malformed and is a bug waiting to happen.

So, what to do?
Remove this external reference and put it inline with your div. So, let say your: myapp-CellSelect is:

.myapp-CellSelect {
text-decoration:underline;
cursor: pointer;
}

then your code should look like:
sb.appendHtmlConstant("<div style=\"text-decoration:underline;cursor:point\">");
You no longer are pointing to something in your .css file and the warnings will now be gone.


Auto Selecting an Input Field

When implementing data input screens, like popup dialog boxes for example, you sometimes want to set the focus in the dialog box to something meaningful. Maybe this data entry screen has a Name field followed my other input fields. It might be nice to automatically select the Name field for the user so that they can just start typing when this popup opens. In typical application programming, you can just set the Name field as the initial focus field and it works, however, with web/GWT programming, this will not work as you expect.

Take this example:

TextBox nameBox = new TextBox();
nameBox.setFocus(true);

build the rest of your fields, populate them with data and then show() the dialog. The nameBox is not highlighted, not focused on, not ready for user input until they click on it. Why? Because the setFocus must be called after the dialog box has been rendered. Ok, so what to do?

In the code that will do the: dialog.show(); call, set the focus to the field you want when the system is not busy, meaning right after it has rendered your dialog. How? Like this:

Scheduler.get().scheduleDeferred(new ScheduledCommand()
{
@Override
public void execute()
{
nameBox.setFocus(true);
}
});

dialog.show();

Remember, with GWT there are a lot of async operations that might happen. In my case, I make calls to my database to fill in my dialog and then once they have completed, I show my dialog. Had I tried to setFocus at the beginning, it would have failed. Setting focus at the end works.

Tuesday, September 13, 2011

Patent Issued

Today I received notice that my name was included on a patent. The process was long, the company actually came and went during the whole process, but still, it happened, it's permanent and it's kinda cool. At least to me...

I'm including a link to the patent details here and I truly don't remember all the ins and outs of the algorithm, but I'll try to describe it here.

The Patent

As a UI developer, I'm always worried about keeping the data I'm showing up to date. Almost all systems require multi-user support and once someone sees stale data or worse, tries to edit it, all heck breaks loose. Your application takes a hit, your users start to feel worried about the data integrity and you'll scramble to try and "fix" it.

From the UI point of view, your widgets, tables, trees, views should be backed by "backing" data in the form of some kind of data model. Processes need to be in place to keep that "backing" data up to date and then your widgets need to react to that data changing and do the right thing. This is usually achieved with some kind of polling or pushing. When done right, your users will be amazed and feel very good about the application.

At Quarry Technologies, a secure router was being developed with a configuration CLI (command line). The UI application would need to latch on to a router and push configuration commands at it. Now what happens if someone were to telnet into the router, get onto the command line and start making configuration changes? The UI would be instantly out of date. The configuration screens and data would be stale. The rules engine for validating configuration changes wouldn't be useful, etc. And what if there were multiple UI's and multiple command line jockeys all going at it. Chaos would ensue! and it did....

How to solve this? What if there was a way for the router to tell everyone interested about configuration changes? After all, the router held that final configuration at all times and insured consistency. So we developed a way for the router to essentially "echo" out to all listeners configuration changes as they were accepted and processed. Now the UI application could setup a listener and process configuration changes coming from the router. This sounds simple enough, but there was more to it than that....you can read the goodies in the patent....but in a nutshell, the ability for our router to intelligently push out a consistent state of its configuration to all listeners was the big deal.

So I guess someday my kids, grandkids, etc. can look me up on Google or whatever the worldwide search engine will be and see my name on a patent. Here's to more to come....

Thursday, August 18, 2011

Internationalization/Localization From the Start

The title says it all. "...From the Start". Don't wait until someone wants to know if your application works with a foreign language to do the work. Retrofitting and removing strings etc. will drive you nuts and will be very unproductive. Instead, put the processes in place at the start so that your answer to their question is "Yes, of course, always has...". Here's some gory details on how, and how nice GWT is in doing the hard work for you:


Determining Locale


Before any of the following code examples will take affect, the system must know what locale it should be running against. This is done by adding the languages you support in your gwt.xml file. For example, to support English add:

<extend-property name="locale" values="en"/>


To add support for another language, say Spanish, add:


<extend-property name="locale” values="es”/>



To include the internationalization code into our Gwt application, we must add:
<inherits name="com.google.gwt.i18n.I18N”/> to our gwt.xml file.


The system will look at the locale running locally on the machine running our application and will tie that to the locale property. If the system sees “es” as the locale, then the application will automatically pick up the Spanish files. If we had created OurStrings.properties and OurStrings_es.properties, then the first file is used by default and the second is used if the locale matches “es”.





Internationalization


To implement an international scheme, we will use static string substitution to make the coding easier and to make the compiled javascript smaller and quicker. The process is as follows:


1. Create a properties file - AppMessages.properties, in the main client folder. This file has ids to strings such as

fileMenu = File

editMenu = Edit

helpMenu = help


2. Create a java interface class of the same naming - AppMessages.java in the main client folder. This file implements the properties file strings:


public interface AppMessages extends Messages
{
String fileMenu();

String editMenu();

String helpMenu();

}

there must be a method for each entry in the properties file.


3. In the main class that runs at startup, in the onModuleLoad() method, construct the class as:


AppMessage msgs = (AppMessages) GWT.create(AppMessages.class));


4. Now you can use the msgs class to find strings such as:


msgs.fileMenu(); which will return “File”.

msgs.editMenu(); which will return "Edit" and so on.



To pass parameters on strings, the properties file would have:
hello = hello {0}


The interface would be:
String hello(String who);


The call would be:
msgs.hello(“Eric”); which will return “hello Eric”.




Localization


Localization deals with the display of dates, times and numbers. Dates displayed in English using month/day/year are displayed differently in other countries, sometimes like day/month/year. So, 5/24/2001 in the US would be displayed as 24/5/2001 in England. Times should be displayed according to the timezone and numbers displayed according to the country formatting where decimal points and comma’s are sometimes intermixed. Gwt has automatic classes built in to support localization. Yes automatic. Based on the locale for the application, the dates, times, currencies will be translated for you:


Data today = new Date();
Wednesday Mar 23 12:11:44 UYT 2011


DateTimeFormat.getFullDateFormat().format(today);
Wednesday, March 23, 2011


DateTimeFormat.getFullTimeFormat().format(today);
12:11:44 PM Etc/GMT+3


There is also Long, Medium and Short formats as well.
DateTimeFormat.getShortDateFormat().format(today);
3/23/11
DataTimeFormat.getShortTimeFormat().format(today);
12:11 PM


For numeric displays, similar builtin Gwt classes are available:
double number = 22919.60;


NumberFormat.getDecimalFormat().format(number);
22,919.6


NumberFormat.getPercentFormat().format(number);
2,291,960%


NumberFormat.getCurrencyFormat().format(number);
$22,919.60


GWT does a lot for you here. There's no excuse to not take advantage of this. Yes, the world puts up with English software for sure, but the goodwill you get for having localized and internationalized applications might just get your company a lot more sales.


Monday, July 18, 2011

Everyone on the Bus

When doing UI development, we all know that we have to deal with callbacks. Callbacks when a mouse button is pressed, callbacks when the screen is resized, callbacks when a menu item is selected, callbacks for just about anything that can happen on your screen.

When designing a well structured piece of software, using object oriented techniques, we will end up with a nice hierarchy of classes, each with their own responsibilities and scope. Traditionally, we would build something like a menu class which handles all the menu creation and callbacks. For example, say someone picks the Help menu. This class gets the callback and launches the help system. But lets say that we want to put help buttons all over our application and give the user the option to get help on a variety of things. This would mean that the menu class would have to be passed around to all the other classes so that the various help buttons could trigger different help system displays. Or we could create one big master class that everyone has access to....but this begins to breakdown, means a lot of parameter passing and just starts to become spaghetti code. Not what we want to maintain.

So what is our option? The Event Bus, aka HandlerManager. What does this do you ask?
Quite simply, the event bus lets our client "fire" an event in one piece of code to be caught and handled by any other piece of code that is listening for this specific event.

Let's see some code. First we want to create an event and its handler. Lets use the help example. When fired, we want to create a help event with a string that will represent "what" help data we want to display.

HelpEventHandler.java:

public interface HelpEventHandler extends EventHandler

{
void onSelect(HelpEvent event);
}



HelpEvent.java:

public class HelpEvent extends GwtEvent

{
public static final Type TYPE = new Type();
private final String helpString;

public HelpEvent(final String helpString)
{
this.helpString = helpString;
}

@Override
protected void dispatch(final HelpEventHandler handler)
{
handler.onSelect(this);
}

@Override
public Type getAssociatedType()
{
return TYPE;
}


public String getHelpString()
{
return helpString;
}

}



We now have defined our event and a handler. Now we need someone to listen for this event as follows:

private final HandlerManager  eventBus   = new HandlerManager(null);


eventBus.addHandler(HelpEvent.TYPE, new HelpEventHandler()
{
@Override
public void onSelect(final HelpEvent event)
{
// Someone fired this event, do something with.
new HelpScreen(event.getHelpString()).show();
}
});




Lastly, we need someone to fire this event for the above listener to receive:

private final HandlerManager  eventBus   = new HandlerManager(null);

eventBus.fireEvent(new HelpEvent("my help topic"));


In summary, we built a specific event and handler. This event has a string as the data payload for it, a string that we use to go to a specific help page. This could be an object, data structure or any data that you want the event to get. We then setup a listener to act on this event being fired. Lastly, we fired the event. In practice, you can now implement a single listener and have lots of places in your code "fire" the event. You may have several places in your application where you want to show "help" and can build a single help display class while allowing any of your code to trigger it.

I've used this technique to allow for the editing of my objects from various places in my code. When someone initiates an edit operation, either from a menu pick, a right click, or by selecting on an object, the event is fired and my "edit object" code catches this request and puts up the edit dialog. I can get to this edit dialog from anywhere and never have to change my edit dialog code to do this.

I can now get to the edit dialog from anywhere in my code, just by Getting on the Bus.

Friday, July 1, 2011

Getting Started

As an experienced UI developer and designer, you know that you are going to need views, dialogs, menus, buttons, trees, tables, error dialogs, etc. You also know that you will want a nicely laid out directory structure to hold all your files and to establish a "place" for everything and everything in its "place". But where do you start... being new to GWT?

I started with a book. I chose Essential GWT - Building for the Web with Google Web Toolkit 2. My development platform is a Mac and my editor is the SpringSource Tool Suite (aka Eclipse). Starting with an example from the book, build your initial app and get it running. Spend some time modifying it and trying out different scenarios that the book covers. Learn about MVP (Model, View, Presenter) and adopt it to your liking. Understand how HTML + CSS and Java (compiled into javascript) will all fit together and will be used to make your application.

Make a change in Eclipse, save it and rebuild your app, then just refresh your browser and see how the changes automagically made it to your browser without stopping and restarting....very cool and will be so useful when you really get going.

As part of your initial design work, you will need to figure out what your app will be displaying and if you will need some 3rd party toolkits or if you want to go it natively with just the GWT basics? Native GWT will give you all the building blocks, but things like progress widgets, busy indicators, canvas renderers, etc. will not be there without bringing in some additional widgets. You may also want to bring in some Javascript widgets and integrate them, which is quite easy to do (a blog entry on that forthcoming).

Understand that you are on the web, in a browser, with a certain set of user expectations that are different that an installed application, but that line is blurring all the time.

I will be adding blog entries about GWT from here on out that provide specific small coding examples that answer "how do you do that?".

Monday, June 27, 2011

Welcome to GWT

After spending many years doing GUI development (starting with XWindows, DECwindows, then on to Motif and Java Swing) I was recently given the opportunity to move away from the application space and into the web space. "Build the same application you did with Swing, but make it web based" were the marching orders.

Now, I have to say that UI development seems to have not changed in 25 years. Yes, we got color, a mouse, animation, nicer fonts, etc. but we still create and manage widgets, think object oriented always, and need to put together layouts that adapt to screen sizes. Without even cracking a manual (actually a Google search now!) one can sit in Eclipse and pretty much guess what the method might be for doing something to a widget or for setting up a callback.

...Back to building my Swing app for the web. I was to use a technology called ADF (Oracle's Application Development Framework) with the end product deployed using Weblogic. Being a new Oracle employee, I had no prior knowledge of this technology and found not a lot in the internet about "how to" do things with it, so I decided why not share my findings as I went. My ADF blog was born. In very little time, I was able to start a new complete UI from scratch, taking advantage of templates, css styles, and a lot of code sharing. The complexity came in when trying to model and display data that was stored in our backend database that was "not" a typical RDB conforming data store, but that is a different story for a different day. Let's just say that where many web apps (and non-web apps) fall down is in building a multi-user, concurrent, auto refreshing application where all users coexist in harmony and life is good.

So now I've moved on to a very exciting new startup and was given free rain to "pick" the UI technologies that will be used. Slick, fast, usable, state of the art were the marching orders. After evaluating and comparing Swing, GWT and Flash, GWT was the winner. This blog will follow my adventure into GWT for the first time.

I knew nothing of XWindows/DECwindows and built DECplan, aka Microsoft Project before there was a Microsoft. Then on to Motif based NETarchitect integrated with an ObjectStore backend and is still the "fastest" performing application I have ever worked on. Next came a Swing based networking Control Center and a Virtualization Manager. Last was the ADF based Virtualization Manager and now a GWT set of applications.

I guess starting from drawing lines with X and building menu bars by hand has helped lead me on the path of making UI design and implementation "natural". I'm just wondering what will lead us into a new paradigm and really change the way Gui's are done. Maybe next lifetime.