Статьи

Начало работы с Spring RCP


Давайте познакомимся с
Spring RCP . Кажется, в этот проект дует новая жизнь: после почти двухлетнего перерыва выпуск 1.0.0 вышел несколько месяцев назад. Оставим в стороне вопрос о его направлении и так далее, и вместо этого давайте просто рассмотрим саму технологию, чтобы увидеть, что именно она предлагает. В этом свете я сделал доступным простой плагин для IDE NetBeans, который предоставляет примеры и шаблоны для начала работы. Ниже я прохожу базовый сценарий с помощью плагина. Однако даже те, кто не является пользователями NetBeans, могут многое узнать о Spring RCP, прочитав шаги этого руководства и пояснения к ним.

Содержание

Начиная

  1. Установите подключаемый модуль Spring RCP Tooling в среду IDE NetBeans 6.1.

  2. В мастере создания нового проекта (Ctrl-Shift-N) вы найдете новый шаблон проекта:

     

  3. Завершите работу мастера, и вы получите структуру проекта следующим образом:

    Краткий обзор файлов, которые вы видите выше (имейте в виду, что если вы переместите «richclient-application-context.xml» или «messages.properties» в любое другое место, или если вы переименуете любой из них, вам необходимо обновить Панель Spring Rich Client в диалоговом окне свойств проекта приложения):

    файл объяснение
    SimpleApp.java Предоставляет «основной» метод приложения и запускает приложение с
    помощью класса RCP «ApplicationLauncher» Spring. Этот класс загружает
    XML-файл контекста приложения и XML-файл контекста запуска, где определяются проблемы уровня приложения, такие как заставка, последовательности инициализации и представления.
    SimpleLifecycleAdvisor.java Обеспечивает управление жизненным циклом приложения. Этот класс
    зарегистрирован в XML-файле контекста приложения. Он предоставляет такие методы,
    как «onWindowOpened» и «onCommandsCreated», так что у вас есть
    точки входа для настройки того, что происходит при запуске приложения. ( Например , вы можете настроить размер приложения в методе «onPreWindowOpen».)
    richclient-приложения context.xml Предоставляет XML-файл контекста приложения, в котором настраиваются
    компоненты и службы Spring RCP .
    richclient-стартап-context.xml Предоставляет файл XML контекста запуска, который определяет заставку, но может определять все, что вы хотите, чтобы происходило именно при запуске.
    images.properties Предоставляет ресурс изображения. Он зарегистрирован в
    XML-файле контекста приложения .
    Всплеск-screen.jpg Предоставляет изображение заставки, которое используется в XML-
    файле контекста запуска .
    Команды-context.xml Предоставляет команды приложения, организованные в пределах строк меню и панелей инструментов, и элементы в них. Этот файл объявлен в XML-файле контекста приложения.
    messages.properties Обеспечивает отображение текста в централизованном месте. Например, тексты для названий и описаний находятся здесь.

    Примечание . Шаблон также помещает большинство JAR-файлов Spring RCP в путь к классу вашего приложения. Загляните в узел Библиотеки, чтобы увидеть, какие там есть. Потенциально, больше плагинов могут быть включены в плагин, поскольку сложность предоставляемого инструментария увеличивается.

     

  4. Запустите приложение. Вы должны увидеть это:


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

Теперь мы создадим новое окно в нашем приложении.

  1. Щелкните правой кнопкой мыши узел проекта и выберите New | Spring View, как показано здесь:

  2.  

  3. В диалоговом окне New Spring View введите «CustomerView» и укажите существующий пакет в качестве имени пакета:

     

  4. Нажмите Готово. Теперь у вас есть новый класс, который расширяет класс Spring RCP AbstractView:

    package simple;

    import javax.swing.JComponent;
    import javax.swing.JPanel;
    import org.springframework.richclient.application.support.AbstractView;

    public class CustomerView extends AbstractView {

    @Override
    protected JComponent createControl() {
    JPanel panel = new JPanel();
    return panel;
    }

    }

    Откройте файл richclient-application-context.xml. В конце файла обратите внимание, что ваше представление было автоматически зарегистрировано для вас следующим образом:

    <bean id="CustomerView" class="org.springframework.richclient.application.support.DefaultViewDescriptor">
    <property name="viewClass" value="simple.CustomerView"></property>
    </bean>

    Наконец, откройте ui / messages.properties и обратите внимание на новую запись для пункта меню, который откроет представление:

    CustomerView.label=&CustomerView

     

  5. Запустите приложение и перейдите в Window | Показать представление, откуда вы можете открыть новый вид клиента:

     

  6. Давайте сделаем наш новый вид открытым по умолчанию при каждом запуске приложения. Другими словами, наш Customer View будет первоначальным представлением приложения. Для этого откройте файл richclient-application-context.xml и найдите bean-компонент с атрибутом «lifecycleAdvisor» в качестве атрибута «id». Добавьте это свойство в список свойств этого компонента:

    <property name="startingPageId" value="CustomerView" />

    Обратите внимание, что атрибут name может быть заполнен автоматически, если вы вызываете завершение кода (по умолчанию это Ctrl-Space):

    Следовательно, теперь все определение компонента выглядит следующим образом:

    <bean id="lifecycleAdvisor" class="simple.SimpleLifecycleAdvisor">
    <property name="startingPageId" value="CustomerView" />
    <property name="windowCommandBarDefinitions" value="ui/commands-context.xml" />
    <property name="windowCommandManagerBeanName" value="windowCommandManager" />
    <property name="menubarBeanName" value="menuBar" />
    <property name="toolbarBeanName" value="toolBar" />
    </bean>

     

  7. Запустите приложение еще раз и обратите внимание, что представление клиента теперь отображается при запуске приложения.

Добавление данных клиента

Далее мы будем использовать наш новый Spring View для отображения данных клиентов нашим пользователям. Ничто в этом разделе не относится к Spring RCP. Ниже показано не что иное, как плавная интеграция со стандартной разработкой Swing, а также связанные с этим преимущества использования инструментов разработки, предоставляемых IDE NetBeans. Мы будем использовать одну из баз данных, связанных с IDE, но мы могли бы использовать любую базу данных вообще.

     

  1. Щелкните правой кнопкой мыши узел проекта и выберите New | JPanel Форма. Назовите панель «CustomerPanel» и выберите «простой» в раскрывающемся списке пакета, чтобы ваша панель была создана в том же пакете, что и другие классы. Нажмите Готово.

  2.  

  3. Откройте «CustomerView.java». Измените строку, которая создает экземпляр JPanel, чтобы вместо этого создавалась ваша новая CustomerPanel:

    public class CustomerView extends AbstractView {

    @Override
    protected JComponent createControl() {
    JPanel panel = new CustomerPanel();
    return panel;
    }

    }

    Теперь, когда вы запускаете приложение, CustomerPanel будет определять начальный вид.

     

  4. Откройте окно «Службы» (Ctrl-5). В окне «Службы» разверните узел «Базы данных», щелкните правой кнопкой мыши узел jdbc: derby и выберите «Подключиться». Теперь среда IDE подключается к своей связанной базе данных Derby. Разверните узел jdbc: derby, разверните узел Таблицы и обратите внимание, что есть таблица с именем «CUSTOMER». Это таблица, которую мы покажем в нашем приложении.

     

  5. Откройте CustomerPanel в режиме разработки. Затем перетащите таблицу из палитры в представление конструктора CustomerPanel. Наконец, перетащите узел CUSTOMER на стол. Теперь вы должны увидеть это:

    Примечание. Убедитесь, что вы нажали две кнопки со стрелками в правом верхнем углу снимка экрана выше. Это приведет к автоматическому изменению размера JTable во время выполнения, чтобы он вписался в размер JPanel.

  6.  

  7. Связанные файлы JAR должны автоматически добавляться в ваш проект. Если это не так и вы видите много сообщений об ошибках в сгенерированном коде, щелкните правой кнопкой мыши узел «Библиотеки», выберите «Добавить библиотеку», а затем добавьте «Связывание beans» и «TopLink Essentials», а также «derbyclient.jar» из папки db / lib вашего JDK.

     

  8. Вернувшись в окно Projects, вы должны увидеть, что артефакты, связанные с JPA, были добавлены в ваш проект:

     

  9. Запустите приложение, и вы увидите ваш начальный вид, заполненный данными из вашей базы данных:

Добавление видов стыковки

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

  1. Во-первых, нам нужно добавить новый вид, чтобы у нас было два окна. Используйте шаблон Spring View, как описано ранее в этом руководстве, и добавьте новое представление с любым именем, которое вам нравится, в том же пакете, что и раньше (или в любом другом месте). Как и прежде, представление регистрируется для вас в файле richclient-application-context.xml, а также в файле messages.properties.

     

  2. Когда вы запустите приложение, у вас будет два пункта меню под Window | Показать представление. При выборе второй вид заменяет первый и наоборот. Это не стыковка, это замена. Итак, давайте теперь изменим это так, чтобы оба отображались одновременно, т. Е. Чтобы оба окна пристыковывались к Spring RCP.

     

  3. Начните с добавления этого компонента в файл richclient-application-context.xml:
    <bean id="applicationPageFactory" depends-on="serviceLocator"   
    class="org.springframework.richclient.application.docking.vldocking.VLDockingApplicationPageFactory">
    </bean>

     

  4. Запустите приложение. Когда вы открываете оба представления, вы должны увидеть следующее:

  5.  

  6. Затем найдите бины, которые объявляют два представления, и измените класс, который они используют в richclient-application-context.xml, следующим образом:

    org.springframework.richclient.application.docking.vldocking.VLDockingViewDescriptor

    Поэтому теперь bean-компонент для представления клиента должен выглядеть следующим образом, тогда как то же самое должно быть верно для другого созданного вами представления:

    <bean id="CustomerView" class="org.springframework.richclient.application.docking.vldocking.VLDockingViewDescriptor">
    <property name="viewClass" value="simple.CustomerView" />
    </bean>
  7.  

  8. Давайте теперь посмотрим более внимательно на то, как определяются наши взгляды. Найдите компонент CustomerView, поместите курсор в начало значения атрибута «name» элемента свойства и вызовите завершение кода (Ctrl-Space). Теперь вы должны увидеть список возможных значений:

    Идите вперед и возьмите целую кучу этих имен, в частности те, которые показаны ниже, установив их все в «true»:

    <bean id="CustomerView" class="org.springframework.richclient.application.docking.vldocking.VLDockingViewDescriptor">
    <property name="viewClass" value="simple.CustomerView" />
    <property name="autoHideEnabled" value="true" />
    <property name="closeEnabled" value="true" />
    <property name="floatEnabled" value="true" />
    <property name="maximizeEnabled" value="true"/>
    </bean>

    Вы можете сделать то же самое для другого представления, в зависимости от того, какие из свойств выше вы хотели бы сделать доступными для этого конкретного окна. Названия вышеперечисленных свойств не требуют пояснений, за исключением «autoHideEnabled», которое добавит к вашему виду минимальную функциональность.

  9.  

  10. Запустите приложение еще раз и обратите внимание на небольшие новые кнопки в правом верхнем углу представления:

    Если вы щелкнете правой кнопкой мыши внутри строки заголовка, вы увидите те же опции, на этот раз как пункты меню вместе с нажатием клавиши, которая может их вызвать:

  11.  

     

  12. Попробуйте несколько из этих новых функций в вашем приложении. Например, нажмите кнопку «Отсоединить», и тогда вы сможете переместить весь вид из приложения (удобно, например, если у вашего пользователя несколько мониторов), как показано ниже:

  13. Note: To be able to drag a detached window, your cursor needs to become a hand, which is what happens when you move the mouse over the dotted line at the top of the window’s title bar.

     

  14. Finally, drag the title bar of a view to a position where it could conceivably be dropped and then you will see a shadow where it will appear when you release the view:

  15.  

  16. Once you have more windows, you can move them around and you can even end up with tabs, if you drag the window to the correct position, as shown below:

    Note: One thing I haven’t been able to figure out is how to save window positions at shutdown. In other words, at startup the user would like to have the window positions be restored to where they were when the application last closed. I don’t know how this is handled in Spring RCP. I believe it should be done automatically, which doesn’t seem to be the case since the application reverts to its default state when I rerun it.

Enabling Actions

Let’s now look at the menubar. Several menu items are available by default. Where do they come from? Our simple application contains no Java classes that have anything to do with menu items. So, what’s going on here?

Menus and toolbars are all declared in the «command-context.xml» file. That file and its contents, in turn, are declared in the «richclient-application-context.xml» file, which is the application context XML file that is loaded at startup.

     

  1. Open the «richclient-application-context.xml» file and take note of the declaration of the command-context.xml file, as follows, in line 3:
    <bean id="lifecycleAdvisor" class="simple.SimpleLifecycleAdvisor">
    <property name="startingPageId" value="CustomerView" />
    <property name="windowCommandBarDefinitions" value="ui/commands-context.xml" />
    <property name="windowCommandManagerBeanName" value="windowCommandManager" />
    <property name="menubarBeanName" value="menuBar" />
    <property name="toolbarBeanName" value="toolBar" />
    </bean>

    Note: The menubar and the toolbar are also declared above and are then further spelled out in the «command-context.xml» file.

     

  2. Notice the third line above and then open that file, i.e., the commands-context.xml file. Let’s start by looking at the Help menu:

    So, the «Help Contents» item is disabled, while the «About» item is enabled. Why?

     

  3. Look at the «menuBar» bean in commands-context.xml, where you’ll find that one of its members is «helpMenu». Hold down the Ctrl key and move your mouse over the «helpMenu» text and you will see a hyperlink:

    Click it and you will jump to the «helpMenu» bean, which is defined as follows:

    <bean id="helpMenu" 
    class="org.springframework.richclient.command.CommandGroupFactoryBean">
    <property name="members">
    <list>
    <value>helpContentsCommand</value>
    <value>separator</value>
    <ref bean="aboutCommand" />
    </list>
    </property>
    </bean>

    <bean id="aboutCommand"
    class="org.springframework.richclient.command.support.AboutCommand" />

     

  4. Now you can see why the «Help Contents» item is disabled, while the «About» item is enabled. In the first case, only a value has been declared, while in the second case there is a reference to a bean, for which a class has been defined that handles the invocation of the menu item. Let’s do the same for the «Help Contents» item, starting by creating a new bean for the «Help Contents» item:
    <bean id="helpContentsCommand" class="org.springframework.richclient.command.support.HelpContentsCommand">
    <property name="helpSetPath" value="help/simple-hs.xml" />
    </bean>

    Note: We refer above to «help/simple-hs.xml». That’s the JavaHelp helpset file that is the entrypoint to our helpset. You could create that by hand, as well as all the files that are needed to set up a JavaHelp helpset. Instead of that, save yourself some time and trouble by going back to the New Project wizard (Ctrl-Shift-N) and in the «Samples» category you will find some Spring Rich Client samples. Complete the wizard for one of them and then copy its «help» package into the «Resource Packages» node of your own application. Hurray you now have the start of your own helpset.

     

  5. Finally, we need to hook the bean up to our help menu, replacing the value with a reference to the bean, as shown below, in the same way as is done by default for the About item:
    <bean id="helpMenu" 
    class="org.springframework.richclient.command.CommandGroupFactoryBean">
    <property name="members">
    <list>
    <ref bean="helpContentsCommand"/>
    <value>separator</value>
    <ref bean="aboutCommand" />
    </list>
    </property>
    </bean>

     

  6. Run the application and now the «Help Contents» item is enabled. When you click the item, the JavaHelp from the sample appears.

Adding Context Sensitivity

As your application increases in size, fewer actions remain relevant to all views. Not every menu item should be available to every window, for example. This aspect of large applications is referred to as «context sensitivity» or «selection management». Depending on the current context, certain features should be available while other features are hidden or greyed out or disabled.

So, in this section, we will set things up so that the «New» command is only available if the current view is the Customer view. If the current view is not the Customer view, the «New» menu item and toolbar button (first button in the toolbar in the two following screenshots) will be disabled:

Otherwise, both will be enabled. Below you see the «New» toolbar button enabled because the current view is the Customer view:

To achieve the above result, one simply needs to modify the CustomerView class, as follows:

public class CustomerView extends AbstractView {

/**
* Handler for the "New" action.
*/
private ActionCommandExecutor newContactExecutor = new NewExecutor();

@Override
protected JComponent createControl() {
JPanel panel = new CustomerPanel();
return panel;
}

/**
* Register the local command executor to be
* associated with named commands. This is called by
* Spring RCP prior
* to making the view visible.
*/
@Override
protected void registerLocalCommandExecutors(PageComponentContext context) {
context.register("newCommand", newContactExecutor);
}

/**
* Private inner class to create a new customer.
*/
private class NewExecutor implements ActionCommandExecutor {
@Override
public void execute() {
JOptionPane.showMessageDialog(null, "new customer...");
}
}

}

Notice lines 20-23 in the code above:

@Override  
protected void registerLocalCommandExecutors(PageComponentContext context) {
context.register("newCommand", newContactExecutor);
}

Reference is made here to «newCommand». Where’s that defined? As always, all commands in Spring RCP are defined in «command-context.xml» file. There, note that the «windowCommandManager» bean declares «newCommand», among other commands, under «sharedCommandIds». In each view, a different target executor could be defined for the same command. In the code above, an «ActionCommandExecutor» is defined in the CustomerView, which produces a JOptionPane with a message as a placeholder for real code. In the OtherView, there could be a different way of handling the «newCommand». In other words, though the «newCommand» is globally visible, it is implemented differently per view.

In addition to commands that are defined in «command-context.xml», there are several that are predefined, which you can simply declare in your code:

As a result, for the view above, the commands declared above will be available and implemented as defined in the second argument to «GlobalCommandIds» (all of which are handled by «newContactExecutor», though that’s not very likely in real life). Potentially, you could have all or some of these displayed as toolbar buttons in the toolbar, assuming you declare the related tags in the «command-context.xml» file. They would be enabled if the view in which they’re declared is active:

…while being disabled in the context of other views:

 

 

Changing the Look & Feel

Since the end result is a standard Swing application, we should be able to change the look and feel. Open the «richclient-application-context.xml» and find the bean that is defined as follows, thanks to the NetBeans project template that created the source structure used in this tutorial:

<bean id="lookAndFeelConfigurer"
class="org.springframework.richclient.application.config.JGoodiesLooksConfigurer">
<property name="popupDropShadowEnabled" value="false" />
<property name="theme">
<bean class="com.jgoodies.looks.plastic.theme.ExperienceBlue" />
</property>
</bean>

Let’s change the look and feel to Metal:

<bean id="lookAndFeelConfigurer"
class="javax.swing.plaf.metal.MetalLookAndFeel">
</bean>

Now run it again, with this result:

If you remove the bean altogether, you can set the look and feel via the VM option:

-Dswing.defaultlaf=net.sourceforge.napkinlaf.NapkinLookAndFeel

The result, assuming the Napkin look and feel is on your classpath, is then as follows:

 

Conclusion

There are several other topics that could be discussed in the context of Spring RCP. However, the topics discussed so far should serve as a pretty good basis and give you an understanding of what Spring RCP can do for you and how various pieces fit together. At this point, you certainly should have enough information to build some pretty solid applications on top of Spring RCP.

It is tempting to attempt to compare Spring RCP with similar offerings in the desktop framework domain. It is also tempting to make value judgements. However, that’s not the purpose of this article and will be broached at another point in time.

(And now continue with part 2 of this series!)