Projekt

Obecné

Profil

Stáhnout (16 KB) Statistiky
| Větev: | Tag: | Revize:
1
import java.io.File;
2
import java.util.Properties;
3

    
4
import io.Database.DB_Messenger;
5
import io.FileWorker;
6
import javafx.application.Application;
7
import javafx.application.Platform;
8
import javafx.collections.FXCollections;
9
import javafx.collections.ObservableList;
10
import javafx.geometry.Insets;
11
import javafx.geometry.Pos;
12
import javafx.scene.Node;
13
import javafx.scene.Parent;
14
import javafx.scene.Scene;
15
import javafx.scene.control.Button;
16
import javafx.scene.control.ComboBox;
17
import javafx.scene.control.Label;
18
import javafx.scene.control.Menu;
19
import javafx.scene.control.MenuBar;
20
import javafx.scene.control.MenuItem;
21
import javafx.scene.control.PasswordField;
22
import javafx.scene.control.Separator;
23
import javafx.scene.control.SeparatorMenuItem;
24
import javafx.scene.control.Tab;
25
import javafx.scene.control.TabPane;
26
import javafx.scene.control.TabPane.TabClosingPolicy;
27
import javafx.scene.control.TextField;
28
import javafx.scene.image.Image;
29
import javafx.scene.image.ImageView;
30
import javafx.scene.input.KeyCode;
31
import javafx.scene.input.KeyCodeCombination;
32
import javafx.scene.input.KeyCombination;
33
import javafx.scene.layout.BorderPane;
34
import javafx.scene.layout.HBox;
35
import javafx.scene.layout.Priority;
36
import javafx.scene.layout.VBox;
37
import javafx.stage.FileChooser;
38
import javafx.stage.Stage;
39

    
40
/**
41
 * <p>
42
 * Class for creating a GUI. <br>
43
 * <br>
44
 * Note, VM arguments for Java 11: <br>
45
 * --module-path libs\javafx-sdk-11.0.2\lib --add-modules=javafx.controls
46
 */
47
public class Window extends Application implements IConversionResults {
48

    
49
	/**
50
	 * Main window.
51
	 */
52
	private Stage stage;
53

    
54
	/**
55
	 * Graphic node of menu item for full screen.
56
	 */
57
	private Label fullScreen;
58

    
59
	/**
60
	 * Read-only text area with ACE.
61
	 */
62
	private Editor editor;
63

    
64
	/**
65
	 * Layout for output file.
66
	 */
67
	private VBox outputLayout;
68

    
69
	/**
70
	 * Thread for converting input to JSON.
71
	 */
72
	private Converter converter;
73

    
74
	/**
75
	 * Configuration file.
76
	 */
77
	private Properties properties;
78

    
79
	@Override
80
	public void init() throws Exception {
81
		super.init();
82
		converter = new Converter(this);
83
		converter.start();
84
		properties = FileWorker.getConfig();
85
	}
86

    
87
	@Override
88
	public void stop() throws Exception {
89
		super.stop();
90
		converter.end();
91
		converter.join();
92
		FileWorker.saveConfig(properties);
93
		Platform.exit();
94
	}
95

    
96
	@Override
97
	public void start(Stage stage) throws Exception {
98
		this.stage = stage;
99
		stage.getIcons().add(new Image(FileWorker.getResource("/logo.png")));
100
		stage.setTitle("Java Object Universal Deserializer");
101
		stage.setScene(createScene());
102
		stage.show();
103

    
104
		stage.setMinWidth(stage.getWidth());
105
		stage.setMinHeight(stage.getHeight());
106

    
107
		stage.fullScreenProperty().addListener((obs, oldState, newState) -> {
108
			changeFullScreenMenuItem();
109
		});
110
	}
111

    
112
	/**
113
	 * @return main scene with set CSS.
114
	 */
115
	private Scene createScene() {
116
		Scene scene = new Scene(createLayout());
117
		scene.getStylesheets().add(FileWorker.getResource("/main.css"));
118
		return scene;
119
	}
120

    
121
	/**
122
	 * @return main layout.
123
	 */
124
	private Parent createLayout() {
125
		BorderPane layout = new BorderPane();
126

    
127
		layout.setTop(createMenu());
128
		layout.setCenter(createBodyLayout());
129

    
130
		return layout;
131
	}
132

    
133
	/**
134
	 * @return body layout of the window.
135
	 */
136
	private Node createBodyLayout() {
137
		// Tabs for input file and SQL query.
138
		TabPane header = new TabPane();
139
		header.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE);
140
		header.getTabs().add(createInputFileTab());
141
		header.getTabs().add(createQueryTab());
142

    
143
		// ACE editor.
144
		editor = new Editor();
145

    
146
		// Last mode and theme of the editor.
147
		String propMode = properties.getProperty(FileWorker.ACE_MODE);
148
		String propTheme = properties.getProperty(FileWorker.ACE_THEME);
149

    
150
		// Get all ACE modes and themes.
151
		ObservableList<String> aceModes = FXCollections.observableArrayList();
152
		ObservableList<String> aceThemes = FXCollections.observableArrayList();
153
		FileWorker.getAceModesAndThemes(aceModes, aceThemes);
154

    
155
		// Sets modes combo box.
156
		ComboBox<String> modeBox = new ComboBox<String>();
157
		modeBox.setItems(aceModes);
158
		modeBox.getSelectionModel().select(propMode == null ? Editor.DEFAULT_MODE : propMode);
159
		modeBox.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
160
			if (modeBox.getValue() != null) {
161
				properties.setProperty(FileWorker.ACE_MODE, modeBox.getValue());
162
				editor.setMode(modeBox.getValue());
163
			}
164
		});
165

    
166
		// Sets themes combo box.
167
		ComboBox<String> themeBox = new ComboBox<String>();
168
		themeBox.setItems(aceThemes);
169
		themeBox.getSelectionModel().select(propTheme == null ? Editor.DEFAULT_THEME : propTheme);
170
		themeBox.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
171
			if (themeBox.getValue() != null) {
172
				properties.setProperty(FileWorker.ACE_THEME, themeBox.getValue());
173
				editor.setTheme(themeBox.getValue());
174
			}
175
		});
176

    
177
		// ACE settings layout.
178
		HBox aceSettings = new HBox();
179
		aceSettings.setPadding(new Insets(0, 10, 0, 0));
180
		aceSettings.setSpacing(10.0);
181
		aceSettings.setAlignment(Pos.CENTER_RIGHT);
182
		aceSettings.getChildren().addAll(new Label("Nastavení editoru (režim / téma):"), modeBox, new Label("/"),
183
				themeBox);
184

    
185
		// Layout for editor with settings.
186
		VBox editorLayout = new VBox();
187
		editorLayout.setSpacing(5.0);
188
		VBox.setVgrow(editor.getView(), Priority.ALWAYS);
189
		editorLayout.getChildren().addAll(editor.getView(), aceSettings);
190

    
191
		// Output file label and path.
192
		Label forOutputFile = new Label("Výstupní soubor:");
193
		Label outputFile = new Label("    Ještě nebyl vybrán žádný soubor...");
194
		outputFile.setStyle("-fx-font-style: italic;");
195

    
196
		// Button to save the resulting JSON.
197
		Button save = new Button("Uložit");
198
		save.setOnAction(event -> {
199
			File jsonFile = null;
200

    
201
			FileChooser fCh = new FileChooser();
202
			fCh.setInitialDirectory(new File("."));
203
			fCh.getExtensionFilters().add(new FileChooser.ExtensionFilter("JSON Files", "*.json"));
204
			File file = fCh.showSaveDialog(stage);
205
			if (file != null) {
206
				jsonFile = file;
207
				outputFile.setText(file.getAbsolutePath());
208
				outputFile.setStyle("-fx-font-weight: bold;");
209
			}
210

    
211
			if (jsonFile != null) {
212
				String title = "Uložení JSON";
213
				try {
214
					FileWorker.saveJson(jsonFile, editor.getJson());
215
					Report.info(title, null, "Uložení JSON souboru proběhlo v pořádku.");
216
				} catch (Exception e) {
217
					Report.error(title, null, "Při ukládání JSON souboru nastala chyba.");
218
				}
219
			}
220
		});
221

    
222
		HBox bOF = new HBox();
223
		bOF.setAlignment(Pos.CENTER_RIGHT);
224
		bOF.getChildren().add(save);
225

    
226
		// Output file layout.
227
		outputLayout = new VBox();
228
		outputLayout.setPadding(new Insets(0, 10, 10, 10));
229
		outputLayout.setSpacing(5.0);
230
		outputLayout.getChildren().add(forOutputFile);
231
		outputLayout.getChildren().add(outputFile);
232
		outputLayout.getChildren().add(bOF);
233
		setOutputLayoutDisabled(true);
234

    
235
		// Main layout in the body.
236
		VBox layout = new VBox();
237
		layout.setSpacing(10.0);
238
		VBox.setVgrow(editorLayout, Priority.ALWAYS);
239
		layout.getChildren().addAll(header, new Separator(), editorLayout, new Separator(), outputLayout);
240

    
241
		return layout;
242
	}
243

    
244
	/**
245
	 * @return a tab for connecting to a database.
246
	 */
247
	private Tab createQueryTab() {
248
		// Get the last inserted texts.
249
		String propType = properties.getProperty(FileWorker.DB_TYPE);
250
		String propUrl = properties.getProperty(FileWorker.DB_URL);
251
		String propUser = properties.getProperty(FileWorker.DB_USER);
252

    
253
		// Help text, database names and driver classes.
254
		String promptTexts[] = new String[] { "jdbc:oracle:thin:@server:port:nazevDB",
255
				"jdbc:sqlserver://server:port;databaseName=nazevDB;", "jdbc:mysql://server:port/nazevDB" };
256
		String dbTypeTexts[] = new String[] { "ORACLE", "MS-SQL", "MySQL" };
257
		String dbDriverClasses[] = new String[] { "oracle.jdbc.driver.OracleDriver",
258
				"com.microsoft.sqlserver.jdbc.SQLServerDriver", "com.mysql.cj.jdbc.Driver" };
259

    
260
		// DB type, URL.
261
		Label rdbmsLabel = new Label("Typ DB");
262
		Label urlLabel = new Label("URL");
263
		ComboBox<String> rdbms = new ComboBox<String>(FXCollections.observableArrayList(dbTypeTexts));
264
		TextField url = new TextField(propUrl == null ? "" : propUrl);
265

    
266
		if (propType == null) {
267
			rdbms.getSelectionModel().selectFirst();
268
			url.setPromptText(promptTexts[0]);
269
		} else {
270
			rdbms.getSelectionModel().select(propType);
271
			url.setPromptText(promptTexts[rdbms.getItems().indexOf(propType)]);
272
		}
273
		rdbms.setOnAction(event -> {
274
			url.setPromptText(promptTexts[rdbms.getSelectionModel().getSelectedIndex()]);
275
		});
276

    
277
		// User and password.
278
		Label userLabel = new Label("Uživatel");
279
		Label passwordLabel = new Label("Heslo");
280
		TextField user = new TextField(propUser == null ? "" : propUser);
281
		PasswordField password = new PasswordField();
282

    
283
		// Layout for each pair - label and input component.
284
		VBox rdbmsLayout = new VBox();
285
		rdbmsLayout.getChildren().addAll(rdbmsLabel, rdbms);
286
		VBox urlLayout = new VBox();
287
		urlLayout.getChildren().addAll(urlLabel, url);
288
		VBox userLayout = new VBox();
289
		userLayout.getChildren().addAll(userLabel, user);
290
		VBox passwordLayout = new VBox();
291
		passwordLayout.getChildren().addAll(passwordLabel, password);
292

    
293
		// Styles settings.
294
		rdbmsLabel.setStyle("-fx-font-weight: bold;");
295
		urlLabel.setStyle("-fx-font-weight: bold;");
296
		userLabel.setStyle("-fx-font-weight: bold;");
297
		passwordLabel.setStyle("-fx-font-weight: bold;");
298

    
299
		url.setMinWidth(400);
300
		user.setMinWidth(100);
301
		user.setPrefWidth(200);
302
		user.setMaxWidth(300);
303
		password.setMinWidth(100);
304
		password.setPrefWidth(200);
305
		password.setMaxWidth(300);
306

    
307
		// Layout with elements for connecting to the database.
308
		HBox connLayout = new HBox();
309
		HBox.setHgrow(urlLayout, Priority.ALWAYS);
310
		connLayout.setSpacing(10);
311
		connLayout.getChildren().addAll(rdbmsLayout, urlLayout, userLayout, passwordLayout);
312

    
313
		// Elements for query.
314
		Label select = new Label("SELECT"), from = new Label("FROM"), where = new Label("WHERE"),
315
				queryEnd = new Label(";");
316
		TextField column = new TextField(), table = new TextField(), cond = new TextField();
317

    
318
		select.setStyle("-fx-font-weight: bold;");
319
		from.setStyle("-fx-font-weight: bold;");
320
		where.setStyle("-fx-font-weight: bold;");
321
		queryEnd.setStyle("-fx-font-weight: bold;");
322

    
323
		column.setPromptText("sloupec");
324
		table.setPromptText("tabulka");
325
		cond.setPromptText("podminka");
326

    
327
		HBox.setHgrow(column, Priority.ALWAYS);
328
		HBox.setHgrow(table, Priority.ALWAYS);
329
		HBox.setHgrow(cond, Priority.ALWAYS);
330

    
331
		// Layout for query.
332
		HBox queryLayout = new HBox();
333
		queryLayout.setAlignment(Pos.CENTER);
334
		queryLayout.setSpacing(5.0);
335
		queryLayout.getChildren().addAll(select, column, from, table, where, cond, queryEnd);
336

    
337
		// Button for the execution of the query.
338
		Button setQuery = new Button("Spustit");
339
		setQuery.setOnAction(event -> {
340
			String urlStr = url.getText().trim();
341
			String userStr = user.getText().trim();
342
			properties.setProperty(FileWorker.DB_TYPE, rdbms.getValue());
343
			properties.setProperty(FileWorker.DB_URL, urlStr);
344
			properties.setProperty(FileWorker.DB_USER, userStr);
345

    
346
			String driver = dbDriverClasses[rdbms.getItems().indexOf(rdbms.getValue())];
347
			converter.setInput(null, new DB_Messenger(driver, urlStr, userStr, password.getText().trim(),
348
					table.getText().trim(), cond.getText().trim(), column.getText().trim()));
349
		});
350

    
351
		HBox bIF = new HBox();
352
		bIF.setAlignment(Pos.CENTER_RIGHT);
353
		bIF.getChildren().add(setQuery);
354

    
355
		// Main layout in the tab.
356
		VBox forInput = new VBox();
357
		forInput.setPadding(new Insets(10, 10, 0, 10));
358
		forInput.setSpacing(5.0);
359
		forInput.getChildren().addAll(connLayout, queryLayout, bIF);
360

    
361
		return new Tab("SQL", forInput);
362
	}
363

    
364
	/**
365
	 * @return a tab for selecting an input file.
366
	 */
367
	private Tab createInputFileTab() {
368
		// Input file label and path.
369
		Label forInputFile = new Label("Soubor k deserializaci:");
370
		Label inputFile = new Label("    Ještě nebyl vybrán žádný soubor...");
371
		inputFile.setStyle("-fx-font-style: italic;");
372
		inputFile.setPrefWidth(500); // Value to cut the text.
373
		inputFile.setMaxWidth(Double.MAX_VALUE);
374

    
375
		// Button to choose the input file.
376
		Button setInputFile = new Button("Vstupní soubor");
377
		setInputFile.setOnAction(event -> {
378
			FileChooser fCh = new FileChooser();
379
			fCh.setInitialDirectory(new File("."));
380
			// The input can be a zip file or file without a specific extension -> file
381
			// chooser without extension filters...
382
			// fCh.getExtensionFilters().add(new FileChooser.ExtensionFilter("Binary Files",
383
			// "*.out"));
384

    
385
			// Set initial folder.
386
			String inputDir = properties.getProperty(FileWorker.INPUT_DIR);
387
			if (inputDir != null) {
388
				File initDir = new File(inputDir);
389
				if (initDir.exists()) {
390
					fCh.setInitialDirectory(initDir);
391
				}
392
			}
393

    
394
			// Get the selected file.
395
			File file = fCh.showOpenDialog(stage);
396
			if (file != null) {
397
				properties.setProperty(FileWorker.INPUT_DIR, file.getAbsoluteFile().getParent());
398
				setOutputLayoutDisabled(true);
399

    
400
				inputFile.setText(file.getAbsolutePath());
401
				inputFile.setStyle("-fx-font-weight: bold;");
402

    
403
				converter.setInput(file, null);
404
			}
405
		});
406

    
407
		HBox bIF = new HBox();
408
		bIF.setAlignment(Pos.CENTER_RIGHT);
409
		bIF.getChildren().add(setInputFile);
410

    
411
		// Main layout in the tab.
412
		VBox forInput = new VBox();
413
		forInput.setAlignment(Pos.CENTER_LEFT);
414
		forInput.setPadding(new Insets(10, 10, 0, 10));
415
		forInput.setSpacing(5.0);
416
		forInput.getChildren().addAll(forInputFile, inputFile, bIF);
417

    
418
		return new Tab("Soubor", forInput);
419
	}
420

    
421
	/**
422
	 * @return menu bar.
423
	 */
424
	private Node createMenu() {
425
		Menu menu = new Menu("Aplikace");
426

    
427
		// Full screen (and back).
428
		MenuItem fullScreen = createMenuItem(null, null,
429
				new KeyCodeCombination(KeyCode.F, KeyCombination.CONTROL_DOWN));
430
		fullScreen.setOnAction(event -> {
431
			stage.setFullScreen(!stage.isFullScreen());
432
		});
433
		this.fullScreen = (Label) fullScreen.getGraphic();
434
		changeFullScreenMenuItem();
435

    
436
		// Close app.
437
		MenuItem close = createMenuItem("Ukončit", FileWorker.getResource("/close.png"),
438
				new KeyCodeCombination(KeyCode.E, KeyCombination.CONTROL_DOWN));
439
		close.setOnAction(event -> {
440
			Platform.exit();
441
		});
442

    
443
		menu.getItems().addAll(fullScreen, new SeparatorMenuItem(), close);
444

    
445
		MenuBar bar = new MenuBar();
446
		bar.getMenus().add(menu);
447
		return bar;
448
	}
449

    
450
	/**
451
	 * Changes the text and icon of the menu item.
452
	 */
453
	private void changeFullScreenMenuItem() {
454
		fullScreen.setText(stage.isFullScreen() ? "Normální zobrazení" : "Plné zobrazení");
455
		fullScreen.setGraphic(new ImageView(
456
				stage.isFullScreen() ? FileWorker.getResource("/normal.png") : FileWorker.getResource("/full.png")));
457
	}
458

    
459
	/**
460
	 * @param name        menu item text.
461
	 * @param icon        menu item icon.
462
	 * @param keyCodeComb key code combination for the menu item.
463
	 * 
464
	 * @return menu item.
465
	 */
466
	private MenuItem createMenuItem(String name, String icon, KeyCodeCombination keyCodeComb) {
467
		// Menu items are not stylizable. Therefore, a label is used like a graphic
468
		// element of the menu item.
469
		Label label = new Label(name);
470
		label.setGraphicTextGap(10);
471
		label.getStyleClass().add("menu-graphics");
472
		label.setMinWidth(175);
473
		label.setMaxWidth(175);
474
		if (icon != null)
475
			label.setGraphic(new ImageView(new Image(icon)));
476

    
477
		MenuItem menuItem = new MenuItem();
478
		menuItem.setGraphic(label);
479
		menuItem.setAccelerator(keyCodeComb);
480
		return menuItem;
481
	}
482

    
483
	/**
484
	 * Used to set the disable property of the layout for the output file.
485
	 * 
486
	 * @param disable whether the layout should be inaccessible.
487
	 */
488
	private void setOutputLayoutDisabled(boolean disable) {
489
		outputLayout.setDisable(disable);
490
	}
491

    
492
	@Override
493
	public void loadingInputFileError() {
494
		Platform.runLater(() -> {
495
			Report.error("Načítání souboru", null, "Při načítání souboru došlo k chybě.");
496
		});
497
	}
498

    
499
	@Override
500
	public void completed(String json, String loaded) {
501
		Platform.runLater(() -> {
502
			String _json = json;
503

    
504
			boolean showData = json != null;
505

    
506
			if (!showData && loaded != null
507
					&& Report.confirm("Výsledek deserializace", null, "Při deserializaci došlo k chybě. "
508
							+ "Je ale možné, že nejde o serializovaná data. Chcete zobrazit, co bylo načteno?")) {
509

    
510
				_json = loaded.trim();
511
				showData = true;
512
			}
513

    
514
			if (showData) {
515
				editor.setContent(_json);
516
				setOutputLayoutDisabled(false);
517
			}
518
		});
519
	}
520

    
521
}
(6-6/6)