Вчера довёл свой проект gwt-ui до стадии, когда можно его выкладывать. Получился довольно интересный инструмент, который позволяет сильно упростить построение пользовательских интерфейсов для GWT.
Идея появилась после того, как я заметил, что приходится писать много похожего кода при построении интерфейса: панели, внутри ещё панели, внутри которых виджеты и т.д. В то же время, сейчас всё более и более популярны "описательные" способы построения интерфейсов (напр. XAML).
Такой подход более гибкий, наглядный и удобный, чем "последовательное" создание.
В GWT же сейчас используется именно "последовательное" создание интерфейса: созаются панели, внутрь который добавляются виджеты.
Вспомнив о генераторах в GWT, о которых я недавно писал, подумалось - почему бы не использовать их, для генерации хотя бы базового кода генерации интерфейса? Вот и взялся за реализацию этой идеи.
Как результат и появился проект gwt-ui. Что же он из себя представляет? Фактически, это jar-файл, который можно подключить к проекту, и после этого появится возможность воспользоваться генератором, который находится в этом проекте.
Приведу список возможностей, которые сейчас доступны:
- Построение интерфейса используя XML-описание
- Простой доступ к сгенерированным объектам (сейчас - к контейнерам)
- Простое переключение "состояний" (вызов одного метода)
- "Ленивое" создание виджетов: виджеты создаются только тогда, когда они становятся видимыми
- Наследование состояний: любое состояние может наследоваться от другого. Можно написать некое "основное" состояние, которое описывает базовое расположение виджетов, а остальные просто описывают изменения.
- Возможность задания визуальных свойств контейнеров (напр. "align='right' width='100%' style='bar'")
- Нотификация виджетов о новом состоянии: Если виджет имплементирует интерфейс UIStateListener и он добавлен в интерфейс, то ему будет сообщатся о том, что состояние поменялось.
Вот небольшое how-to создания простейшего интерфейса с помощью gwt-ui:
1. Файл описания интерфейса.
Для начала создадим файлик, рядом с файлом описания модуля (который <ModuleName>.gwt.xml), в котором опишем структуру простейшего интерфейса (более сложный пример можно посмотреть в коде примера, доступного в svn):
<gwtui>
<layout>
<container id='main' type='FlowPanel'/>
</layout>
<states widgetpackage='client'>
<state id='fiststate' default='true' >
<content container='main'><widget type='MyWidget1' /></content>
</state>
<state id='anotherstate'>
<content container='main'><widget type='MyWidget2' /></content>
</state>
</states>
</gwtui>
В этом файле определены:
- Контейнер, имеющий тип FlowPanel под именем 'main'
- Два состояния:
- Состояние 'firststate', которое будет использоватся по умолчанию (т.е. при первоначальной загрузке и/или если произведенна попытка изменить состояние, которое не описанно в документе. При установке этого состояния, в контейнер под именем 'main' помещается виджет с типом 'MyWidget1' (находищийся в пакете 'client')
- Состояние 'anotherstate'. При установке этого состояния, в контейнер под именем 'main' помещается виджет с типом 'MyWidget2' (находищийся в пакете 'client'). При этом, виджеты, которые были помещенны в этот контейнер другими состояниями пропадают.
Думаю, синтаксис достаточно прост. Более сложное описание примера можно посмотреть на страничке демо-примера, где используется и наследие состояний и визуальные свойства контейнеров.
2. Подключение GWTUI
Для работы gwt-ui, требуется подключение модуля в файле определения модуля GWT. Это можно сделать просто добавив такую строчку в файл определения (<ModuleName>.gwt.xml):
<inherits name='org.olostan.gwtui.GWTUI'/>
3. Создание интерфеса-маркера
Для получения объектов, созданных gwt-ui и изменения состояний интерфейса, необходимо определить в своём проекте интерфейс, который будет наследоватся от интерфейса "UIManager", например:
public interface MyUI extends UIManager {
public Panel getMainContainer();
}
Данный интерфейс позволяет получить екземпляр контейнера 'main', описанного в файле описания интерфейса. Для того, например, чтоб добавить его на страничку.
4. Создание и добавление пользовательского интерфейса
Для того, чтобы создать сгенерированный пользовательский интерфейс, достаточно воспользоватся статическим методом GWT.create(). После этого с помощью полученного интерфейса можно будет получить доступ к созданным объектам и поменять текушее состояние. Например, при инициализации модуля:
public class MyModule implements EntryPoint {
MyUI ui;
public void onModuleLoad() {
ui = (MyUI) GWT.create(MyUI.class);
RootPanel.get().add(ui.getMainContainer());
ui.setState("fiststate");
}
}
В последствии, когда надо поменять текущее состояние, можно вызвать метод setState, например:
ui.setState('anotherstate');.
Вот таким способом можно создавать интерфейсы на основе XML-описания интерфейса и потом переключать состояния интерфейса.
4 comments:
Маладца
Хорошая идея, декларативный подход рулит.
Чего не хватает - так это подключать какой-нибудь HTML template engine, чтобы отделить дизайн от представления
а через пару лет в GWT появился UIBinder... и очень похоже, кстати :)
Но прошу заметить что в UIBinder-е нет поддержки смены состояний :)
А в остальном да. Даже имплементация чем-то похожа ;)
Post a Comment