View Javadoc
1   package fr.ifremer.quadrige3.ui.swing.content;
2   
3   /*
4    * #%L
5    * Reef DB :: UI
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2014 - 2015 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU Affero General Public License as published by
13   * the Free Software Foundation, either version 3 of the License, or
14   * (at your option) any later version.
15   *
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   *
21   * You should have received a copy of the GNU Affero General Public License
22   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23   * #L%
24   */
25  
26  import fr.ifremer.quadrige3.core.dao.technical.Assert;
27  import fr.ifremer.quadrige3.core.security.AuthenticationInfo;
28  import fr.ifremer.quadrige3.ui.swing.*;
29  import fr.ifremer.quadrige3.ui.swing.content.db.DbManagerUIHandler;
30  import fr.ifremer.quadrige3.ui.swing.content.login.LoginUI;
31  import jaxx.runtime.SwingUtil;
32  import jaxx.runtime.validator.swing.SwingValidator;
33  import org.apache.commons.lang3.StringUtils;
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  import org.nuiton.jaxx.application.swing.util.CloseableUI;
37  
38  import javax.swing.*;
39  import java.awt.Cursor;
40  import java.awt.Dimension;
41  
42  import static org.nuiton.i18n.I18n.t;
43  
44  /**
45   * <p>AbstractMainUIHandler class.</p>
46   *
47   * @since 0.1
48   */
49  public abstract class AbstractMainUIHandler<M extends ApplicationUIContext, UI extends MainUI<? extends AbstractMainUIHandler>> extends AbstractUIHandler<ApplicationUIContext, UI> {
50  
51      /**
52       * Logger.
53       */
54      private static final Log LOG = LogFactory.getLog(AbstractMainUIHandler.class);
55  
56      private JComponent currentBody;
57  
58      private Timer messageTimer;
59  
60      /**
61       * <p>reloadDbManagerText.</p>
62       */
63      public void reloadDbManagerText() {
64  
65          ApplicationUI<?, ?> ui = getCurrentUI();
66  
67          if (ui != null && ui.getHandler() instanceof DbManagerUIHandler) {
68              DbManagerUIHandler dbManagerUIHandler = (DbManagerUIHandler) ui.getHandler();
69              dbManagerUIHandler.updateMessage();
70          }
71      }
72  
73      //------------------------------------------------------------------------//
74      //-- AbstractApplicationUIHandler methods                                     --//
75      //------------------------------------------------------------------------//
76  
77      /**
78       * {@inheritDoc}
79       */
80      @Override
81      public void beforeInit(UI ui) {
82          super.beforeInit(ui);
83          ApplicationUIContext context = ApplicationUIContext.getInstance();
84          ui.setContextValue(context);
85          ui.setContextValue(ui, MainUI.class.getName());
86  
87          context.installActionUI(ui);
88  
89          // change the current screen
90          context.addPropertyChangeListener(ApplicationUIContext.PROPERTY_SCREEN, evt -> setScreen((Screen) evt.getNewValue()));
91  
92          // ecoute des changements de l'état busy
93          context.addPropertyChangeListener(ApplicationUIContext.PROPERTY_BUSY, evt -> {
94              Boolean newValue = (Boolean) evt.getNewValue();
95              updateBusyState(newValue != null && newValue);
96          });
97  
98          // ecoute des changements de l'état busy
99          context.addPropertyChangeListener(ApplicationUIContext.PROPERTY_HIDE_BODY, evt -> {
100             Boolean newValue = (Boolean) evt.getNewValue();
101             if (getUI() != null && getUI().getBody() != null) {
102                 getUI().getBody().setVisible(newValue != null && newValue);
103             }
104         });
105 
106     }
107 
108     /**
109      * <p>updateBusyState.</p>
110      *
111      * @param busy a boolean.
112      */
113     protected void updateBusyState(boolean busy) {
114 
115         if (LOG.isDebugEnabled()) {
116             LOG.debug(busy ? "block ui in busy mode" : "unblock ui in none busy mode");
117         }
118 
119         // update cursor
120         getUI().setCursor(busy ? Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR) : Cursor.getDefaultCursor());
121 
122         if (getUI().getMenu() != null) {
123             if (busy) getUI().getMenu().removeNotify();
124             else getUI().getMenu().addNotify();
125         }
126     }
127 
128     /**
129      * {@inheritDoc}
130      */
131     @Override
132     public void afterInit(UI ui) {
133 
134         initUI(ui);
135 
136         // allow MainUI frame to move even when UIAction performing or modal dialog (DOCUMENT_MODAL or APPLICATION_MODAL) opened
137         // only dialog with TOOLKIT_MODAL mode will block MainUI
138         // TODO : à laisser en commentaire tant ques les ActionUI de JAXX sont TOOLKIT_MODAL (ou superieure à APPLICATION_MODAL)
139         // spécialement dans FileChooserUtil qui n'ouvre pas en modal
140         // sinon lors des actions longues, le menu est toujours dispo
141         // par contre on perd la possibilté de bouger la fenetre lors de ces actions
142 //        ui.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
143 
144         // installation layer de blocage en mode busy
145         SwingUtil.setLayerUI(getUI().getBody(), getUI().getBusyBlockLayerUI());
146 
147         // Init SwingSession
148         getContext().initSwingSession(getUI());
149 
150         changeTitle();
151 
152         JToolBar bar = getUI().getBottomBar();
153         getUI().getStatus().addWidget(bar, 0);
154 
155         messageTimer = new Timer(3000, e -> getUI().getStatus().clearStatus());
156         messageTimer.setRepeats(false);
157 
158     }
159 
160     /**
161      * {@inheritDoc}
162      */
163     @Override
164     protected JComponent getComponentToFocus() {
165         return getCurrentBody();
166     }
167 
168     /**
169      * <p>Getter for the field <code>currentBody</code>.</p>
170      *
171      * @return a {@link JComponent} object.
172      */
173     public JComponent getCurrentBody() {
174         return currentBody;
175     }
176 
177     public ApplicationUI<?, ?> getCurrentUI() {
178         return (ApplicationUI<?, ?>) currentBody;
179     }
180 
181     /**
182      * <p>closeUI.</p>
183      */
184     public void closeUI() {
185 
186         // close ui
187         onCloseUI();
188 
189         getContext().saveSwingSession(null);
190 
191         // close context
192         getContext().close();
193 
194     }
195 
196     /**
197      * {@inheritDoc}
198      */
199     @Override
200     public void onCloseUI() {
201 
202         if (getUI() != null) {
203             getUI().setVisible(false);
204         }
205     }
206 
207     //------------------------------------------------------------------------//
208     //-- Public methods                                                     --//
209     //------------------------------------------------------------------------//
210 
211     /**
212      * <p>reloadUI.</p>
213      */
214     public void reloadUI() {
215 
216         // close ui
217         ApplicationUIUtil.destroy(getUI());
218 
219         // restart ui
220         Application.getInstance().restartUI();
221     }
222 
223     /**
224      * {@inheritDoc}
225      */
226     @Override
227     public final void showInformationMessage(String message) {
228         if (getUI().isVisible()) {
229             getUI().getStatus().setStatus(ApplicationUIUtil.getHtmlString(message));
230             messageTimer.restart();
231         }
232     }
233 
234     /**
235      * <p>registerValidator.</p>
236      *
237      * @param validator a {@link SwingValidator} object.
238      */
239     public void registerValidator(SwingValidator<?> validator) {
240         getUI().getValidatorMessageWidget().registerValidator(validator);
241     }
242 
243     /**
244      * {@inheritDoc}
245      */
246     @Override
247     public void clearValidators() {
248         getUI().getValidatorMessageWidget().clearValidators();
249     }
250 
251     /**
252      * <p>quitCurrentScreen.</p>
253      *
254      * @return a boolean.
255      */
256     public boolean quitCurrentScreen() {
257 
258         boolean canClose;
259         if (getContext().getScreen() == null || getCurrentUI() == null) {
260 
261             // no screen, surely can quit
262             canClose = true;
263             if (LOG.isWarnEnabled()) {
264                 LOG.warn("==================================================");
265                 LOG.warn("No screen, Should then skipCheckCurrent in action.");
266                 LOG.warn("==================================================");
267             }
268         } else {
269             ApplicationUI<?, ?> currentUI = getCurrentUI();
270             Assert.notNull(currentUI);
271             AbstractUIHandler<?, ?> handler = currentUI.getHandler();
272             if (handler instanceof CloseableUI) {
273 
274                 // try to quit UI
275                 canClose = ((CloseableUI) handler).quitUI();
276             } else {
277 
278                 // can always close ui
279                 canClose = true;
280             }
281         }
282         return canClose;
283     }
284 
285     //------------------------------------------------------------------------//
286     //-- Internal methods                                                   --//
287     //------------------------------------------------------------------------//
288 
289     /**
290      * <p>setScreen.</p>
291      *
292      * @param screen a {@link Screen} object.
293      *               <p>
294      *               TODO ???? à mettre dans un listener quand un nouvel écran est demandé
295      */
296     protected void setScreen(Screen screen) {
297 
298         ApplicationUIContext context = getContext();
299 
300         // clean destroy of current boby
301         if (currentBody != null) {
302             getContext().saveSwingSession(currentBody);
303             getUI().getBody().remove(currentBody);
304             ApplicationUIUtil.destroy(currentBody);
305             currentBody = null;
306         }
307 
308         if (screen != null) {
309 
310             // load new body
311             ApplicationUI<?, ?> screenUI = context.getApplicationUI(screen);
312 
313             if (screenUI != null) {
314 
315                 // Retrieve the Icon object from object context
316                 Icon icon = screenUI.getContextValue(Icon.class);
317 
318                 final JButton showHelp = getUI().getShowHelp();
319                 final JToolBar rightDecoration = new JToolBar();
320                 rightDecoration.setFloatable(false);
321                 rightDecoration.setOpaque(false);
322                 rightDecoration.setBorderPainted(false);
323                 rightDecoration.add(showHelp, 0);
324                 Assert.isInstanceOf(JComponent.class, screenUI, "the new screen to display must be a JComponent");
325                 JComponent newBody = (JComponent) screenUI;
326                 this.currentBody = newBody;
327                 context.getSwingSession().add(newBody, true);
328                 // call afterViewInit()
329                 screenUI.getHandler().afterViewInit();
330                 getUI().getBody().setTitle(screenUI.getHandler().getTitle());
331                 getUI().getBody().setContentContainer(newBody);
332                 getUI().getBody().setLeftDecoration(new JLabel(icon));
333                 getUI().getBody().setRightDecoration(rightDecoration);
334                 getUI().getBody().getRightDecoration().setVisible(true);
335 
336             } else {
337 
338                 // if no screen, set fallback screen
339                 context.getDialogHelper().showErrorDialog(t("quadrige3.main.screen.error", screen.getName()));
340                 context.setFallBackScreen();
341             }
342         }
343     }
344 
345     /**
346      * <p>changeTitle.</p>
347      */
348     public void changeTitle() {
349 
350         String title = getContext().getSelectedScreenTitle();
351 
352         getUI().setTitle(t("quadrige3.main.title.application",
353                 getConfig().getApplicationName(),
354                 getConfig().getVersion(),
355                 title));
356 
357     }
358 
359     /**
360      * <p>askAuthenticationInfo.</p>
361      *
362      * @param url a {@link String} object.
363      * @return a {@link fr.ifremer.quadrige3.core.security.AuthenticationInfo} object.
364      */
365     public AuthenticationInfo askAuthenticationInfo(String url) {
366 
367         AuthenticationInfo authentication;
368 
369         // Auto-login, if config as login/pwd (only the first time)
370         if (getContext().getAuthenticationInfo() == null
371                 && StringUtils.isNotBlank(getConfig().getAuthenticationDefaultUsername())
372                 && StringUtils.isNotBlank(getConfig().getAuthenticationDefaultPassword())) {
373             authentication = new AuthenticationInfo(
374                     getConfig().getAuthenticationDefaultUsername(),
375                     getConfig().getAuthenticationDefaultPassword()
376             );
377         }
378 
379         // Open the login dialog
380         else {
381 
382             AuthenticationInfo authenticationInfo = getContext().getAuthenticationInfo();
383 
384             // Get last login if exists
385             if (authenticationInfo == null && StringUtils.isNotBlank(getConfig().getAuthenticationDefaultUsername())) {
386                 authenticationInfo = new AuthenticationInfo(getConfig().getAuthenticationDefaultUsername(), null);
387             }
388 
389             LoginUI loginUI = new LoginUI(getContext());
390             loginUI.getModel().setUrl(url);
391             loginUI.getModel().setAuthenticationInfo(authenticationInfo);
392             openDialogForceOnTop(loginUI, new Dimension(Math.max(300, loginUI.getPreferredSize().width), loginUI.getPreferredSize().height)); // Fix the size (Mantis #47634)
393             authentication = loginUI.getModel().getAuthenticationInfo();
394         }
395 
396         if (authentication != null) {
397 
398             // store it back in authentication store
399             getContext().setAuthenticationInfo(authentication);
400         }
401 
402         return authentication;
403     }
404 
405 }