Связывание представления с данными

Просто вывод на экран панели не представляет особого интереса. Наша основная цель — показать пользователю данные о файлах и папках выбранной файловой системы. Ограничимся для начала отображением фиксированного пользовательского каталога (выбор нужной файловой системы и ресурсов для просмотра оставим на будущее).

Создание модуля расширения eclipse на основе jar-архивов

К сожалению, проект Commons VFS не содержит готового подключаемого модуля eclipse, так что создадим его самостоятельно. На данном этапе это будет просто модуль-"пустышка", который является лишь контейнером для необходимых библиотек. В дальнейшем создадим точки расширения для обеспечения возможности создания собственных независимых реализаций виртуальной файловой системы.
Проект apache commons VFS (текущая версия 1.0-RC8) зависит от ряда дополнительных библиотек:



БиблиотекаТребуется для:
Jakarta Commons Logging версии 1.0.4 или вышевсе
Jakarta Commons Collections версии 3.1LRU Cache (опционально)
Jakarta Commons Net версии 1.4.1 или вышеFTP
Jakarta ORO версии 2.0.8
Jakarta Commons Httpclient версии 2.0.WebDAV HTTP, URI Utils
jdom.org JDom . версии 1.0. Требуется только для webdav 2.2+WebDAV
Jakarta Slide версии 2.2pre1 (20050629.002841). Требуется, если будет использоваться RandomAccessContent с webdavWebDAV
jCIFS версии 0.8.3 или вышеCIFS
JSch версии 0.1.23 или вышеSFTP
Commons Compress Nightly build 20050911tar, bz2


Рис. 1. Мастер автоматического создания проекта на основе jar-файлов

В простейшем случае можно собрать все требуемые библиотеки, сложить их в папку проекта и прописать зависимости в настройках проекта. Но модульная структура eclipse предполагает создание отдельных модулей для обеспечения повторного использования кода разными проектами. Причем желательно создавать отдельные модули для каждой независимой части — в данном случае библиотеки. Разбивка на отдельные независимые модули позволяет также снизить затраты интернет-трафика при автоматическом обновлении приложения в случае выпуска новых версий модулей. Процесс создания модулей на основе внешних jar-файлов в Eclipse IDE автоматизирован (это не запрещает создание таких проектов вручную). Воспользуемся мастером автоматического создания проекта, вызвав меню File -> New -> Project -> Plug-in development -> Plug-in from existing JAR archives.

Рис. 2. Выбор jar-файлов

Примечание:

Во многих диалогах и формах выбора элементов из списка или деревьев с большим количеством элементов доступно поле фильтра отбора данных. Список допустимых значений автоматически фильтруется при наборе текста критерия фильтра, что позволяет быстро находить требуемые элементы.

Первым шагом создания проекта будет диалог выбора исходных JAR-архивов (можно указать несколько файлов). Далее будет предложено ввести наименование модуля и других реквизитов проекта.

Рис. 3. Ввод реквизитов проекта на основе jar-файлов

Обращаем внимание на галочку Unzip the Jar archives into the project. Если данный пункт будет включен, то содержимое архивов будет распаковано — в противном случае архивы будут просто скопированы в каталог проекта. Первый вариант дает преимущество при развертывании (deployment) модуля, так как при этом создается упакованный в jar архив проекта. При втором варианте проект создается в виде каталога. При "ручном" создании содержащих библиотеки проектов для того, чтобы данные jar-архивы библиотек были доступны другим модулям, на страничке Runtime редактора манифеста следует указать список экспортируемых библиотек. На той же закладке редактора манифеста в блоке Exported packages надо указать, какие пакеты будут доступны извне. Для зависящих от других библиотек модулей надо дополнительно прописать список зависимостей в закладке Dependences редактора манифеста.

Связка модель-вид

Панель навигатора файлов выступает в качестве вида, а в качестве модели данных выступает виртуальная файловая система проекта Apache Commons VFS. Панель навигатора включает в себя компоненты org.eclipse.jface.viewers.TreeViewer для отображения дерева каталогов и org.eclipse.jface.viewers.TableViewer для отображения списка файлов. В дальнейшем реализуем еще и компоненту отображения текущего адреса. Компоненты TreeViewer и TableViewer (вьюверы) предназначены для отображения структурированных данных (наследники абстрактного класса ContentViewer). Для отображения данных этими компонентами требуется создать классы-посредники, которые будут являться связующим звеном между моделью и представлением. Для получения списка отображаемых объектов служит провайдер контента (content provider), а за формат отображения в понятном человеку виде отвечает провайдер меток (текста и изображений (label provider)).

При указании текущего объекта вьюверу или смене его на новый в методе setInput(Object input) вьювер запрашивает у провайдеров, какую информацию и в каком виде отображать. Для сложных древовидных структур данных запрашивается также информация о дочерних и родительских объектах. Кроме предоставления информации об объектах модели, провайдеры также информируют вьюверы о том, что данные были изменены извне, и необходимо обновить отображение данных вьювером. В абстрактных классах вьюверов для этого зарезервированы специальные методы:

. refresh — просто указывает на необходимость обновления данных. Это самая простая, но в то же время самая требуемая ресурсоемкая операция; . add — для указания, что был добавлен элемент или группа элементов;
. remove — для указания, что был удален элемент или группа элементов;
. update — для указания, что был изменен элемент. Опционально может быть указан список свойств, которые могут влиять на отображение, сортировку и фильтрацию.

Так как провайдеры относятся больше к уровню бизнес-логики, то есть смысл выделить вновь создаваемые классы работы с виртуальной файловой системой в отдельный модуль расширения com.berdaflex.filearranger.vfs.

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

Создаем класс VfsTreeContentProvider, реализующий интерфейс ITreeContentProvider. Метод getChildren(..) должен возвращать список дочерних объектов используемой модели данных, если они есть у текущего элемента. Воспользуемся готовым методом getChildren(..), доступным для объектов типа FileObject:

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

Аналогичный метод есть и для получения родительского элемента:

public Object getParent(Object element) {
if ((element != null) && (element instanceof FileObject)) {
try {
return ((FileObject) element).getParent();
} catch (FileSystemException e) {
. . .
}
}
return null;
}

Для получения информации о наличии дочерних элементов также есть аналогичный метод:

public boolean hasChildren(Object element) {
if ((element != null) && (element instanceof FileObject)) {
try {
return ((FileObject) element).getType().hasChildren();
} catch (FileSystemException e) {
. . .
}
}
return false;
}

Для получения списка элементов относительно корневого элемента воспользуемся реализованным методом получения дочерних элементов getChildren(..):
public Object[] getElements(Object inputElement) {
if (inputElement != null) {
return getChildren(inputElement);
}
return null;
}

Для реализации провайдера меток создадим наследник VfsTreeLabelProvider класса LabelProvider, который является базовой реализацией интерфейса ILabelProvider. На данном этапе метод получения изображения опустим:

public String getText(Object element) {
if ((element != null) && (element instanceof FileObject) {
return ((FileObject) element).getName().getBaseName();
} else {
element.toString();
}
}

Для простоты тестирования созданных провайдеров назначим их пока в методе создания панели проводника файлов, а точнее, создадим метод инициализации и добавим его вызов:

private void createVfsExplorerComposite() {
. . .
initialize();
}

private void initialize() {
getSite().setSelectionProvider(vfsExplorerComposite.getTreeViewer());
try {
VfsTreeContentProvider vfsTreeContentProvider = new VfsTreeContentProvider();
vfsExplorerComposite.getTreeViewer().setContentProvider(
vfsTreeContentProvider);
vfsExplorerComposite.getTreeViewer().setLabelProvider(
new VfsTreeLabelProvider());
setInput(System.getProperty("user.home"));
} catch (FileSystemException e) {
. . .
}

Для того, чтобы определить опорную точку — в данном случае это адрес в файловой системе, — предназначен метод setInput(Object input). Для тестирования укажем пока жесткий путь к каталогу пользователя:

protected void setInput(String filePath) throws FileSystemException {
FileSystemManager fsManager = VFS.getManager();
if (fsManager != null) {
currentFileObject = fsManager.resolveFile(filePath);
vfsExplorerComposite.getTreeViewer().setInput(currentFileObject);
} else {
. . .
}
}

Теперь можно пробовать запускать наше приложение. Как видно из рисунка, наш проводник успешно отображает содержимое каталога.

Рис. 4. Вывод дерева файлов каталога пользователя

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

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

Сергей Бердачук,
сайт



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

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