Wrapping text in a JLabel

March 29th, 2009

The Java Swing framework does not seem to supply a component designed to display static text in fluid manner. JLabels are great for displaying a line of text, or a carefully constructed multi-line statement (with suitable line breaks), but provide no support for wrapping. JTextAreas can probably be customized to the point where they appear to look like static labels, but who has the time?

The WrappableJLabel class is an extension to the regular JLabel that provides support for basic wrapping. When called with the default constructor, the component will expand to fill all available space in its parent container, wrapping if necessary. An optional width argument can be passed in the constructor, which will be used as the preferred width of the component.

Download WrappableJLabel.java or view the JavaDoc.

Example usage

The following brief example creates a WrappableJLabel that will expand to fill the surrounding fixed-sized JDialog:

/* Creates a JDialog with a fixed size and places
   a WrappableJLabel inside. */
 
String text = "Lorem ipsum dolor sit amet, consectetur " +
  "adipiscing elit. Vivamus quis magna. Ut ante ligula, " +
  /* HTML line breaks are allowed */
  "pulvinar sed, egestas in, tempor vel, dui.<br>" +  
  "Cras pellentesque sagittis sem. Maecenas venenatis " +
  "odio nec tellus. Nunc a sapien. Nunc quam turpis, " +
  "malesuada in, pellentesque non, fringilla ut, magna.";
 
JDialog dialog = new JDialog();
dialog.setDefaultCloseOperation(WindowConstants.
    DISPOSE_ON_CLOSE);
dialog.setPreferredSize(new Dimension(200, 300));
dialog.setLayout(new BorderLayout());    
 
WrappableJLabel wrapLabel = new WrappableJLabel(text);    
dialog.add(wrapLabel, BorderLayout.PAGE_START);    
dialog.add(new JButton("Test button"), BorderLayout.PAGE_END);
 
dialog.pack();    
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);

Comments, suggestions for improvements and bug reports welcome. Due to levels of spam, you’ll need to register to leave a comment – apologies.

How to add and delete a watermark using VBA

January 27th, 2009

The following two code snippets can be used to add and remove a watermark using VBA. It has been tested in Word 2003 and 2007 and seems to work fine.

Add a watermark

The code below inserts a “DRAFT” watermark diagonally across the page.

Sub AddTheWatermark()
  ActiveDocument.Sections(1).Range.Select
  ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
  Selection.HeaderFooter.Shapes.AddTextEffect( _
      PowerPlusWaterMarkObject68660062, "DRAFT", "Arial", 1, False, False, 0, 0 _
      ).Select
  With Selection.ShapeRange
    .Name = "PowerPlusWaterMarkObject68660062"
    .TextEffect.NormalizedHeight = False
    .Line.Visible = False
    .Fill.Visible = True
    .Fill.Solid
    .Fill.ForeColor.RGB = RGB(192, 192, 192)
    .Fill.Transparency = 0.5
    .Rotation = 315
    .LockAspectRatio = True
    .Height = CentimetersToPoints(6.41)
    .Width = CentimetersToPoints(16.03)
    .WrapFormat.AllowOverlap = True
    .WrapFormat.Side = wdWrapNone
    .WrapFormat.Type = 3
    .RelativeHorizontalPosition = _
      wdRelativeVerticalPositionMargin
    .RelativeVerticalPosition = _
      wdRelativeVerticalPositionMargin
    .Left = wdShapeCenter
    .Top = wdShapeCenter
  End With
  ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument
End Sub

Delete a watermark

The code below deletes all watermark objects in the active document.

Sub DeleteTheWatermark()
 
  ActiveDocument.Sections(1).Range.Select
  ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader   
  Dim shapes_to_delete As New Collection
 
  For i = 1 To Selection.HeaderFooter.Shapes.Count
    If InStr(Selection.HeaderFooter.Shapes(i).Name, "PowerPlusWaterMarkObject") > 0 Then
      shapes_to_delete.Add (Selection.HeaderFooter.Shapes(i).Name)
    End If
  Next i
 
  For Each s In shapes_to_delete
    Selection.HeaderFooter.Shapes(s).Select
    Selection.Delete
  Next s
 
  ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument
End Sub

Relative links in PHP

January 7th, 2009

Whenever I create a web site, I use functions to output the header and footer of each page. This technique allows easy editing of page layouts as most of the HTML resides in these two functions. Every page on the site will call the same two functions, resulting in a consistent look and feel across the whole web site.

The header function outputs the <head> section of the HTML, which will normally contain links to style sheets. The question is: should these links be relative or absolute?

Relative links

The problem with relative links rears its ugly head when the header function is called from different directory depths. Take, for example, the following directory structure:

/css/main.css
/members/admin/index.php [1]
/members/index.php [2]

It’s clear to see that file [1] requires a different relative link to access the CSS file compared with file [2] (i.e. ../../css/main.css versus ../css/main.css). A static relative link won’t work for every file in a web site.

Absolute links

What about an absolute link? This would certainly solve the above problem, however it presents its own irritating issue: what to do if the folder structure changes?

To give an example, my local web server is configured to serve pages from /var/www and I create a subdirectory for each site I’m constructing. So my work on http://www.foo.com will probably be stored in /var/www/foo and accessed as http://localhost/foo on my test server. Unfortunately, this means that absolute links on my test server (e.g. /foo/css/main.css) will break on my production server (which would require /css/main.css).

Solution

One solution is to define a base bath, as follows:

define("BASE_PATH", dirname(substr(__FILE__,
  strlen($_SERVER['DOCUMENT_ROOT']) -1)));

Let’s break the definition into pieces to see what this code is doing:

  • The __FILE__ constant will output the full path of the current file from the web server’s point of view, e.g. /var/www/mysite/foo/bar.php.
  • The $_SERVER['DOCUMENT_ROOT'] variable will output the directory from which the web server is serving files, e.g. /var/www.
  • The substr command effectively subtracts one from the other, leaving /mysite/foo/bar.php.
  • The dirname command strips off the file name, leaving /mysite/foo.

Now, suppose my bar.php file contains the header function. It’s now able to construct an absolute link to anywhere in the web site, by prefixing the BASE_PATH constant to a relative link, e.g.:

$link = BASE_PATH . '/../css/main.css';

This forms an absolute link that is resilient to the folder structure changes discussed above.