Monday, August 30, 2010

GWT: iPhone Like Buttons

In a new entry dedicated to GWT we're going to learn how to create an iPhone like button.

The objective is to create a rounded button with an image and support for badges.

Let's compare the iPhone button with the result of our tutorial
iPhone Button
Our CoolButton

Do you like it? Then stay with me for the How To.

Create the new Widget

We'll start creating a new Composite Widget, we'll call it CoolButton.

public class CoolButton extends Composite implements HasClickHandlers,
  ClickHandler {

 private final AbsolutePanel wrapper;
 private final PushButton pushButton;
 private final Label badge;
 
 public CoolButton(Image buttonIcon) {
  
  wrapper = new AbsolutePanel();
  badge = new Label();
  badge.setStyleName("badges");
  badge.setVisible(false);

  pushButton = new PushButton(buttonIcon);
  pushButton.setStyleName("CoolButton");

  wrapper.add(pushButton, 0, 20);
  wrapper.add(badge, 40, 10);
  wrapper.setWidth("75px");
  wrapper.setHeight("80px");

  this.addClickHandler(this);

  initWidget(wrapper);
 }
 
 @Override
 public HandlerRegistration addClickHandler(ClickHandler handler) {
  return addDomHandler(handler, ClickEvent.getType());
 }

 @Override
 public void onClick(ClickEvent event) {
  //toggleButton.fireEvent(event);
 }

 public void setEnabled(boolean enabled) {
  pushButton.setEnabled(enabled);
 }

 public void setBadge(int total) {
  if (total > 0) {
   badge.setVisible(true);
   badge.setText(String.valueOf(total));
  } else {
   badge.setVisible(false);
  }
 }
}

We'll analyze this code:

We're creating a Composite Widget, so basically we're creating a wrapper around already existing Widgets and adding some logic on top.

private final AbsolutePanel wrapper;
 private final PushButton pushButton;
 private final Label badge;

For you Widget we're using an AbsolutePanel, a PushButton and a Label.

The PushButton is our main component. It's a real button and displays an image, so it's perfect for our needs. The Label will be used to show the badge. Finally, the AbsolutePanel will allow us to layout the components, overlapping them to create the desired effect.

public CoolButton(Image buttonIcon) {
  
  wrapper = new AbsolutePanel();
  badge = new Label();
  badge.setStyleName("badges");
  badge.setVisible(false);

  pushButton = new PushButton(buttonIcon);
  pushButton.setStyleName("CoolButton");

  wrapper.add(pushButton, 0, 20);
  wrapper.add(badge, 40, 10);
  wrapper.setWidth("75px");
  wrapper.setHeight("80px");

  this.addClickHandler(this);

  initWidget(wrapper);
 }

In the constructor we create the badge label, and hide it by default. We'll show it later if needed. We create also the button with the specified image.

The tricky part here is the use of AbsolutePanel. The AbsolutePanel doesn't resize automatically to show properly all its children, as other LayoutPanels, so we need to position everything manually and make sure that it will fit.

wrapper.add(pushButton, 0, 20);

We place the button in the coordinates 0,20 that leaves some vertical space on top of the button that will be needed to place the badge.

wrapper.add(badge, 40, 10);

The badge is placed in the coordinates 40,10 so vertically will overlap with the button, and horizontally will be close to the right side.

wrapper.setWidth("75px");
wrapper.setHeight("80px");

Finally we make sure we've enough space to show everything.

All these coordinates and sizes are hardcoded, because they're relative to the image size.

The rest of the code doesn't have too much mystery. Since it's a button we need to add the needed code to fire the ClickEvents and register a ClickHandler. Also we need a method to set the badge and properly show and hide it.

With that we've our widget done. Now we need to attack the styling, so take a look to the CSS.

.badges {
 text-align: center;
 display: inline-block;
 font-size: 16px;
 color: white;
 background: #ff3333;
 border: 2px solid white;
 padding: 0px 5px;
 -moz-border-radius: 15px;
 -webkit-border-radius: 15px;
 -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.5);
 -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.5);
}

The badges style is quite simple, but let's check the different elements:
  • color: Defines de text color
  • background: defines the color of the background
  • border: defines the white border
  • border-radius: defines de rounding border (for Firefox and Webkit)
  • box-shadow: defines a tiny shadow for the badge (also for Firefox and Webkit)
.CoolButton {
 padding-left: 2px;
 padding-top: 2px;
 cursor: pointer;
 border: 1px solid black;
 -moz-border-radius: 5px;
 -webkit-border-radius: 5px;
 -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.5);
 -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.5);
 background: #00b5e2;
}

The button style is again the same CSS elements.

Note: That's not the case in our example, but GWT doesn't recognize properly some CSS styles, for those cases we need to wrap it in a literal call

background: -moz-linear-gradient(top, #e4e4e4, #cfcfcf);
background: literal("-webkit-gradient(linear, 0% 0%, 0% 100%, from(#e4e4e4), to(#cfcfcf))");

And that's it. You can download the code from the next link: iPhoneDemo - CoolButton

See you soon.

Monday, August 16, 2010

GWT: Best 5 GWT Libraries

Continuing with the GWT series we're going to see some of the best GWT libraries.

Ext GWT

Ext GWT, also known as GXT, is a complete widget library for GWT. It gives you Grid, Trees, Drag&Drop, Forms, Data Binding and much more.

The beauty is that everything comes perfectly integrated and works perfectly with GWT. GXT can be compared with SmartGWT, but the main difference is that SmartGWT is a wrapper around a JavaScript library, but GXT is a pure GWT implementation.

If the GWT widgets are not enough for you application, that should be your first option. GXT has a Commercial and Open Source license, so if your application is not Open Source, you'll need to pay.

GWT-Mosaic

GWT-Mosaic is a great expansion to the standard GWT library. Distributed with an Apache License, allows you to use it in any application.

GWT-Mosaic provides enhanced Trees and Tables, compared to GWT. But probably the best feature is the layout implementation. If you're used to the Swing layouts, you'll feel at home. On top of that it also provides a great Form and DataBinding support.

Probably the main complexity is mixing the Mosaic layouts with GWT components. But checking the demos and documentation helps to solve it. As a best practice tip you need to remember only that: don't insert a Mosaic layout inside a GWT layout.

GWT-DND

GWT-DND is one of the basic components of other libraries, like GWT-Mosaic and GWT-Cal. Distributed with an Apache License only makes it better ;)

GWT-DND provides all the needed support for all type of Drag&Drop operations, you can even expand them for your own needs.

GWT-Log

GWT-Log is the best option nowadays to have client side logging capabilities. The lack of a real logging system is probably one of the big missing features of GWT, but GWT-Log solves it perfectly.

It even provides multiple ways of see the logs, allowing to send the logs to the server, show them in a window or a console client side. As any log system is possible to configure the logging level.

GWT 2.1 implements java.util.logging emulation that seems will be able to super-seed this library, but until it's released, GWT-Log will still be an irreplaceable library in my GWT projects.

GWT-Cal

GWT-Cal is probably my favorite GWT library. If provides a great looking a really flexible calendar component for GWT projects. If you need an iCal / Outlook / Google Calendar component, don't look more, that's what you need.














Why do I like it? Well mainly because is the core part of the GWT application I'm working with, but also  because both developers are really helpful and collaborative.

Conclusion

As you can see all the proposed libraries are based in Apache License, except GXT and GWT-Cal. As I said at the beginning, if GXT covers your needs, don't make your life complex and use it.

Before using any GWT library, check that's really a GWT library and not a wrapper around a JavaScript library. The main problem with this kind of solutions is that are hard to mix with pure GWT components and usually slower and harder to expand.

As a last tip remember that any extra library that you add to your project will have 2 side effects: the compilation of your application will take longer and your application will need to load bigger files.

See you soon.

Friday, August 13, 2010

La Odisea del iPhone 4

El pasado viernes 30 de Julio de 2010 recibí una amigable llamada de un comercial de Movistar ofreciéndome el iPhone 4. La verdad es que la oferta era muy tentadora, pero quería ver que me ofrecía Vodafone, por lo que quedé con el comercial que me llamaría el siguiente martes.

Hablé con un comercial de Vodafone y me dijeron que la única opción era a través del programa de Puntos (me tocaba pagar más de 300 euros). Así que llame al departamento de bajas, donde me dijeron lo mismo. Les digo que tengo 2 líneas y que me llevaré las 2 a Movistar. Nada, que adiós....

El martes 3 de Agosto me vuelve a llamar el comercial de Movistar y le digo que acepto la oferta. Me confirma que recibiré el iPhone4 en 1 semana y que la portabilidad de línea se realizará el viernes 13 de Agosto. El iPhone4 me sale por 69 euros y contrato la otra linea con un Nokia Navigator para mi mujer. Perfecto!!!!

El miércoles 4 de Agosto recibo una nueva llamada, diciéndome que en estos momentos no hay disponibilidad de iPhone4 y que como cortesía me enviarán un iPhone3GS hasta que el modelo solicitado esté disponible, y que para compensar las molestias me descuentan 40 euros del iPhone (ahora sólo me costará 29 euros) Me dicen que no me preocupe y que se mantienen las fechas.

Llegamos al jueves 12 de Agosto, ni rastro del terminal ni de las tarjetas. Llamo al 1004 y me confirman que durante el mismo jueves recibiré el paquete.

Estamos a viernes 13 de Agosto y no hay rastro del terminal. La portabilidad se ha realizado y estoy sin línea. Vuelvo a llamar al 1004 y, sorpresa, resulta que el iPhone3 llega HOY al almacén. Sí, sí, el iPhone3, el de cortesía para que no me quedase sin línea. Y que no está previsto que yo lo reciba hasta la próxima semana.

La única solución que me dan es solicitar un duplicado de la tarjeta y que me abonarán el coste en la próxima factura. Claro para eso necesito tener un terminal de Movistar.

Mientras espero alguna solución estoy sin línea y la única solución es que me busque la vida.

Movistar: Ya recuerdo porqué me marche hace 3 años. Apenas llevo unas horas con vosotros y ya me arrepiento :(

Os mantendré informados.

Monday, August 9, 2010

PC vs Mac (from Microsoft Point of View)

Microsoft just opened a new page on their website comparing PCs and Macs in an attempt to counter attack the "Get a Mac" campaign.

I'm sorry to say that even when Microsoft as all the right to play to the same game as Apple, the reasons they are showing are, at least, weak:

Having Fun

It's true that's not possible to play Blue-Rays in a Mac or connect it to an XBox. The first is due to an Apple's decision and the second is probably because either Microsoft or Apple are interested in this kind of connection.

Regarding the problem of connecting a Mac to a TV, really I've done it and it's not a big deal. Sure you need an special connector, but works fine.

The lack of games in the OSX OS seems that's finally changing and shouldn't be an issue in the near future.

In any case these could be reasons for a home user, but no company should be stopped due to these points.

Simplicity

The computer that's easiest to use is typically the one you already know how to use. Another nice one is Unlike Macs, many PCs running Windows 7 support Touch
To me that's a really weak reason. In fact if you saw my post from some days ago I would say that OSX is much more easier to use than Windows.  Apple is a reference regarding usability and OSX is a really easy system to use. Just think about how easy is to install something in OSX. 

Also in OSX there's almost no need for antivirus or other maintenance programs. Try to do that in Windows and you'll see how works.

Affirmations as "the mouse works differently. And many of the shortcuts you're familiar with don't work the same way on a Mac" Sound really egocentric to me. Sure they are different, but I don't think that anyone would need more that 5 minutes to learn them.

The last one is hilarious "Unlike Macs, many PCs running Windows 7 support Touch" Is Microsoft the only one that missed the "Magic Mouse" and "Magic TrackPad" devices, not to talk about the normal TrackPad in the MacBooks. We could also talk about the touch support in iPhone and iPad, but since are not using OSX (yet) we'll leave them aside.

Working Hard
If most of the computers in your office or school run Windows you may find it harder to get things done with a Mac.

Can we apply the same argument if most of the computers use OSX? I'm using my MacBookPro in a network with Windows and Linux computers and I don't have any problem accessing to any kind of file. iWorks works perfectly well with Office documents (even OpenOffice work fine) and accessing the network drives is not a problem.

Or maybe Microsoft means that Windows is really bad sharing files with different OS (sarcastic mode off).

Sharing

Macs don't like share. I'm sorry but I don't known what is Microsoft talking about. The Macs can share using NFS, Samba or even the beautiful "BonJour" system. That's an affirmation without any base or explanation.


Compatibility
Plain and simple, if you're a PC user, lots of your favorite stuff just might not work on a Mac. With PCs outselling Macs 10 to 1, the reality is that most computer software is developed to run on PCs

Let's start with the most obvious point that's "More doesn't mean better" Also again the affirmation is quite egocentric. Almost all the most important programs have an OSX version or a substitute. And in most of the cases the OSX version is as good as the Windows version, or event better.


Choice
PCs give you a lot more choice and capabilities for your money. You can get the PC you want, in the size and color you want, with the features you want. You just don't have as many options with a Mac.

That's again quite obvious. When only 1 company is making Mac computers is not possible to have all the combinations that Windows have with all the hundreds of manufacturers of PCs. Again they are mixing quantity with quality.

One of the main problems of Windows stability is that Windows needs to work with thousands of hardware combinations, and not all the drivers are as stable as expected. Meanwhile Apple keeps a low number of hardware combinations, making easier to keep the stability.

As another point, I think is hard to find in the market more beautiful and well design computers than the Macs.

Conclusion

I known that seems that I'm an anti-Microsoft guy. That's not the case, but I got pissed off with the weak excuses that Microsoft is showing to publicity their operating system. Most of the affirmations are simply false, and the others are quite subjective.

What do you think?


Thursday, August 5, 2010

GWT: Extend The DatePicker/CalendarView

We're going to start this series of articles related with GWT with a tutorial about extending the DatePicker/CalendarView.

With the DatePicker you can choose any date in a Calendar and browse through it. The DatePicker uses internally the CalendarView class to configure the way the Dates are showed.

The nice thing about the DatePicker is that is really simple to use, but this simplicity comes with a high cost for Enterprise developments: It's really hard to extend, since is highly dependent of internal classes.

One of the most requested features is the ability to limit the valid dates, basically configuring a minimum and a maximum date.

To accomplish that we need to extend the DefaultCalendarView class.

In you GWT Project create a new com.google.gwt.user.datepicker.client package in your /src directory

Go to the GWT subversion repository and copy the DefaultCalendarView file to your code.

Now we're going to start doing our changes:

Create a new constructor adding support for the minimum and maximum dates and define the new variables

private Date minDate = null;
 private Date maxDate = null;

 /**
  * Constructor.
  */
 public DefaultCalendarView() {
 }

 /**
  * Constructor.
  * 
  * @param minDate
  *            Minimum allowed date.
  * @param maxDate
  *            Maximum allowed date.
  */
 public DefaultCalendarView(Date minDate, Date maxDate) {
  this.minDate = minDate;
  this.maxDate = maxDate;
 }

Ok that was easy, now we can define which are the minimum and maximum valid dates, but that's still doing nothing by itself

The easiest way to accomplish our objective is to disable the non-valid dates in the calendar, so let's modify the ......

@Override
 public boolean isDateEnabled(Date d) {
  if (minDate != null && maxDate != null) {
   if (d.after(minDate) && d.before(maxDate)) {
    return true;
   } else {
    return false;
   }
  }
  return getCell(d).isEnabled();
 }

We are almost done. Now let's modify the update method of the CellGrid subclass.

public void update(Date current) {
    // * Another Tweak *//
    setEnabled(getDatePicker().isDateEnabled(current));
    getValue().setTime(current.getTime());
    String value = getModel().formatDayOfMonth(getValue());
    setText(value);
    dateStyle = cellStyle;
    if (isFiller()) {
     dateStyle += " " + css().dayIsFiller();
    } else {
     String extraStyle = getDatePicker().getStyleOfDate(current);
     if (extraStyle != null) {
      dateStyle += " " + extraStyle;
     }
    }
    // We want to certify that all date styles have " " before and
    // after
    // them for ease of adding to and replacing them.
    dateStyle += " ";
    updateStyle();
   }

Note that we only changed the first line of the method, so we are not enabling the cell by default anymore, but we're checking if should be enabled.

The last missing part is that the DatePicker class needs also to be extended to use our new code:

public class DatePickerEx extends DatePicker {

 public DatePickerEx(Date minimum, Date maximum) {
  super(new DefaultMonthSelector(),
    new DefaultCalendarView(minimum, maximum), new CalendarModel());
 }

 public DatePickerEx(MonthSelector monthSelector, CalendarView view,
   CalendarModel model) {
  super(monthSelector, view, model);
 }
}

For your convenience you can also download the code in this archive

We're done. Enjoy your new DatePicker.

Introduction to GWT

This is the Part 1 of what I expect will become a series of articles about my personal experiences when developing with GWT.

Some months ago I started a project with GWT for my current employee. This was my first GWT project, so I needed to do some research and quite a lot of proof of concept, to make sure I could cover all the requested features.

What’s and what’s not GWT
 

That’s what Google says about GWT in their official page. 
Google Web Toolkit (GWT) is a development toolkit for building and optimizing complex browser-based applications. GWT is used by many products at Google, including Google Wave and Google AdWords. It's open source, completely free, and used by thousands of developers around the world. 
In this paragraph we have the first key about what’s GWT “is a development toolkit for building complex browser-based applications”. GWT is not the toolkit to use in your homepage or a simple website. For those tasks it’s much better to use pure Javascript toolkits (like JQuery) or maybe some PHP backend. 

GWT is useful when you want to create complex enterprise browser-based applications. But “what’s a complex enterprise browser-based application”? 

Well, I imagine that really depends, but I would say that any browser-based application that requires support for multiple simultaneous users, access to some backend with complex rules and wants to use a rich user interface. 

GWT only solves the rich user interface part, but is a perfect complement for a J2EE backend, allowing an easy integration and a rich experience. 

How is different GWT from other web toolkits? 

I would say that the most important difference is that when developing you only need to known Java, there’s no need to known anything about HTML or Javascript (even when it helps when you need to do really complex features) 

Ok, but JSP or IceFaces/RichFaces also allow to do that. Yes and no. JSP is the Java equivalent to PHP. That means that you need to known HTML and Javascript and inject the PHP in the middle. IceFaces/RichFaces are a really good alternative. In fact I almost choose IceFaces for my project, but the widgets and the flexibility of the components where not matching my expectations. 

Why should I choose GWT? 

For me GWT was the correct solution due to multiple factors:
  • Google is putting quite some efforts in this toolkit and the community around it is really active
  • GWT can be easily customized using CSS and even with direct DOM interaction
  • There are some really interesting extensions for GWT
    • GWT-Cal: Covert one of my main requisites and the developers are really friendly and helpful
    • GWT-Mosaic: Perfectly complements some missing feature and widgets in GWT
    • GWT-Log: Nice and easy integrated logging system
    • GWT-DND: Wonderful Drag&Drop API
Is everything that good? Really?
Well, not really. When I started my project I used SmartGWT. At the beginning it was awesome, everything was really simple, tons of widgets and a lot of people giving good reviews.
I was decided to use it, in fact I even started my project using SmartGWT, but not everything was that perfect.
When using SmartGWT I started finding problems, some were more annoyances than bugs, others required tons of extra work. My first disappointment came from the lack of help in the official forums. In fact I was even surprised by the hard reaction of some of the developers with some users questions. The next problem came when I tried to modify the theme. Was a complete nightmare, everything seemed like a problem and I found myself investing too much time in something that should be really simple.
By then I knew enough to create my own components and libraries like GWT-Mosaic only made everything easier. So I took the way that I wanted to avoid using SmartGWT, but at the end was easier than expected. And now I could use simple CSS and PNGs to create my UI.
Conclusion
Here I finish the first part of these tour through GWT. As you saw GWT is easy enough to use, but powerful enough to tweak it as you want. The ecosystem of libraries is rich enough, but keep always in mind what to you want to achieve.
In the Part 2 I will show you how to create some nice effects and widgets in GWT.
See you soon.