View Javadoc
1   /*
2    * Copyright 2013-2023 Medical Information Systems Research Group (https://medical.zcu.cz),
3    * Department of Computer Science and Engineering, University of West Bohemia.
4    * Address: Univerzitni 8, 306 14 Plzen, Czech Republic.
5    *
6    * This file is part of Sparkle project.
7    *
8    * Sparkle is free software: you can redistribute it and/or modify
9    * it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License.
11   *
12   * Sparkle is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15   * GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with Sparkle. If not, see <http://www.gnu.org/licenses/>.
19   */
20  package cz.zcu.mre.sparkle.gui.mainForm.mainTabPane;
21  
22  import cz.zcu.mre.sparkle.Messages;
23  import cz.zcu.mre.sparkle.data.Storage;
24  import cz.zcu.mre.sparkle.gui.dialogs.other.ProgressDialog;
25  import cz.zcu.mre.sparkle.gui.evaluation.EvaluationTab;
26  import cz.zcu.mre.sparkle.gui.evaluation.queryTabs.select.SelectEvaluationTab;
27  import cz.zcu.mre.sparkle.gui.mainForm.MainForm;
28  import cz.zcu.mre.sparkle.gui.query.QueryFormPane;
29  import cz.zcu.mre.sparkle.gui.query.QueryTab;
30  import cz.zcu.mre.sparkle.gui.query.QueryTabPane;
31  import cz.zcu.mre.sparkle.gui.query.queryTypes.insert.InsertQueryFormPane;
32  import cz.zcu.mre.sparkle.gui.query.queryTypes.insert.InsertQueryTab;
33  import cz.zcu.mre.sparkle.gui.query.other.CloseableTab;
34  import cz.zcu.mre.sparkle.gui.query.other.SaverTab;
35  import cz.zcu.mre.sparkle.gui.query.queryTypes.ask.AskQueryFormPane;
36  import cz.zcu.mre.sparkle.gui.query.queryTypes.ask.AskQueryTab;
37  import cz.zcu.mre.sparkle.gui.query.queryTypes.construct.ConstructQueryFormPane;
38  import cz.zcu.mre.sparkle.gui.query.queryTypes.construct.ConstructQueryTab;
39  import cz.zcu.mre.sparkle.gui.query.queryTypes.delete.DeleteInsertQueryFormPane;
40  import cz.zcu.mre.sparkle.gui.query.queryTypes.delete.DeleteInsertQueryTab;
41  import cz.zcu.mre.sparkle.gui.query.queryTypes.delete.DeleteQueryFormPane;
42  import cz.zcu.mre.sparkle.gui.query.queryTypes.delete.DeleteQueryTab;
43  import cz.zcu.mre.sparkle.gui.query.queryTypes.describe.DescribeQueryFormPane;
44  import cz.zcu.mre.sparkle.gui.query.queryTypes.describe.DescribeQueryTab;
45  import cz.zcu.mre.sparkle.gui.query.queryTypes.select.SelectQueryFormPane;
46  import cz.zcu.mre.sparkle.gui.query.queryTypes.select.SelectQueryTab;
47  import cz.zcu.mre.sparkle.gui.query.queryTypes.subselect.SubSelectPane;
48  import cz.zcu.mre.sparkle.gui.query.queryTypes.subselect.SubSelectQueryFormPane;
49  import cz.zcu.mre.sparkle.gui.query.queryTypes.subselect.SubSelectQueryTab;
50  import javafx.collections.ObservableList;
51  import javafx.concurrent.Task;
52  import javafx.event.Event;
53  import javafx.event.EventHandler;
54  import javafx.scene.control.Tab;
55  import javafx.scene.control.TabPane;
56  import org.reactfx.collection.LiveArrayList;
57  import java.io.File;
58  import java.util.Iterator;
59  import java.util.LinkedList;
60  import java.util.List;
61  import java.util.Queue;
62  import java.util.concurrent.ExecutionException;
63  import java.util.logging.Level;
64  import java.util.logging.Logger;
65  import static cz.zcu.mre.sparkle.tools.Definitions.QUERY_FILE_EXTENSION_DELIMITER;
66  
67  /**
68   * Kontroler {@code TabPane} pro zalozky s dotazy nebo vysledkem dotazu.
69   *
70   * @author Jan Smucr
71   * @author Klara Hlavacova
72   * @author Petr Vcelak (vcelak@kiv.zcu.cz)
73   */
74  public class MainTabPane extends TabPane {
75  
76      private static final Logger LOG = Logger.getLogger(MainForm.class.getName());
77  
78      public enum QueryType {
79          SELECT, ASK, DESCRIBE, CONSTRUCT, DELETE, INSERT, DELETE_INSERT, SUBSELECT
80      }
81  
82      /**
83       * Akce pri uzavreni aplikace - zavreni zalozek.
84       *
85       * @param mainForm okno (hlavni formular)
86       *
87       * @return false - chyba, true - ok
88       */
89      public final boolean onCloseRequest(MainForm mainForm) {
90          ObservableList<Tab> tabs = new LiveArrayList<>(getTabs());
91          tabs.forEach((tab) -> {
92              QueryTabPane.selectFormTab(tab);
93          });
94  
95          // Postupné uzavření záložek. Každá záložka může vyvolat dialog tázající-se na uložení souboru.
96          final Iterator<Tab> iter = getTabs().iterator();
97  
98          while (iter.hasNext()) {
99              final Tab tab = iter.next();
100 
101             if (tab instanceof CloseableTab && !(tab instanceof SubSelectQueryTab)) {
102                 if (!((CloseableTab) tab).requestClose()) {
103                     return false;
104                 }
105             }
106             if (mainForm.getMainTabPane().getTabs().contains(tab)) {
107                 iter.remove();
108             }
109         }
110 
111         saveAndDisconnect(mainForm);
112         return true;
113     }
114 
115     /**
116      * Ulozi nastaveni (lokalni zdroje, ...) a odpoji uloziste.
117      *
118      * @param mainForm okno (hlavní formular)
119      */
120     private void saveAndDisconnect(MainForm mainForm) {
121         try {
122             ProgressDialog.performTask(mainForm.getStage(), new Task<Void>() {
123                 @Override
124                 protected Void call() throws Exception {
125                     updateMessage(Messages.getString("SAVING_CONFIGURATION")); //$NON-NLS-1$
126                     mainForm.storeObjects();
127                     mainForm.saveFormSettings();
128                     updateMessage(Messages.getString("DISCONNECTING")); //$NON-NLS-1$
129                     mainForm.disconnect();
130                     return null;
131                 }
132             });
133         } catch (InterruptedException | ExecutionException e) {
134             LOG.log(Level.SEVERE, "Exception: ", e); //$NON-NLS-2$
135         }
136     }
137 
138     /**
139      * Vlozi zalozku.
140      *
141      * @param tab vkladana zalozka
142      */
143     private void addTab(final Tab tab) {
144         getTabs().add(tab);
145     }
146 
147     /**
148      * Vrati aktivni {@link QueryTab} nebo <code>null</code>.
149      *
150      * @return Aktivní {@link QueryTab} nebo <code>null</code>.
151      */
152     public QueryTab<?> getCurrentQueryTab() {
153         final Tab tab = getSelectionModel().getSelectedItem();
154         return tab instanceof QueryTab<?> ? (QueryTab<?>) tab : null;
155     }
156 
157     /**
158      * Method shows relevant tab.
159      *
160      * @param tab Relevant tab.
161      */
162     public void showTab(Tab tab) {
163         getSelectionModel().select(tab);
164     }
165 
166     /**
167      * Vrací {@link QueryFormPane} vázaný na aktivní {@link QueryTab} nebo
168      * {@link EvaluationTab}.
169      *
170      * @return Instance {@link QueryFormPane}.
171      */
172     public QueryFormPane<?> getCurrentQueryPane() {
173         QueryTab<?> tab = getCurrentQueryTab();
174         if (tab == null) {
175             final EvaluationTab<?> evTab = getCurrentEvaluationTab();
176             if (evTab == null) {
177                 return null;
178             }
179             tab = evTab.getQueryTab();
180         }
181         return tab.getQueryFormPane();
182     }
183 
184     /**
185      * @return Aktivní {@link EvaluationTab} nebo <code>null</code>.
186      */
187     private EvaluationTab<?> getCurrentEvaluationTab() {
188         final Tab tab = getSelectionModel().getSelectedItem();
189         return tab instanceof EvaluationTab<?> ? (EvaluationTab<?>) tab : null;
190     }
191 
192     /**
193      * It returns relevant {@link QueryTab} due to parameter
194      * ({@link QueryFormPane}).
195      *
196      * @param queryFormPane {@link QueryFormPane} of wanted {@link QueryTab}.
197      *
198      * @return Relevant {@link QueryTab}.
199      */
200     public QueryTab getQueryTab(QueryFormPane queryFormPane) {
201         for (Tab tab : getTabs()) {
202             if (!(tab instanceof SelectEvaluationTab)) {
203                 QueryTab qt = (QueryTab) tab;
204                 if (qt.getQueryFormPane() == queryFormPane) {
205                     return qt;
206                 }
207             }
208         }
209         return null;
210     }
211 
212     /**
213      * Vrati {@code QueryFormPane} rodicovske zalozky subselektu.
214      *
215      * @param queryTab subselekt zalozka
216      *
217      * @return {@code QueryFormPane} rodicovske zalozky subselektu
218      */
219     public static QueryFormPane<?> getMainQueryPart(SubSelectQueryTab queryTab) {
220         QueryFormPane<?> queryFormPane = null;
221         SubSelectQueryFormPane subSelectQueryPane = (SubSelectQueryFormPane) queryTab.getQueryFormPane();
222 
223         while (queryFormPane == null) {
224             QueryFormPane<?> parentQueryFormPane = subSelectQueryPane.getSubSelectPane().getParentQueryFormPane();
225 
226             if (parentQueryFormPane instanceof SubSelectQueryFormPane) {
227                 subSelectQueryPane = (SubSelectQueryFormPane) parentQueryFormPane;
228             } else {
229                 queryFormPane = parentQueryFormPane;
230             }
231         }
232 
233         return queryFormPane;
234     }
235 
236     /**
237      * Nacte dotaz ze souboru
238      *
239      * @param file soubor s dotazem (.sqf, .txt)
240      * @param mainForm The main form.
241      */
242     public static final void open(final File file, MainForm mainForm) {
243 
244         for (final Tab tab : mainForm.getMainTabPane().getTabs()) {
245             if (!(tab instanceof SaverTab)) {
246                 continue;
247             }
248             final File openedFile = ((SaverTab) tab).fileProperty().get();
249 
250             if (file.equals(openedFile)) {
251                 if (!((CloseableTab) tab).requestClose()) {
252                     return;
253                 }
254                 closeTab(tab, mainForm);
255                 //mainTabPane.getSelectionModel().select(tab);
256                 break;
257             }
258         }
259 
260         Storage storage
261                 = new Storage(mainForm.getAppPrefixesStorage(), mainForm.getAppResourcesStorage(),
262                         mainForm.getAppDataTypesStorage(), mainForm.getAppFunctionsStorage());
263 
264         int countTabBeforeLoading = mainForm.getMainTabPane().getTabs().size();
265         final Tab tab = QueryTab.open(mainForm, file, mainForm.getStage(), mainForm.getDataAgent(), storage);
266 
267         int countTabAfterLoading = mainForm.getMainTabPane().getTabs().size();
268         int positionOfMainQueryPart = countTabAfterLoading - (countTabAfterLoading - countTabBeforeLoading);
269 
270         if (tab != null) { // Reordering of positions of loaded query and its SUBSELECTs.
271             mainForm.getMainTabPane().getTabs().add(positionOfMainQueryPart, tab);
272             mainForm.getMainTabPane().getSelectionModel().select(tab);
273             setSubQueriesDefaultState(tab, mainForm);
274         } else { // Removing of SubSelectQueryTabs - if loading failed
275             for (int i = positionOfMainQueryPart; i < countTabAfterLoading; i++) {
276                 mainForm.getMainTabPane().getTabs().remove(positionOfMainQueryPart);
277             }
278         }
279     }
280 
281     /**
282      * Zavre zalozku.
283      *
284      * @param tab Zavirana zalozka
285      * @param mainForm okno (hlavni formular)
286      */
287     public static void closeTab(Tab tab, MainForm mainForm) {
288         EventHandler<Event> handler = tab.getOnClosed();
289         if (null != handler) {
290             handler.handle(null);
291         } else {
292 
293             try {
294                 mainForm.getMainTabPane().getTabs().remove(tab);
295 
296             } catch (Exception e) {
297                 LOG.info(e.getMessage());
298             }
299         }
300     }
301 
302     /**
303      * Method creates binding between "main query part" (e.g. SELECT query) and
304      * SUBSELECT. It's used during auto-loading query from text file.
305      *
306      * @param mainQueryTab Main query tab (e.g. SELECT query).
307      * @param mainForm The main form.
308      */
309     public static void setSubQueriesDefaultState(Tab mainQueryTab, MainForm mainForm) {
310 
311         if (mainQueryTab instanceof QueryTab) {
312             QueryTab queryTabMainQuery = (QueryTab) mainQueryTab;
313 
314             Queue<QueryTab> nodeQueue = new LinkedList<>();
315             String subSelectSuffix = Messages.getString("SUBSELECT_QUERY_DEFAULT_FILE_NAME"); //$NON-NLS-1$
316             nodeQueue.add(queryTabMainQuery);
317 
318             while (!nodeQueue.isEmpty()) {
319                 QueryTab<?> currentQueryTab = nodeQueue.remove();
320 
321                 mainForm.getContextMenu(currentQueryTab);
322 
323                 String queryTabName;
324                 if (currentQueryTab.getQueryFormPane() instanceof SubSelectQueryFormPane) {
325                     queryTabName = currentQueryTab.titleProperty().get();
326 
327                     // Binding changed properties
328                     currentQueryTab.setCheckingMainQueryPart(queryTabMainQuery.getFormChangedProperty());
329                     queryTabMainQuery.setCheckingSubSelect(currentQueryTab.getFormChangedProperty());
330                 } else {
331                     String name = queryTabMainQuery.titleProperty().get();
332                     queryTabName = name.substring(0, name.lastIndexOf(QUERY_FILE_EXTENSION_DELIMITER));
333                 }
334 
335                 int counter = 1;
336                 List<SubSelectPane> subSelectPanes = currentQueryTab.getQueryFormPane().getSubSelectPanes();
337 
338                 for (SubSelectPane subSelectPane : subSelectPanes) {
339                     subSelectPane.setQueryTabName(queryTabMainQuery, queryTabName + subSelectSuffix + counter);
340                     nodeQueue.add(subSelectPane.getParentQueryTab());
341                     counter++;
342                 }
343             }
344         }
345 
346         /*final Color color = queryTabMainQuery.getQueryFormPane().getObtainedColor();
347         if (color != null) {
348             queryTabMainQuery.setBackgroundColor(color);
349         }*/
350         mainForm.setLoading(false);
351     }
352 
353     /**
354      * Vrati zalozku s danym typem dotazu.
355      *
356      * @param type typ dotazu
357      * @param mainForm okno (hlavni formular)
358      * @return Return the created Tab.
359      */
360     public Tab createQueryTab(QueryType type, MainForm mainForm) {
361         Storage localStorage = new Storage(mainForm.getAppPrefixesStorage(), mainForm.getAppResourcesStorage(),
362                 mainForm.getAppDataTypesStorage(), mainForm.getAppFunctionsStorage());
363         final Tab tab;
364         switch (type) {
365 
366             case SELECT:
367                 tab = new SelectQueryTab(new SelectQueryFormPane(mainForm, mainForm.getDataAgent(), localStorage,
368                         SelectQueryFormPane.XML_QUERY_TYPE_VALUE));
369                 addAndSelectTab(tab);
370                 return tab;
371 
372             case ASK:
373                 tab = new AskQueryTab(new AskQueryFormPane(mainForm, mainForm.getDataAgent(), localStorage,
374                         AskQueryFormPane.XML_QUERY_TYPE_VALUE));
375                 addAndSelectTab(tab);
376                 return tab;
377 
378             case DESCRIBE:
379                 tab = new DescribeQueryTab(new DescribeQueryFormPane(mainForm, mainForm.getDataAgent(), localStorage,
380                         DescribeQueryFormPane.XML_QUERY_TYPE_VALUE));
381                 addAndSelectTab(tab);
382                 return tab;
383 
384             case CONSTRUCT:
385                 tab = new ConstructQueryTab(
386                         new ConstructQueryFormPane(mainForm, mainForm.getDataAgent(), localStorage,
387                                 ConstructQueryFormPane.XML_QUERY_TYPE_VALUE));
388                 addAndSelectTab(tab);
389                 return tab;
390 
391             case DELETE_INSERT:
392                 tab = new DeleteInsertQueryTab(
393                         new DeleteInsertQueryFormPane(mainForm, mainForm.getDataAgent(), localStorage,
394                                 DeleteInsertQueryFormPane.XML_QUERY_TYPE_VALUE));
395                 addAndSelectTab(tab);
396                 return tab;
397 
398             case INSERT:
399                 tab = new InsertQueryTab(new InsertQueryFormPane(mainForm, mainForm.getDataAgent(), localStorage,
400                         InsertQueryFormPane.XML_QUERY_TYPE_VALUE));
401                 addAndSelectTab(tab);
402                 return tab;
403 
404             case DELETE:
405                 tab = new DeleteQueryTab(new DeleteQueryFormPane(mainForm, mainForm.getDataAgent(), localStorage,
406                         DeleteQueryFormPane.XML_QUERY_TYPE_VALUE));
407                 addAndSelectTab(tab);
408                 return tab;
409 
410             case SUBSELECT:
411                 tab = new SubSelectQueryTab(new SubSelectQueryFormPane(mainForm, mainForm.getDataAgent(),
412                         localStorage, SubSelectQueryFormPane.XML_QUERY_TYPE_VALUE));
413                 tab.setClosable(false);
414                 addTab(tab);
415                 return tab;
416         }
417 
418         return null;
419     }
420 
421     /**
422      * Vrati vybranou zalozku.
423      *
424      * @return vybranou zalozka
425      */
426     public Tab getCurrentTab() {
427         return getSelectionModel().getSelectedItem();
428     }
429 
430     /**
431      * Vlozi zalozku a vybere ji.
432      *
433      * @param tab vkladana zalozka
434      */
435     private void addAndSelectTab(final Tab tab) {
436         getTabs().add(tab);
437         getSelectionModel().select(tab);
438     }
439 
440 }