Actually I am writing a table where I can see and choose files and (sub-)directories from another directory. I want it to look similar to the windows explorer for example. There you can choose a directory on the left side and on the right side you see the content. I did nearly the same, used a HorizontalSplitPanel with a tree on the left and a table on the right side. There is no problem with the tree but I have 2 problems with the table.
What I did here is the following: When the user chooses a directory, a new FilesystemContainer is created and set as datasource to the table. Then I modify the header and the content of the columns. Here is the first problem. Although the appearance of the table should always be the same, I have to set it again explicitly every time a new directory is chosen, because the whole content changes. But it seems that there is no way to change the content of the container as removing items isn’t supported. Here is the corresponding method which is called every time a new directory is chosen:
private void updateFileTable() {
File pathFile = new File(path);
if (pathFile.isDirectory()) {
fileContainer =
new FilesystemContainer(pathFile, filterSelector.getChosenFilter()
.getValue(), false);
} else if (pathFile.isFile()) {
fileContainer =
new FilesystemContainer(pathFile.getParentFile(), filterSelector
.getChosenFilter().getValue(), false);
}
fileTable.setContainerDataSource(fileContainer);
fileTable.setVisibleColumns("Name", "Last Modified", "Size");
fileTable.setColumnExpandRatio("Name", 1);
fileTable.setColumnExpandRatio("Last Modified", 0);
fileTable.setColumnExpandRatio("Size", 0);
fileTable.setConverter("Size", new SizeConverter());
fileTable.setConverter("Last Modified", new DateConverter());
for (Object itemId : fileTable.getItemIds()) {
Resource resource = FileTypeResolver.getIcon((File) itemId);
fileTable.setItemIcon(itemId, resource);
}
Messages messages = new Messages();
fileTable.setColumnHeaders(messages.get("name"), messages.get("changedate"),
messages.get("size"));
}
I didn’t want to commit already, don’t know what happened. I even can’t edit it. Great forum…
The question to the above code is, whether there is a better solution or not.
The second problem is to get icons into the table. I don’t want that they have an extra column. And I don’t want to use real pictures until now, I wanted to use the Resource class. I have no idea how to solve this as Table#setItemIcon(…) doesn’t work like it does on the left hand side tree for example.
It is enough to set up the table settings only once - after that you can simply call the setContainerDataSource(…) each time a new directory is opened and skip the table setup.
In order to show the icons, you need to set the RowHeaderMode for your table:
table.setRowHeaderMode(RowHeaderMode.ICON_ONLY);
If you’re happy with the default icons, you can replace the for loop with setItemIconProperty(“Icon”) method call, as the FilesystemContainer already has a property for the icon.
To the first problem: I tried it out again and it seems that most settings aren’t overwritten when I call setContainerDataSource again. So I have to say again which columns are visible but I don’t have to make the translations again or set the converter. Strange, but good to know. In my case I really only have to set the visible columns again.
With your solution for the second problem I am not really happy. It is very short but then I have an extra column for the icons. That’s not very nice. Isn’t there a good way to put the icon directly in front of the text in the first column?
You’re right, the visible columns are reset on a setContainerDataSource call. To make it a bit cleaner, you can use the setContainerDataSource(Container container, Collection<?> visibleIds) API call to preserve the visible columns.
Showing the icon inside a column with other data can be achieved with a little bit of css:
.v-table-cell-content-documentIcon {
background-image: url("../runo/icons/16/document.png");
background-repeat: no-repeat;
text-indent: 15px;
}
And
table.setCellStyleGenerator(new CellStyleGenerator() {
@Override
public String getStyle(Table source, Object itemId, Object propertyId) {
if ("Name".equals(propertyId)){
return "documentIcon";
}
return null;
}
});
If you want different icons for different file types, then you’ll need to add separate styles for those and determine the type in the CellStyleGenerator.
Another approach is to add a layout to a column and inside the layout add a label and an embedded resource. That would be a bit heavier to render, however it’d give you a some more control in your java code.