Отображаем данные в табличной форме

Для представления табличных данных в навигаторе файлов используется jface TableViewer.

Многие задаются вопросом, зачем разделять провайдеры контента и меток? Разработчики библиотеки jface решили, что это позволяет повторно использовать программный код, так как провайдер контента обычно имеет аналогичную реализацию для разных вьюверов.

Рис. 1. Схема связи модели и представления

Реализация интерфейса ITableContentProvider

Следующим этапом процесса связывания модели с представлением будет связь с табличным вьювером VfsTableView. Создадим провайдер контента — класс VfsTableContentProvider, реализующий интерфейс ITableContentProvider. Интерес представляет реализация метода getElements(Object inputElement). Особенность реализации данного метода состоит в анализе наличия потомков у выбранного корневого элемента. Если потомков нет, то возвращается список элементов для родительского элемента:

public Object[] getElements(Object inputElement) {
if (inputElement instanceof FileObject) {
try {
if (((FileObject) inputElement).getType().hasChildren()) {
return getChildren(inputElement);
} else {
return getChildren(((FileObject) inputElement).getParent());
}
} catch (FileSystemException e) {
. . .
}
}
return getChildren(inputElement);
}

Для исключения дублирования кода введен вспомогательный метод поиска дочерних элементов getChildren():

private Object[] getChildren(Object parentElement) {
if (parentElement instanceof FileObject) {
try {
FileObject fileObject = (FileObject) parentElement;
if (fileObject.getType().hasChildren()) {
return fileObject.getChildren();
}
} catch (FileSystemException e) {
. . .
}
}
return new Object[0];
}

Реализация интерфейса ITableLabelProvider

Провайдер меток, реализующий интерфейс ITableLabelProvider класс VfsTableLabelProvider для табличного представления, будет несколько сложнее древовидного, так как на экран выводится несколько колонок свойств объекта. Для простоты построения прототипа будем выводить фиксированный набор колонок: "Имя", "Тип", "Размер" и "Дата последнего изменения". Для улучшения читабильности кода создадим отдельные методы для отображения значений каждого из атрибутов. Нумерация колонок метода getColumnText() начинается от нуля.

public String getColumnText(Object element, int columnIndex) {
if ((element != null) && (element instanceof FileObject)) {
// name
if (columnIndex == 0) {
return getFileObjectName((FileObject) element);
}
// size
if (columnIndex == 1) {
return getFileObjectSize((FileObject) element);
}
// type
if (columnIndex == 2) {
return getFileObjectType((FileObject) element);
}
// date
if (columnIndex == 3) {
return getFileObjectDate((FileObject) element);
}
}
return "???";
}

Примечание. В связи с ограничениями операционной системы Windows нулевую колонку нельзя будет сортировать. В дальнейшем изменим реализацию данного метода и будем использовать ее для вывода иконки. Отображение имени файла реализовано простейшим способом:

private String getFileObjectName(FileObject fileObject) {
return fileObject.getName().getBaseName();
}

Реализация виртуальной файловой системы позволяет получать размер содержимого файлового объекта, так что данный метод тривиален:

private String getFileObjectSize(FileObject fileObject) {
try {
if (((FileObject) fileObject) != null) {
if (((FileObject) fileObject).getType().equals(FileType.FOLDER)) {
return "";
} else if (((FileObject) fileObject).getType().hasContent()) {
return "" + ((FileObject) fileObject).getContent().getSize();
}
}
} catch (FileSystemException e) {
. . .
}
return "???";
}

Реализация получения типа файла более интересна, так как здесь используется системный объект Program, при помощи которого мы пытаемся получить информацию о файловом объекте по его расширению:

private String getFileObjectType(FileObject fileObject) {
try {
if (fileObject != null) {
if (fileObject.getType().equals(FileType.FOLDER)) {
return "Folder";
} else {
if (fileObject.getType().equals(FileType.FILE)) {
int dotPos = fileObject.getName().getBaseName()
.lastIndexOf('.');
if (dotPos != -1) {
String extension = fileObject.getName()
.getBaseName().substring(dotPos);
Program program = Program.findProgram(extension);
if (program != null) {
return program.getName();
} else {
return extension.toUpperCase();
}
} else {
return "Unknown";
}
}
}
}
} catch (FileSystemException e) {
. . .
}
return "???";
}

Получение форматированной даты не представляет особых проблем. Воспользуемся стандартным DateFormat-форматом. Возможность настройки отображаемого формата отложим на будущее.

private DateFormat dateFormat = DateFormat.getDateTimeInstance(
DateFormat.MEDIUM, DateFormat.MEDIUM);
. . .
private String getFileObjectDate(FileObject fileObject) {
try {
return dateFormat.format(new Date(fileObject.getContent()
.getLastModifiedTime()));
} catch (FileSystemException e) {
. . .
}
return "???";
}

Подключаем табличные провайдеры

Для отображения колонок таблицы в панели проводника требуется создать и назначить вьюверу колонки. За этот процесс будет отвечать метод setTableColumns():

private void setTableColumns() {
//Создаем колонки
TableColumn column = new TableColumn(vfsExplorerComposite
.getTableViewer().getTable(), SWT.LEFT);
column.setText("Name");
column.setWidth(150);

TableColumn columnSize = new TableColumn(vfsExplorerComposite
.getTableViewer().getTable(), SWT.LEFT);
columnSize.setText("Size");
columnSize.setWidth(100);

TableColumn columnType = new TableColumn(vfsExplorerComposite
.getTableViewer().getTable(), SWT.LEFT);
columnType.setText("Type");
columnType.setWidth(150);

TableColumn columnDate = new TableColumn(vfsExplorerComposite
.getTableViewer().getTable(), SWT.LEFT);
columnDate.setText("Date Modified");
columnDate.setWidth(150);

// отображаем заголовок
vfsExplorerComposite.getTableViewer().getTable().setHeaderVisible(true);
}

Осталось назначить провайдеры табличному вьюверу. А также создать обработчик изменений в дереве файловых объектов для обеспечения синхронных изменений в табличном вьювере. Метод инициализации примет следующий вид:

private void initialize() {
. . .
vfsExplorerComposite.getTableViewer().setContentProvider(
new VfsTableContentProvider());
vfsExplorerComposite.getTableViewer().setLabelProvider(
new VfsTableLabelProvider());
setTableColumns();
setInput(System.getProperty("user.home"));
vfsExplorerComposite.getTreeViewer().addSelectionChangedListener(
new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection selection = (IStructuredSelection) event
.getSelection();
vfsExplorerComposite.getTableViewer().setInput(
selection.getFirstElement());
}
});
} catch (FileSystemException e) {
. . .
}
}

Созданная связь данных с табличным вьювером VfsTableView теперь наглядно видна при запуске нашего проводника файлов. При навигации по дереву объектов в табличной форме автоматически отображается список файлов с атрибутами.

Рис. 2. Отображение списка файлов в табличной форме

Рекомендуемые ресурсы

Сайт проекта "Аранжировщик файлов": сайт
Статья A.O. Van Emmenis из цикла "Using JFace and SWT in stand-alone mode": сайт

Сергей Бердачук, http://www.berdaflex.com


Компьютерная газета. Статья была опубликована в номере 37 за 2006 год в рубрике программирование

©1997-2024 Компьютерная газета