(More) refactoring of ConfirmDialog

Sorry to step on your commit again, but I think there are some really important design choices to be made here,
and want to make sure we're clear from the start. I'll try to justify them in terms of more general principles
to make the argument at least that the changes are not purely

1) DRY- don't repeat yourself.
   If you find yourself writing many lines of code that looks quite similar, then consider reorganizing. Duplicated code,
   for example, calling messageContainer.setHTML in three different places, increases the cost and risk of future changes.
    Since you've already grouped the three pieces of text into a logical unit - the ConfirmDialogMessages class,
   you just need to gather all of this code into a single method: see updateMessages.

2) Favor Composition over inheritance. Inheriting behavior - subclassing ConfirmDialog into DeleteInstance dialog makes
   the relationship between the classes hard(er) to reason about - when is perform() called? How many times? for example,
   while using interfaces to decompose the ConfirmDialog into general bits - general layout and state transition, and into
   action-specific messages and behavior is much clearer.

   To point to one of my own monsters, take a look at AbstractGridPresenter and try to figure out how to add support
   for multiple selections. Yuck.

3) Cohesiveness. The messages displayed to the user, the style of the button, and the action to perform, are all intimate
   properties of the Delete action. It makes sense to bundle them together in a single class. This gives you a single
   place to make changes for the delete action. If you wanted to reuse the delete action in some other context, you could
   further decompose the DeleteAction class to take a Set<Cuid> as constructor parameter and provide a Function<Void> callback
   to handle refreshing.

4) Use promise rather than callbacks when chaining together multiple asynchronous actions. They reduce the number of lines of
   codes and reduce the surface space for errors/omissions in propogating exceptions. For example, it's really important to place
   the onSuccess() method within a try/catch clause, because otherwise an exception that occurs in this method will go entirely
   unhandled and leave the application in a frozen state. Using Promise.then() or Promise.join() enforces this requirement.
   You will typically use an AsyncCallback only at the very end of the chain where the user interface needs to be updated based on
   success/failure of the whole async process.

   Take a look also at Promise.waitAll() and Promise.forEach() which facilitate working with multiple promises.

5) Encapsulation: Use Composite only if you really need it. For the most part, there's no reason to expose a widget's innards to external users.
   The ModalDialog class, for example, can keep the PopupPanel as a class member and expose only behaviors like show() and hide()
   that are meant for external callers.

6) UiBinders can use any root widget, including PopupPanel, you don't have to wrap it in an HTMLPanel.

7) See UiObject.setVisible()
[AI-532] Fix NPE when setting activity category to null