SR-JRC | a java richclient framework |
| create a dynamically loadable application The entrypoint of a GUI-application is SRStarter, which is part of SRJRCFrames and is the same for all applications. You "only" need to create the loadable part of the application. From a thechnical point of view this means, that you won't create a root-frame window, but use the space offered by the application frame SRStarter. In the sense of MVC your application will be the C - the controller. The root window of the application is of type To ease the creation of an application class, the framework offers the base class public class SampleApp extends AbstractApplication<SampleCfg> { } The default configuration of the application will be provided by a context-definition you write (see Configuration) and the application frame SRStarter will overwrite those settings with the values read from the users environment. Of cause, this will be performed before giving control to the instance of your application. Ingredients of a minimalistic application
Let's look a bit closer at each point ... To give all windows and icons of all applications the same look, neither the menue, nor the toolbar will be defined by using private enum Command { FILE_NEW, SEP_FILE, FILE_OPEN, EDIT_COPY, EDIT_RELEASE, SEP_EDIT, EDIT_DELETE, VIEW_REFRESH } As the naming suggests, there's some logic in it. The actionhandler splits the Enum-names at the "_" so the The application frame SRStarter adds some menue entries by its own. That includes an action to close all applications, an action to switch to another applications window, to open the common preferences editor or to start the browser for the help pages. There are no restrictions on the menue callbacks, so any method is valid for menue usage. To get a method executed at selection of a menue entry, both need to marry - that's what's class SampleActionHandler extends AbstractActionHandler implements ApplicationActionHandler { public SampleActionHandler(String name) { super(name); } @Override public void init() { setupAction(getName(), Command.FILE_NEW, new AbstractActionCallback() { @Override public void actionPerformed(ActionEvent ae) { doCreateSample(ae); } }, KeyEvent.VK_N , AccessMode.APP_READ); ... } public Enum The constructor has a name-parameter just to know for whom it is working for. The methods To support context menues, there's a variant of init, that takes a context object as parameter: @Override public void init(Object contextObj) { setupAction(getName(), Command.FILE_OPEN, new AbstractActionContextCallback(contextObj) { @Override public void actionPerformed(ActionEvent ae) { doEditSample(new ActionContextEvent(ae, getContext())); } }, KeyEvent.VK_O); ... } For this usecase there's an extended callback-class public SampleApp() { super(SampleApp.class.getSimpleName()); setActionHandler(new SampleActionHandler(getName())); } A GUI application without window content doesn't make much sense. As we don't know, whether we would like to change that content one day, we don't code it in the application, but use another class: @Override protected JComponent createPane() { if (content == null) { view = new AddressTableView(getInitialData(), EventSelectionModel.SINGLE_SELECTION, null); view.setSelectionChangedExecutor(new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { selectionChanged(e); } }); view.setPopDoubleLeftExecutor(new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { popupDoubleLeft(e); } }); view.setPopSingleRightExecutor(new AbstractAction() { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { popupSingleRight(e); } }); content = new ApplicationPage(getName(), view.getView()); } return content; } The instance of The class The The messagepart of all public class SampleStatusBar extends AbstractStatusBar { private static final long serialVersionUID = 1L; @Override protected void checkExtends() {} @Override protected void updateExtends() {} } is a major design goal of SRJRCFrames, so you need a listener for the events from other applications. If you don't care about others, leave that methodbody empty ... @Override public void onApplicationEvent(ApplicationEvent arg0) { // do nothing } The counterpart of the listener is the tossing of events. There's an application service for that purpose: if (aePublisher == null) { aePublisher = (ApplicationEventPublisher) ApplicationServiceProvider.getService(ApplicationEventPublisher.class); } When we have an instance of that service, we could inform others of our existance: aePublisher.publishEvent(new SampleAppStartedEvent("hello world")); If the user selects the menue-entry "Preferences", the application frame SRStarter asks every loaded application for an edtior page and assembles a preferences dialog from that pages. The application frame adds standardpages for common use and shows all pages in a tabbed view - so each page can be randomly activated. To offer such an editor page, ... public JComponent getConfigPage() { if (cfgEdit == null) cfgEdit = new ConfigEditor(getAppConfig()); return cfgEdit; } If your application does not have any userlevel properties, your function may return class ConfigEditor extends AbstractEditor<SampleCfg> { private static final long serialVersionUID = 1L; public ConfigEditor(SampleCfg instance) { super(instance, false); } @Override protected JComponent buildPanel() { if (msgSource == null) msgSource = ApplicationServiceProvider.getService(MessageSource.class); FormLayout layout = new FormLayout("left:max(100dlu;pref), 3dlu, 100dlu:grow"); DefaultFormBuilder builder = new DefaultFormBuilder(layout); String prefix = SampleCfg.class.getSimpleName() + "."; PresentationModel Your sample application will now look like this: public class SampleApp extends AbstractApplication<SampleCfg> { private enum Command { FILE_NEW, SEP_FILE, FILE_OPEN, EDIT_COPY, EDIT_RELEASE, SEP_EDIT, EDIT_DELETE, VIEW_REFRESH } class SampleActionHandler extends AbstractActionHandler implements ApplicationActionHandler { public SampleActionHandler(String name) { super(name); } @Override public void init() { setupAction(getName(), Command.FILE_NEW, new AbstractActionCallback() { @Override public void actionPerformed(ActionEvent ae) { doCreateSample(ae); } }, KeyEvent.VK_N , AccessMode.APP_READ); ... } @Override public void init(Object contextObj) { setupAction(getName(), Command.FILE_OPEN, new AbstractActionContextCallback(contextObj) { @Override public void actionPerformed(ActionEvent ae) { doEditSample(new ActionContextEvent(ae, getContext())); } }, KeyEvent.VK_O); ... } public Enum |