View Javadoc

1   /*
2    * Copyright 2006-2016 The JGUIraffe Team.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License")
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package net.sf.jguiraffe.gui.app;
17  
18  import net.sf.jguiraffe.gui.builder.Builder;
19  import net.sf.jguiraffe.gui.builder.window.Window;
20  import net.sf.jguiraffe.gui.cmd.CommandBase;
21  import net.sf.jguiraffe.locators.Locator;
22  
23  /**
24   * <p>
25   * A specialized {@code Command} implementation for opening a sub window.
26   * </p>
27   * <p>
28   * This {@code Command} class provides functionality for opening sub frames or
29   * dialog boxes. An instance is initialized with the {@link Locator} to the
30   * builder script that defines the window. It executes this script in the worker
31   * thread and eventually displays the resulting window.
32   * </p>
33   * <p>
34   * Most applications need to open dialog boxes or other sub windows. With this
35   * command this can be done in a standard way. Using {@link CommandActionTask}
36   * an instance can be associated with an action. It is possible to define such
37   * an action completely in a builder script using the dependency injection
38   * framework. This can look as follows:
39   *
40   * <pre>
41   * &lt;!-- Definition of the command bean for opening a dialog --&gt;
42   * &lt;di:bean name=&quot;openDialogCommand&quot; singleton=&quot;false&quot;
43   *   beanClass=&quot;net.sf.jguiraffe.gui.app.OpenWindowCommand&quot;&gt;
44   *   &lt;di:constructor&gt;
45   *     &lt;di:param&gt;
46   *       &lt;di:bean class=&quot;net.sf.jguiraffe.locators.ClassPathLocator&quot;&gt;
47   *         &lt;di:factory&gt;
48   *           &lt;di:methodInvocation method=&quot;getInstance&quot;&gt;
49   *             &lt;di:param value=&quot;myDialog.jelly&quot;/&gt;
50   *           &lt;/di:methodInvocation&gt;
51   *         &lt;/di:factory&gt;
52   *       &lt;/di:bean&gt;
53   *     &lt;/di:param&gt;
54   *   &lt;/di:constructor&gt;
55   * &lt;/di:bean&gt;
56   * &lt;!-- The command task used by the action for opening a dialog --&gt;
57   * &lt;di:bean name=&quot;openDialogTask&quot;
58   *   beanClass=&quot;net.sf.jguiraffe.gui.app.CommandActionTask&quot;&gt;
59   *   &lt;di:setProperty property=&quot;commandBeanName&quot;
60   *     value=&quot;openDialogCommand&quot;/&gt;
61   *   &lt;di:setProperty property=&quot;beforeEnabler&quot;&gt;
62   *     &lt;di:bean beanClass=&quot;net.sf.jguiraffe.gui.builder.enablers.ActionEnabler&quot;&gt;
63   *       &lt;di:constructor&gt;
64   *         &lt;di:param value=&quot;openDialogAction&quot;/&gt;
65   *       &lt;/di:constructor&gt;
66   *     &lt;/di:bean&gt;
67   *   &lt;/di:setProperty&gt;
68   * &lt;/di:bean&gt;
69   * &lt;!-- The action for opening a dialog --&gt;
70   * &lt;a:action name=&quot;openDialogAction&quot; text=&quot;Open dialog...&quot;
71   *   taskBean=&quot;openDialogTask&quot;/&gt;
72   * </pre>
73   *
74   * This fragment first defines the {@code OpenWindowCommand} bean. The bean is
75   * passed a newly created {@code Locator} object when it is constructed. Here a
76   * locator implementation is used that searches the builder script in the class
77   * path. It follows the definition of the action task bean. This is a
78   * {@link CommandActionTask} which is configured with our command bean. Note
79   * that also an <em>action enabler</em> is specified; this object disables the
80   * action while it is executed. Finally the action itself is defined. It
81   * references the task bean. The action can later be used to create a menu item
82   * or a button in a tool bar.
83   * </p>
84   *
85   * @author Oliver Heger
86   * @version $Id: OpenWindowCommand.java 205 2012-01-29 18:29:57Z oheger $
87   */
88  public class OpenWindowCommand extends CommandBase implements ApplicationClient
89  {
90      /** The locator to the builder script. */
91      private final Locator locator;
92  
93      /** Stores the central application object. */
94      private Application application;
95  
96      /** The window created in the background thread. */
97      private Window window;
98  
99      /**
100      * Creates a new instance of {@code OpenWindowCommand} and initializes it
101      * with the {@code Locator} pointing to the builder script. The command will
102      * execute this builder script and display the resulting window.
103      *
104      * @param loc the {@code Locator} to the builder script (must not be
105      *        <b>null</b>)
106      * @throws IllegalArgumentException if the {@code Locator} is <b>null</b>
107      */
108     public OpenWindowCommand(Locator loc)
109     {
110         super(true);
111         if (loc == null)
112         {
113             throw new IllegalArgumentException("Locator must not be null!");
114         }
115         locator = loc;
116     }
117 
118     /**
119      * Returns the {@code Locator} to the builder script executed by this
120      * command.
121      *
122      * @return the {@code Locator}
123      */
124     public final Locator getLocator()
125     {
126         return locator;
127     }
128 
129     /**
130      * Returns the central {@code Application} instance.
131      *
132      * @return the {@code Application}
133      */
134     public final Application getApplication()
135     {
136         return application;
137     }
138 
139     /**
140      * Sets the central {@code Application} instance. From this object the
141      * {@code ApplicationContext} is obtained, which provides access to the
142      * builder. This method is typically called by the dependency injection
143      * framework.
144      *
145      * @param app the central {@code Application} object
146      */
147     public final void setApplication(Application app)
148     {
149         application = app;
150     }
151 
152     /**
153      * <p>
154      * Executes this command. This implementation calls the builder to execute
155      * the builder script defining the window to be opened. Then the window is
156      * actually displayed.
157      * </p>
158      * <p>
159      * Note: This method does not implement a sophisticated exception handling.
160      * It expects the current {@code Locator} to be valid and to point to a
161      * builder script that actually returns a window. Otherwise, an exception is
162      * thrown which will be passed to the {@code onException()} method.
163      * </p>
164      * @throws Exception if an error occurs
165      */
166     public void execute() throws Exception
167     {
168         if (getApplication() == null)
169         {
170             throw new IllegalStateException("No Application reference set!");
171         }
172 
173         Builder builder = getApplication().getApplicationContext().newBuilder();
174         ApplicationBuilderData builderData = getApplication()
175                 .getApplicationContext().initBuilderData();
176         prepareBuilderData(builderData);
177 
178         window = builder.buildWindow(getLocator(), builderData);
179     }
180 
181     /**
182      * Updates the UI after background processing is complete. This
183      * implementation opens the window created in the background thread unless
184      * an exception occurred before.
185      */
186     @Override
187     protected void performGUIUpdate()
188     {
189         if (getException() == null)
190         {
191             assert getWindow() != null : "No window!";
192             getWindow().open();
193         }
194     }
195 
196     /**
197      * Prepares the {@code ApplicationBuilderData} object. This method is called
198      * by {@code execute()} with the {@code ApplicationBuilderData} object
199      * obtained from the {@link ApplicationContext}. Derived classes can
200      * override it to perform custom initialization. This base implementation is
201      * empty.
202      *
203      * @param builderData the {@code ApplicationBuilderData} object to be
204      *        initialized
205      */
206     protected void prepareBuilderData(ApplicationBuilderData builderData)
207     {
208     }
209 
210     /**
211      * Returns the {@code Window} that was built in the background thread. This
212      * method is called by the GUI updater to obtain the window to be displayed.
213      * It exists mainly for testing purposes.
214      *
215      * @return the {@code Window} to be displayed
216      */
217     Window getWindow()
218     {
219         return window;
220     }
221 }