Blog Archives

Filter selection within a TreeGrid

Every node within a TreeGrid can be selected. But sometimes you only need the leafs or only a few of them. It is possible to filter the selection later, just before you execute an action on the selected nodes. But the better way is to prevent a selection on obsolete nodes. Use a custom SelectionModel for that.

public class CustomSelectionModel extends GridSelectionModel<ModelData> {

	public CustomSelectionModel() {
		addListener(Events.BeforeSelect, new NoSelectionListener());
	}

	private class NoSelectionListener
		implements Listener<SelectionEvent<ModelData>> {

		@Override
		public void handleEvent(SelectionEvent<ModelData> se) {
			ModelData model = se.getModel();
			if (model instanceof Something) {
				se.setCancelled(true);
			}
		}

	}
}

You can also use properties of the model to make a decision, but sometimes you can simply ask for the instance type (i.e. folders and files).

Bold font on TreeGrid

You can have a bold font on a TreeGrid. Create your own renderer and enhance the HTML returning by the renderer.

private class BoldGridCellRenderer extends TreeGridCellRenderer<ModelData> {
	protected String getText(TreeGrid<ModelData> grid, ModelData model, String property, int rowIndex, int colIndex) {
		return "<span style=\"font-weight:bold\">" + super.getText(grid, model, property, rowIndex, colIndex) + "</span>";
	}
}

Add the renderer to your tree column (use always TreeGridCellRenderer for that column!).

ColumnConfig name = new ColumnConfig("name", "Name", 300);
name.setRenderer(new BoldGridCellRenderer());

DateFormat

You can not use java.text.DateFormat within GWT/GXT applications. The class is not supported by the Google runtime environment. But there is a similar class com.google.gwt.i18n.client.DateTimeFormat which is useable:

DateTimeFormat dFormat = DateTimeFormat.getFormat("dd.MM.yyyy");
String date = dFormat.format(new Date());

DateTimeFormat tFormat = DateTimeFormat.getFormat("HH:mm:ss");
String time = tFormat.format(new Date());

This can be used within GridCellRenderer or ColumnConfig within a ColumnModel.

ColumnConfig config = new ColumnConfig("column", "Column", 100);
config.setDateTimeFormat(dFormat);

Icons

To create an icon you can use

AbstractImagePrototype icon = IconHelper.create("path/to/png");

Within a TreeGrid it is possible to use a ModelIconProvider

TreeGrid<ModelData> grid = new TreeGrid<ModelData>(store, columnModel);
grid.setIconProvider(new MyIconProvider());

The provider can return an icon for different situations (like expanded or collapsed nodes, some special node types).

public class MyIconProvider implements ModelIconProvider<ModelData> {

   private final TreeGrid<ModelData> grid;

   public MyIconProvider(TreeGrid<ModelData> grid) {
      this.grid = grid;
   }

   public AbstractImagePrototype getIcon(ModelData model) {
      if (model instanceof Something) {
         return IconHelper.create("img/something.png");
      }
      
      if (grid.isExpanded(model)) {
         return IconHelper.create("img/folder-open.png");
      } else {
         return IconHelper.create("img/folder-close.png");
      }
   }
}

Resize your application within the browser

You can resize your application automatically within your browser window. Use a Viewport:

Viewport vp = new Viewport();
vp.setLayout(new FitLayout());
FitData layoutData = new FitData(5,5,5,5);
vp.add(new ContentPanel(), layoutData);
RootPanel.get().add(vp);

You should also set FitLayout to fit the ContentPanel of your application within the browser window.

Tooltips within Grid

If you need tooltips within a grid you should create your own GridCellRenderer.

public class MyData extends BaseModelData {
   public MyData(String name, Date date) {
      set("name", name);
      set("date", date);
   }
}

public class MyPanel extends ContentPanel {
   public MyPanel() {
      // ...
      ListStore store = new ListStore();
      Grid grid = new Grid(store, new MyColumnModel());
      // ...
      add(grid);
      new QuickTip(grid);  // don't forget it!
   }
}

public class MyColumnModel extends ColumnModel {
   public MyColumnModel() {
      super(new ArrayList());

      // our ModelData has two properties: name and date
      ColumnConfig aCol = new ColumnConfig("name", "Name", 300);
      aCol.setRenderer(new NameRenderer());
      configs.add(aCol);

      ColumnConfig bCol = new ColumnConfig("date", "Date", 100);
      bCol.setRenderer(new DateRenderer());
      configs.add(bCol);
   }

   private class NameRenderer implements GridCellRenderer {
      public Object render(MyData model, String property, ColumnData config, int rowIndex, int colIndex, ListStore store, Grid grid) {
         return "<div>" + model.get(property) + "</div>";
      }
   }

   private class DateRenderer implements GridCellRenderer {
      public Object render(MyData model, String property, ColumnData config, int rowIndex, int colIndex, ListStore store, Grid grid) {
         String date = DateTimeFormat.getFormat("dd.MM.yyyy").format(model.get("date"));
         return "<div qtitle=\"Date\" qtip=\"a date with format dd.MM.yyyy\">" + date + "</div>";
      }
   }
}

We can return HTML code from the renderer, which has “qtitle” and “qtip” attributes, which are used by the QuickTip instance.

Cayenne-Modeler with Netbeans 6.9

It is possible to start the Cayenne modeler within Netbeans. Go to your Maven project and right-click on the project name. Choose Custom->Goals… and put “cayenne-modeler:run” (without quotes) into the first line. Click on “Remember as” and choose a name for the goal (like Cayenne-Modeler). Now you have a new menu item, which can start the modeler. But you need the associated plugin within the pom-file of the project. Go to “Project Files” and open the “pom.xml”. Add

<build>
<plugins>
<plugin>
<groupId>org.apache.cayenne.plugins</groupId>
<artifactId>maven-cayenne-modeler-plugin</artifactId>
</plugin>
</plugins>
</build>

Now you can open the modeler.

Proximity

I use Proximity as Maven mirror. If you need a new repository to use the artifacts for your project, you have to change three XML files to add it, which is a not easy and every time you have to copy and paste some parts of the configuration and have to change them manually. Because I’m a lazy developer I have written a script to create the necessary XML tags. You can download it from the server. Check the path of the Proximity installation within the script, per default it is set to $CATALINA_HOME/webapps/proximity. The script contains only a basic logic, you can enhance it with more complex things. The new repository will be added to the “public” repository group, which is set as the mirror within the Maven configuration file.

Server down

The PhOSCo.info server was down today, I have executed an update of the server software.

JPA and then?

Some tests with JPA (EclipseLink as implementation) were not successful. I need a persistence.xml file to define different persistence contexts, but what is if I need a new context at runtime? I have to provide such an xml file, but how I can merge the new one with the already existing file without restarting the core system? It’s not nice to define all classes within the xml too, so I have closed this chapter.

I have found another interesting approach: Apache Cayenne. It seems to meet the requirements, especially the use of events during insert/update/commits etc. would allow me to integrate the ACS component of PhOSCo. So I’m thinking about a migration to this framework. Maybe I only can get some ideas from there or the complete framework. I will see.