Pull to refresh

Новое в Ext GWT 3.0

Reading time6 min
Views6.9K
JavaScript-библиотеки Ext JS и Ext GWT известны, помимо прочего, одним из лучших наборов визуальных компонентов — как по дизайну, так и по кроссбраузерности, да и по стабильности работы. Потому и руки сами тянутся к любому проекту на GWT добавить Ext и заменить скучные гугловые виджеты на симпатичные формы и окошки.

Однако интеграция Ext GWT и GWT до сих пор оставляла желать лучшего — по сути, вторая версия Ext GWT полностью вытесняет все средства компоновки интерфейса GWT, предлагая собственные API для всего, вплоть до обработки событий. Поэтому для третьей версии библиотеки, доступной сейчас в виде developer preview, разработчики из Sencha активно переписывают скриптовое наследие Ext JS, используя паттерны и идиомы, принятые в GWT. Главное ожидаемое преимущество — более корректная интеграция с GWT и, как следствие, более компактный и оптимизированный код интерфейса: генерация и обфускация JavaScript и CSS происходит на этапе GWT-компиляции, с использованием механизма deferred binding, за счёт чего исключаются фрагменты кода, не использующиеся в текущем проекте.

Реализация виджетов с использованием Appearance


Одним из паттернов, перенятых у GWT, стал Appearance, позволяющий выделить виджет, его разметку, стиль и связующую логику в независимые и заменяемые части. Такой подход позволяет легко менять стили и темы виджетов, и даже их разметку — например, использовать в качестве DOM-реализации кнопки либо div, либо button. Вот простейший пример применения паттерна Appearance для простой div-кнопки, у которой можно изменять текст и иконку:

public interface Appearance {
    void render(SafeHtmlBuilder sb);
    void onUpdateText(XElement parent, String text);
    void onUpdateIcon(XElement parent, Image icon);
}

public static class DefaultAppearance implements Appearance {
 
    public interface Style extends CssResource {
 
      String testButton();
 
      String testButtonText();
 
      String testButtonImage();
    }

    public interface Resources extends ClientBundle {
	  @Source("DefaultAppearance.css")
	  Style style();
    }

    public interface Template extends XTemplates {
      @XTemplate(source = "DefaultAppearance.html")
      SafeHtml template(Style style);
    }
 
    private final Style style;
    private final Template template;
 
    public DefaultAppearance() {
      this((Resources) GWT.create(Resources.class));
    }
 
    public DefaultAppearance(Resources resources) {
      this.style = resources.style();
      this.style.ensureInjected();
      this.template = GWT.create(Template.class);
    }
 
    @Override
    public void onUpdateIcon(XElement parent, Image icon) {
      XElement element = parent.selectNode("." + style.testButtonImage());
      element.removeChildren();
      element.appendChild(icon.getElement());
    }
 
    @Override
    public void onUpdateText(XElement parent, String text) {
      parent.selectNode("." + style.testButtonText()).setInnerText(text);
    }
 
    @Override
    public void render(SafeHtmlBuilder sb) {
      sb.append(template.template(style));
    }

}

Вложенный интерфейс Style представляет стиль отрисовки компонента. По умолчанию он связывается с внешним файлом DefaultAppearance.css — эта связь задаётся в интерфейсе Resources. Наконец, третий вложенный интерфейс, Template, представляет разметку компонента, и связан по умолчанию с внешним файлом DefaultAppearance.html. В конструкторе объекта DefaultAppearance можно переопределить реализацию интерфейса Resources, таким образом заменив стиль или тему компонента. Аналогичным образом можно поменять шаблон Template, или даже весь объект DefaultAppearance целиком — виджету достаточно знать простой интерфейс Appearance, чтобы делегировать ему установку параметров или обработку событий.

В итоге Ext GWT даёт нам три точки расширения, через которые мы можем повлиять на отображение виджета: изменив его CSS-стиль, HTML-разметку, либо полностью переопределив объект Appearance и механизм, с помощью которого он взаимодействует с DOM для отрисовки виджета. Благодаря паттерну Appearance все эти аспекты оказываются аккуратно отделёнными друг от друга.

JavaBean-объекты как модели данных


Наконец-то можно будет отказаться от интерфейса ModelData, в который необходимо было раньше оборачивать любые JavaBean-объекты, чтобы они могли служить моделями данных. В Store и Loader возможно станет использовать любые объекты, не связанные какими-либо контрактами интерфейсов и не расширяющие специализированные классы. Всё это достигается за счёт магии deferred binding — код для доступа к конкретным полям объекта генерируется на этапе GWT-компиляции. Пока что примеры нового API для работы с хранилищами и загрузчиками отсутствуют, зато новшество продемонстрировано на примере другого нововведения — переработанного механизма шаблонов XTemplate:

interface TemplateTest extends XTemplates {
    @XTemplate("<div><span>{name}</span></div>")
    SafeHtml renderCustomer(Customer customer);
 
    @XTemplate(source="template.html")
    SafeHtml renderCustomerExternal(Customer customer);
}

...

TemplateTest template = GWT.create(TemplateTest.class);
SafeHtml html = template.renderCustomer(customer);

Поля любого переданного объекта теперь можно использовать непосредственно в теле шаблона — так, в приведённом коде используется поле customer.name. Для тестирования этого кода мне не пришлось даже объявлять каких-либо мета-интерфейсов — всё необходимое генерируется магически на этапе компиляции. Сам шаблон, как видно из примера, может содержаться либо в строке-значении аннотации XTemplate, либо во внешнем файле, имя которого помещается в поле source той же аннотации. Результатом применения шаблона становится безопасный HTML — безопасный в том смысле, что полученный SafeHtml аккуратно обращается с возможными источниками XSS-атак в переданных полях и значениях.

UiBinder: декларативная раскладка интерфейса


Ещё одна давно ожидаемая функция — интеграция с существующим ещё с GWT 2.0 механизмом разметки интерфейса в XML — UiBinder. Он позволяет вынести во внешний XML-файл раскладку компонентов, сделав её декларативной и структурированной и отделив от логики интерфейса, прописанной в Java-коде. До сих пор UiBinder был доступен лишь для стандартных виджетов и контейнеров GWT, однако сейчас разработчики Ext GWT активно работают над интеграцией с ним собственных компонентов. Основной проблемой, из-за которой API ещё до конца не зафиксирован и даже вынесен в отдельный jar-файл, является сложность настройки контейнеров с помощью LayoutData — текущая реализация UiBinder не позволяет писать собственные парсеры для атрибутов XML-разметки. Разработчики Ext GWT и GWT сейчас занимаются согласованием изменений в GWT, которые сделают это возможным. Пока что предлагается следующий вариант (корневые теги для удобочитаемости опущены):

<border:BorderLayoutContainer pixelSize="800, 400">
  <border:north layoutData="size:100; margins: 0 0 5 0">
        <gxt:ContentPanel />
   </border:north>
   <border:west layoutData="size:150; margins: 0 5 0 0">
        <gxt:ContentPanel />
   </border:west>
   <border:center layoutData="0">
        <gxt:ContentPanel heading="BorderLayout UiBinder Example" />
   </border:center>
   <border:east layoutData="size:150; margins: 0 0 0 5">
        <gxt:ContentPanel />
   </border:east>
   <border:south layoutData="size:100; margins: 5 0 0 0">
        <gxt:ContentPanel />
   </border:south>
</border:BorderLayoutContainer>

Легко видеть, что предлагаемый синтаксис поля layoutData чем-то напоминает CSS-стили в атрибутах. Для работы этого механизма необходимо подключить к проекту библиотеки gxt-uibinder-3.0.0-SNAPSHOT.jar и uibinder-bridge-2.3.0-SNAPSHOT.jar. Однако надо сказать, что у меня так и не получилось протестировать приведённый пример — GWT упорно отказывался преобразовывать неизвестное ему содержимое layoutData в объект BorderLayoutData.

Заключение


К прочим мелким приятностям в новой версии библиотеки можно отнести:
  • унифицированный с GWT механизм обработки событий — никаких листенеров, стандартные хендлеры;
  • переведённые с Flash на JavaScript графики — примеры из имеющегося в дистрибутиве приложения Ext GWT Explorer, как обычно, впечатляют вылизанностью и быстродействием;
  • некоторые упрощения в контейнерах и раскладках — контейнеры LayoutContainer отныне жёстко связаны с раскладками Layout (RowLayoutContainer, BorderLayoutContainer, и т.д.), что несколько облегчает их конфигурацию и обеспечивает при этом типовую безопасность.

В заключение отмечу, что текущая версия Ext GWT 3.0 работает в связке с GWT 2.3.0, и требует как минимум Java 1.6 для успешной компиляции, что обусловлено в том числе и требованиями самого GWT. Поменялся и корневой пакет библиотеки — в духе недавнего ребрендинга компании com.extjs был заменён на com.sencha. Разработчики обещают выпускать новые версии developer preview раз в несколько недель, однако отмечают, что эти версии пока лишь демонстрируют новые функции и ещё не зафиксированный API, а потому не рекомендуются для использования в разработке.

Ссылки



Tags:
Hubs:
+17
Comments8

Articles

Change theme settings