Archive for December, 2009

Finally a decent MessageBox!

Tuesday, December 8th, 2009

by Josef from Eden Foundation.

There is one frustration every Swing programmer shares: The message box system. The class JOptionPane, that comes with the Java Runtime Environment, is indeed versatile – but at the same time agonizing because of a very basic problem. Long messages don’t wrap… (click on the image to see what I mean)

a far too wide message dialog

This is the default behavior. There are various workarounds, the best that I’ve read about being to override the getMaxCharactersPerLineCount() method through a subclass. It’s a decent solution.

But once you start thinking about a bad class, you start getting wishful. And my wishlist came to include:

  • HTML-formatting for my messages (so some things can be written in bold or italic).
  • Possibility for the user to select and copy parts of the message, or it’s entirety, for sending in chats or emails when communicating with support.
  • Support for really, really long messages, the ones that are as long as License agreement! for the cases where this actually is desirable. If so, the message box should not disappear partly outside the screen. Instead, the message should be scrollable.

As I couldn’t find my dreambox anywhere on the net, I finally took the time to fix my own. I found it especially challenging because of the LayoutManagers that just didn’t seem to want to do what I want, but in the end, a tip from Stanislav Lapitsky helped me sort it out. He had a quick-and-dirty on how to figure out the height of a JEditorPane if you are locking it’s width:

http://java-sl.com/tip_text_height_measuring.html

So I’ve made a wrapper class that I call instead of JOptionPane, that wraps my message strings into a JEditorPane before displaying them. The key part of the code was to embed the text messages in a nice component.

  1.   public static void error(Component owner, String message, String title) {
  2.     JOptionPane.showMessageDialog(owner, wrap(message, "Error Encountered:"),
  3.         title == null ? "Error" : title, JOptionPane.ERROR_MESSAGE);
  4.   }
  5.  
  6.   private static JComponent wrap(String message, String shortTitle) {
  7.  
  8.     int maxWidth = 400;
  9.     int maxHeight = Toolkit.getDefaultToolkit().getScreenSize().height * 2 / 3;
  10.  
  11.     String htmlizedMessage = null;
  12.     if (message.contains("<p>") || message.contains("<P>")
  13.         || message.contains("<br>") || message.contains("<BR>")
  14.         || message.contains("<Br>"))
  15.       htmlizedMessage = message;
  16.     else
  17.       htmlizedMessage = message.replace("\n", "<BR>");
  18.  
  19.     int h = getContentHeight(htmlizedMessage, maxWidth);
  20.  
  21.     JPanel pnl = new JPanel();
  22.     pnl.setLayout(new BorderLayout());
  23.     JEditorPane text = new JEditorPane("text/html", htmlizedMessage);
  24.     text.setBorder(null);
  25.     text.setBackground(null);
  26.     text.setEditable(false);
  27.  
  28.     int titleHeight = 0;
  29.     if (shortTitle != null) {
  30.       JLabel lblTitle = new JLabel(shortTitle);
  31.       lblTitle.setFont(lblTitle.getFont().deriveFont(
  32.           lblTitle.getFont().getSize() * 1.5f));
  33.       lblTitle.setBorder(new EmptyBorder(0, 0, 10, 0));
  34.       lblTitle.setMaximumSize(lblTitle.getPreferredSize());
  35.       titleHeight = lblTitle.getPreferredSize().height;
  36.       pnl.add(lblTitle, BorderLayout.PAGE_START);
  37.     }
  38.     JScrollPane scroll = new JScrollPane(text);
  39.     scroll.setBorder(null);
  40.     scroll.setMaximumSize(new Dimension(maxWidth, maxHeight));
  41.     scroll.setPreferredSize(new Dimension(Math.min(maxWidth, text
  42.         .getPreferredSize().width), Math.min(maxHeight, getContentHeight(
  43.         htmlizedMessage, maxWidth))));
  44.  
  45.     pnl.add(scroll, BorderLayout.CENTER);
  46.     return pnl;
  47.   }

The result looks like this:

…like this…

…or this…

…or if the message is really, really long and almost qualifies to be an End User License Agreement (as if any end users ever have the time and legal knowledge to understand those), like this:

You can find the full source here:

http://www.edenfoundation.org/products/code/MsgDlg.java

svn over ssh with another port than 22

Wednesday, December 2nd, 2009

A client of mine has their own SVN repository and they where running ssh over another port than the normal 22. Doing this can be a bit tricky since svn doesn’t really like the common host:port style when using svn+ssh protocoll (or whatever you call that combo).

I’m using NetBeans (6.7.1) in Ubuntu, so was eager to get svn working directly from there. Since svn itself doesn’t like special ports, neither did NB. But after a simple search on “netbeans svn ssh port number” I surfed into (not stumbled – you know – I surf the web..) a subject in the subversion mailing list which reviled a simple solution. With ssh you can add some kind of alias for hosts for which you also can define a port etc, then it’s as simple as one two three to use custom ports with svn+ssh. I’m taking the liberty to sum the mail archive post here:

create (if not already there) a file in you home folder ~/.ssh/config

Adopt the following to your needs and add them to that file


host mysvnhost
Hostname svn.onthehost.tld
Port 80
ForwardAgent no
ForwardX11 no

Then just use svn+ssh://mysvnhost/path/to/repo with svn.