IGNITE-1155 Extract ignite-schema-import-ui module.
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/e8d71b55 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/e8d71b55 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/e8d71b55 Branch: refs/heads/ignite-1155 Commit: e8d71b5523f8898d7a67a07f1b311c6f4cb19186 Parents: d5925e6 Author: sevdokimov <sevdoki...@gridgain.com> Authored: Mon Jul 27 20:26:19 2015 +0300 Committer: sevdokimov <sevdoki...@gridgain.com> Committed: Mon Jul 27 20:26:19 2015 +0300 ---------------------------------------------------------------------- modules/schema-import-ui/pom.xml | 110 ++ .../main/java/media/data_connection_48x48.png | Bin 0 -> 4443 bytes .../src/main/java/media/error_48x48.png | Bin 0 -> 4349 bytes .../src/main/java/media/ignite_128x128.png | Bin 0 -> 4917 bytes .../src/main/java/media/ignite_16x16.png | Bin 0 -> 608 bytes .../src/main/java/media/ignite_24x24.png | Bin 0 -> 930 bytes .../src/main/java/media/ignite_32x32.png | Bin 0 -> 1203 bytes .../src/main/java/media/ignite_48x48.png | Bin 0 -> 1868 bytes .../src/main/java/media/ignite_64x64.png | Bin 0 -> 2453 bytes .../src/main/java/media/information_48x48.png | Bin 0 -> 4102 bytes .../src/main/java/media/question_48x48.png | Bin 0 -> 3857 bytes .../src/main/java/media/sign_warning_48x48.png | Bin 0 -> 2988 bytes .../src/main/java/media/style.css | 134 ++ .../src/main/java/media/text_tree_48x48.png | Bin 0 -> 2567 bytes .../ignite/schema/ui/ConfirmCallable.java | 103 + .../org/apache/ignite/schema/ui/Controls.java | 692 +++++++ .../org/apache/ignite/schema/ui/GridPaneEx.java | 177 ++ .../apache/ignite/schema/ui/JavaFxUtils.java | 122 ++ .../org/apache/ignite/schema/ui/MessageBox.java | 261 +++ .../apache/ignite/schema/ui/ModalDialog.java | 50 + .../ignite/schema/ui/SchemaImportApp.java | 1768 ++++++++++++++++++ .../ignite/schema/ui/TextColumnValidator.java | 32 + .../schema/test/AbstractSchemaImportTest.java | 132 ++ .../test/generator/CodeGeneratorTest.java | 70 + .../schema/test/generator/XmlGeneratorTest.java | 50 + .../apache/ignite/schema/test/model/Objects.txt | 502 +++++ .../ignite/schema/test/model/ObjectsKey.txt | 96 + .../ignite/schema/test/model/Primitives.txt | 506 +++++ .../ignite/schema/test/model/PrimitivesKey.txt | 96 + .../schema/test/model/ignite-type-metadata.xml | 362 ++++ .../test/parser/DbMetadataParserTest.java | 118 ++ .../testsuites/IgniteSchemaImportTestSuite.java | 41 + modules/schema-import/pom.xml | 34 - .../main/java/media/data_connection_48x48.png | Bin 4443 -> 0 bytes .../src/main/java/media/error_48x48.png | Bin 4349 -> 0 bytes .../src/main/java/media/ignite_128x128.png | Bin 4917 -> 0 bytes .../src/main/java/media/ignite_16x16.png | Bin 608 -> 0 bytes .../src/main/java/media/ignite_24x24.png | Bin 930 -> 0 bytes .../src/main/java/media/ignite_32x32.png | Bin 1203 -> 0 bytes .../src/main/java/media/ignite_48x48.png | Bin 1868 -> 0 bytes .../src/main/java/media/ignite_64x64.png | Bin 2453 -> 0 bytes .../src/main/java/media/information_48x48.png | Bin 4102 -> 0 bytes .../src/main/java/media/question_48x48.png | Bin 3857 -> 0 bytes .../src/main/java/media/sign_warning_48x48.png | Bin 2988 -> 0 bytes .../schema-import/src/main/java/media/style.css | 134 -- .../src/main/java/media/text_tree_48x48.png | Bin 2567 -> 0 bytes .../ignite/schema/generator/CodeGenerator.java | 17 +- .../schema/generator/ConfirmOverride.java | 42 + .../ignite/schema/generator/XmlGenerator.java | 13 +- .../ignite/schema/model/PojoDescriptor.java | 34 +- .../apache/ignite/schema/model/PojoField.java | 62 +- .../schema/parser/DatabaseMetadataParser.java | 5 +- .../ignite/schema/ui/ConfirmCallable.java | 81 - .../org/apache/ignite/schema/ui/Controls.java | 643 ------- .../org/apache/ignite/schema/ui/GridPaneEx.java | 177 -- .../org/apache/ignite/schema/ui/MessageBox.java | 261 --- .../apache/ignite/schema/ui/ModalDialog.java | 50 - .../ignite/schema/ui/SchemaImportApp.java | 1764 ----------------- .../ignite/schema/ui/TextColumnValidator.java | 32 - .../ignite/schema/utils/ChangeListener.java | 30 + .../apache/ignite/schema/utils/Property.java | 84 + .../schema/test/AbstractSchemaImportTest.java | 134 -- .../test/generator/CodeGeneratorTest.java | 70 - .../schema/test/generator/XmlGeneratorTest.java | 50 - .../apache/ignite/schema/test/model/Objects.txt | 502 ----- .../ignite/schema/test/model/ObjectsKey.txt | 96 - .../ignite/schema/test/model/Primitives.txt | 506 ----- .../ignite/schema/test/model/PrimitivesKey.txt | 96 - .../schema/test/model/ignite-type-metadata.xml | 362 ---- .../test/parser/DbMetadataParserTest.java | 118 -- .../testsuites/IgniteSchemaImportTestSuite.java | 41 - 71 files changed, 5639 insertions(+), 5221 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/pom.xml ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/pom.xml b/modules/schema-import-ui/pom.xml new file mode 100644 index 0000000..c56d050 --- /dev/null +++ b/modules/schema-import-ui/pom.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- + POM file. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.ignite</groupId> + <artifactId>ignite-parent</artifactId> + <version>1</version> + <relativePath>../../parent</relativePath> + </parent> + + <artifactId>ignite-schema-import-ui</artifactId> + <version>1.4.1-SNAPSHOT</version> + + <dependencies> + <dependency> + <groupId>org.apache.ignite</groupId> + <artifactId>ignite-core</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.apache.ignite</groupId> + <artifactId>ignite-schema-import</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>com.h2database</groupId> + <artifactId>h2</artifactId> + <version>1.3.175</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <resources> + <resource> + <directory>src/main/java</directory> + <excludes> + <exclude>**/*.java</exclude> + </excludes> + </resource> + </resources> + + <testResources> + <testResource> + <directory>src/test/java</directory> + <excludes> + <exclude>**/*.java</exclude> + </excludes> + </testResource> + </testResources> + + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <manifest> + <mainClass>org.apache.ignite.schema.ui.SchemaImportApp</mainClass> + </manifest> + </archive> + </configuration> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>schema-import</id> + <activation> + <file> + <exists>${java.home}/lib/jfxrt.jar</exists> + </file> + </activation> + <dependencies> + <dependency> + <groupId>javafx</groupId> + <artifactId>jfxrt</artifactId> + <version>${java.version}</version> + <scope>system</scope> + <systemPath>${java.home}/lib/jfxrt.jar</systemPath> + </dependency> + </dependencies> + </profile> + </profiles> +</project> http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/media/data_connection_48x48.png ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/media/data_connection_48x48.png b/modules/schema-import-ui/src/main/java/media/data_connection_48x48.png new file mode 100644 index 0000000..475f219 Binary files /dev/null and b/modules/schema-import-ui/src/main/java/media/data_connection_48x48.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/media/error_48x48.png ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/media/error_48x48.png b/modules/schema-import-ui/src/main/java/media/error_48x48.png new file mode 100644 index 0000000..e341b8a Binary files /dev/null and b/modules/schema-import-ui/src/main/java/media/error_48x48.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/media/ignite_128x128.png ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/media/ignite_128x128.png b/modules/schema-import-ui/src/main/java/media/ignite_128x128.png new file mode 100644 index 0000000..d99a83c Binary files /dev/null and b/modules/schema-import-ui/src/main/java/media/ignite_128x128.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/media/ignite_16x16.png ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/media/ignite_16x16.png b/modules/schema-import-ui/src/main/java/media/ignite_16x16.png new file mode 100644 index 0000000..3e07d33 Binary files /dev/null and b/modules/schema-import-ui/src/main/java/media/ignite_16x16.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/media/ignite_24x24.png ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/media/ignite_24x24.png b/modules/schema-import-ui/src/main/java/media/ignite_24x24.png new file mode 100644 index 0000000..8da5c97 Binary files /dev/null and b/modules/schema-import-ui/src/main/java/media/ignite_24x24.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/media/ignite_32x32.png ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/media/ignite_32x32.png b/modules/schema-import-ui/src/main/java/media/ignite_32x32.png new file mode 100644 index 0000000..c6c6819 Binary files /dev/null and b/modules/schema-import-ui/src/main/java/media/ignite_32x32.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/media/ignite_48x48.png ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/media/ignite_48x48.png b/modules/schema-import-ui/src/main/java/media/ignite_48x48.png new file mode 100644 index 0000000..5b684cc Binary files /dev/null and b/modules/schema-import-ui/src/main/java/media/ignite_48x48.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/media/ignite_64x64.png ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/media/ignite_64x64.png b/modules/schema-import-ui/src/main/java/media/ignite_64x64.png new file mode 100644 index 0000000..c1d348b Binary files /dev/null and b/modules/schema-import-ui/src/main/java/media/ignite_64x64.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/media/information_48x48.png ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/media/information_48x48.png b/modules/schema-import-ui/src/main/java/media/information_48x48.png new file mode 100644 index 0000000..8712a1b Binary files /dev/null and b/modules/schema-import-ui/src/main/java/media/information_48x48.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/media/question_48x48.png ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/media/question_48x48.png b/modules/schema-import-ui/src/main/java/media/question_48x48.png new file mode 100644 index 0000000..84683f9 Binary files /dev/null and b/modules/schema-import-ui/src/main/java/media/question_48x48.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/media/sign_warning_48x48.png ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/media/sign_warning_48x48.png b/modules/schema-import-ui/src/main/java/media/sign_warning_48x48.png new file mode 100644 index 0000000..5e7cccd Binary files /dev/null and b/modules/schema-import-ui/src/main/java/media/sign_warning_48x48.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/media/style.css ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/media/style.css b/modules/schema-import-ui/src/main/java/media/style.css new file mode 100644 index 0000000..6eee5f9 --- /dev/null +++ b/modules/schema-import-ui/src/main/java/media/style.css @@ -0,0 +1,134 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.root { + -fx-background-color: eeeeee; +} + +.button { + -fx-font-size: 14; + -fx-focus-color: gray; +} + +.label { + -fx-font-size: 14; +} + +.check-box { + -fx-font-size: 14; + -fx-focus-color: gray; +} + +.combo-box-base { + -fx-font-size: 14; + -fx-focus-color: gray; +} + +.combo-box-popup .list-view { + -fx-font-size : 14; +} + +.text-area { + -fx-font-size: 14; + -fx-background-color: transparent, transparent, transparent; +} + +.text-area .scroll-pane { + -fx-background-color: transparent; +} + +.text-area .scroll-pane .viewport{ + -fx-background-color: transparent; +} + +.text-area .scroll-pane .content{ + -fx-background-color: transparent; +} + +.text-area .scroll-bar:vertical:disabled { + -fx-opacity: 0; +} + +.text-field { + -fx-font-size: 14; + -fx-background-color: -fx-text-box-border, -fx-control-inner-background, -fx-control-inner-background; +} + +.text-field:focused { + -fx-background-color: -fx-text-box-border, -fx-control-inner-background, -fx-control-inner-background; +} + +.table-view { + -fx-focus-color: gray; + -fx-font-size: 14; +} + +.table-view .table-row-cell:selected { + -fx-background-color: -fx-table-cell-border-color, -fx-cell-hover-color; + -fx-background-insets: 0, 0 0 1 0; +} + +.table-view:focused .table-row-cell:selected { + -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar; +} + +.table-row-cell:empty { + -fx-background-color: white; +} + +.table-row-cell:empty .table-cell { + -fx-border-width: 0px; +} + +.tooltip { + -fx-font-size: 14; + -fx-background-radius: 0 0 0 0; +} + +.page-corner { + -fx-shape: " "; +} + +.progress-indicator { + -fx-progress-color: gray +} + +.split-pane { + -fx-background-color: -fx-box-border, eeeeee; +} + +.titled-pane { + -fx-font-size: 14; +} + +.titled-pane:focused { + -fx-text-fill: -fx-text-base-color; +} + +.titled-pane:focused > .title { + -fx-color: eeeeee; +} + +.titled-pane:focused > .title > .arrow-button .arrow { + -fx-background-color: black; +} + +#banner { + -fx-font-size: 20px; + -fx-font-weight: bold; + -fx-background-color: white +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/media/text_tree_48x48.png ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/media/text_tree_48x48.png b/modules/schema-import-ui/src/main/java/media/text_tree_48x48.png new file mode 100644 index 0000000..6ca9e65 Binary files /dev/null and b/modules/schema-import-ui/src/main/java/media/text_tree_48x48.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/ConfirmCallable.java ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/ConfirmCallable.java b/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/ConfirmCallable.java new file mode 100644 index 0000000..92340d0 --- /dev/null +++ b/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/ConfirmCallable.java @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.schema.ui; + +import javafx.application.*; +import javafx.stage.*; +import org.apache.ignite.schema.generator.*; + +import java.util.concurrent.*; + +import static org.apache.ignite.schema.ui.MessageBox.Result.*; + +/** + * Callable to ask user for confirmation from non EDT thread. + */ +public class ConfirmCallable implements Callable<MessageBox.Result>, ConfirmOverride { + /** Owner window. */ + private final Stage owner; + + /** Message template. */ + private final String template; + + /** Message to show in confirmation dialog. */ + private String msg; + + /** User choice. */ + private MessageBox.Result choice = NO; + + /** + * @param owner Owner window. + * @param template Message template. + */ + public ConfirmCallable(Stage owner, String template) { + this.owner = owner; + this.template = template; + } + + /** {@inheritDoc} */ + @Override public MessageBox.Result call() throws Exception { + choice = MessageBox.applyToAllChoiceDialog(owner, String.format(template, msg)); + + return choice; + } + + /** + * Execute confirmation in EDT thread. + * + * @return Confirm result. + */ + public ConfirmOverride.Result confirm(String msg) { + this.msg = msg; + + if (choice == YES_TO_ALL) + return Result.OVERRIDE; + + if (choice == NO_TO_ALL) + return Result.NO; + + FutureTask<MessageBox.Result> fut = new FutureTask<>(this); + + Platform.runLater(fut); + + MessageBox.Result res; + + try { + res = fut.get(); + } + catch (Exception ignored) { + return Result.NO; + } + + switch (res) { + case CANCEL: + return Result.CANCEL; + + case NO: + case NO_TO_ALL: + return Result.NO; + + case YES: + case YES_TO_ALL: + return Result.OVERRIDE; + + default: + throw new RuntimeException("Unknown result: " + res); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/Controls.java ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/Controls.java b/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/Controls.java new file mode 100644 index 0000000..075a84b --- /dev/null +++ b/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/Controls.java @@ -0,0 +1,692 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.schema.ui; + +import com.sun.javafx.scene.control.skin.*; +import javafx.application.*; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.*; +import javafx.collections.*; +import javafx.event.*; +import javafx.geometry.*; +import javafx.scene.*; +import javafx.scene.control.*; +import javafx.scene.control.cell.*; +import javafx.scene.image.*; +import javafx.scene.input.*; +import javafx.scene.layout.*; +import javafx.scene.text.*; +import javafx.util.*; +import javafx.util.converter.*; +import org.apache.ignite.schema.utils.*; + +import java.lang.reflect.*; + +/** + * Utility class to create controls. + */ +public class Controls { + /** */ + public static final Insets DFLT_PADDING = new Insets(10, 10, 10, 10); + + /** + * Create scene with predefined style. + * + * @param root The root node of the scene graph. + * @return New {@code Scene} instance. + */ + public static Scene scene(Parent root) { + Scene scene = new Scene(root); + + scene.getStylesheets().add("media/style.css"); + + return scene; + } + + /** + * Create grid pane with default padding. + * + * @param top Top padding + * @param right Right padding. + * @param bottom Bottom padding. + * @param left Left padding. + * @return New {@code GridPaneEx} instance. + */ + public static GridPaneEx paneEx(double top, double right, double bottom, double left) { + GridPaneEx paneEx = new GridPaneEx(); + + paneEx.setPadding(new Insets(top, right, bottom, left)); + + return paneEx; + } + + /** + * Create new {@code HBox} with default padding. + * + * @param spacing Amount of horizontal space between each child. + * @param dfltPadding If {@code true} than set default padding for pane. + * @return New {@code HBox} instance. + */ + public static HBox hBox(int spacing, boolean dfltPadding) { + HBox hb = new HBox(spacing); + + if (dfltPadding) + hb.setPadding(DFLT_PADDING); + + return hb; + } + + /** + * Create new {@code HBox} with default padding and add controls. + * + * @param spacing Amount of horizontal space between each child. + * @param dfltPadding If {@code true} than set default padding for pane. + * @param controls Controls to add. + * @return New {@code HBox} instance. + */ + public static HBox hBox(int spacing, boolean dfltPadding, Node... controls) { + HBox hb = hBox(spacing, dfltPadding); + + hb.getChildren().addAll(controls); + + return hb; + } + + /** + * Create new {@code VBox} with default padding. + * + * @param spacing Amount of horizontal space between each child. + * @return New {@code VBox} instance. + */ + public static VBox vBox(int spacing) { + VBox vb = new VBox(spacing); + + vb.setPadding(DFLT_PADDING); + + return vb; + } + + /** + * Create new {@code VBox} with default padding and add controls. + * + * @param spacing Amount of horizontal space between each child. + * @param controls Controls to add. + * @return New {@code VBox} instance. + */ + public static VBox vBox(int spacing, Node... controls) { + VBox vb = vBox(spacing); + + vb.getChildren().addAll(controls); + + return vb; + } + + /** + * Create stack pane. + * + * @param controls Controls to add. + * @return New {@code StackPane} instance. + */ + public static StackPane stackPane(Node... controls) { + StackPane sp = new StackPane(); + + sp.getChildren().addAll(controls); + + return sp; + } + + /** + * Create border pane. + * + * @param top Optional top control. + * @param center Optional center control. + * @param bottom Optional bottom control. + * @param left Optional left control. + * @param right Optional right control. + * @return New {@code BorderPane} instance. + */ + public static BorderPane borderPane(Node top, Node center, Node bottom, Node left, Node right) { + BorderPane bp = new BorderPane(); + + bp.setTop(top); + bp.setCenter(center); + bp.setBottom(bottom); + bp.setLeft(left); + bp.setRight(right); + + return bp; + } + + /** + * Sets control tooltip if needed. + * + * @param ctrl Target control. + * @param tip Tooltip text. + * @return Control itself for method chaining. + */ + public static <T extends Control> T tooltip(T ctrl, String tip) { + if (!tip.isEmpty()) + ctrl.setTooltip(new Tooltip(tip)); + + return ctrl; + } + + /** + * Create label. + * + * @param text Label text. + * @return New {@code Label} instance. + */ + public static Label label(String text) { + return new Label(text); + } + + /** + * Create button with text only. + * + * @param text Button text. + * @param tip Tooltip text. + * @param onAct Button action. + * @return New {@code Button} instance. + */ + public static Button button(String text, String tip, EventHandler<ActionEvent> onAct) { + Button btn = new Button(text); + + btn.setOnAction(onAct); + + tooltip(btn, tip); + + return btn; + } + + /** + * Create button with icon only. + * + * @param icon Button icon. + * @param tip Tooltip text. + * @param onAct Button action. + * @return New {@code Button} instance. + */ + public static Button button(ImageView icon, String tip, EventHandler<ActionEvent> onAct) { + Button btn = new Button(); + + btn.setGraphic(icon); + btn.setOnAction(onAct); + + tooltip(btn, tip); + + return btn; + } + + /** + * Create pane with buttons. + * + * @param alignment Alignment of buttons. + * @param dfltPadding If {@code true} than set default padding for pane. + * @param btns Buttons that will be added to pane. + * @return New {@code HBox} instance with buttons. + */ + public static Pane buttonsPane(Pos alignment, boolean dfltPadding, Button... btns) { + HBox hb = hBox(10, dfltPadding, btns); + + hb.setAlignment(alignment); + + return hb; + } + + /** + * Create checkbox. + * + * @param text Checkbox text. + * @param tip Tooltip tex. + * @param sel Checkbox selected state. + * @return New {@code Checkbox} instance. + */ + public static CheckBox checkBox(String text, String tip, boolean sel) { + CheckBox ch = new CheckBox(text); + + ch.setSelected(sel); + + tooltip(ch, tip); + + return ch; + } + + /** + * Create text field. + * + * @param tip Tooltip text. + * @return New {@code TextField} instance. + */ + public static TextField textField(String tip) { + TextField tf = new TextField(); + + tooltip(tf, tip); + + return tf; + } + + /** + * Create static text. + * + * @param text Text to show. + * @param wrap Text wrapping width. + * @return New {@code Text} instance. + */ + public static Text text(String text, int wrap) { + Text t = new Text(text); + + t.setFont(new Font(14)); + + if (wrap > 0) + t.setWrappingWidth(wrap); + + return t; + } + + /** + * Create password field. + * + * @param tip Tooltip text. + * @return New {@code PasswordField} instance. + */ + public static PasswordField passwordField(String tip) { + PasswordField pf = new PasswordField(); + + tooltip(pf, tip); + + return pf; + } + + /** + * Create combo box. + * + * @param tip Tooltip text. + * @param items Combo box items. + * @return New {@code ComboBox} instance. + */ + public static <T> ComboBox<T> comboBox(String tip, T... items) { + ComboBox<T> cb = new ComboBox<>(FXCollections.observableArrayList(items)); + + cb.setMaxWidth(Double.MAX_VALUE); + cb.getSelectionModel().select(0); + + tooltip(cb, tip); + + return cb; + } + + /** + * Create split pane for provided nodes. + * + * @param node1 First node. + * @param node2 Second node. + * @param pos Initial divider position. + * @return New {@code SplitPane} instance. + */ + public static SplitPane splitPane(Node node1, Node node2, double pos) { + SplitPane sp = new SplitPane(); + + sp.setOrientation(Orientation.VERTICAL); + sp.getItems().addAll(node1, node2); + sp.setDividerPosition(0, pos); + + return sp; + } + + /** + * Create titled pane. + * + * @param title Title. + * @param node Node. + * @return New {@code TitledPane} instance. + */ + public static TitledPane titledPane(String title, Node node) { + TitledPane tp = new TitledPane(title, node); + + tp.setExpanded(false); + + return tp; + } + + /** + * Create table column. + * + * @param colName Column name to display. + * @param propName Property name column is bound to. + * @param tip Column tooltip text. + * @param minWidth The minimum width column is permitted to be resized to. + * @param maxWidth The maximum width column is permitted to be resized to. + * @param editable {@code true} if column is editable. + * @return New {@code TableColumn} instance. + */ + private static <S, T> TableColumn<S, T> tableColumn(String colName, String propName, String tip, + int minWidth, int maxWidth, boolean editable) { + TableColumn<S, T> col = new TableColumn<>(); + + col.setGraphic(tooltip(new Label(colName), tip)); + + col.setSortable(false); + + if (minWidth > 0) + col.setMinWidth(minWidth); + + if (maxWidth > 0) + col.setMaxWidth(maxWidth); + + col.setCellValueFactory(new MyPropertyValueFactory<S, T>(propName)); + + col.setEditable(editable); + + return col; + } + + /** */ + private static class MyPropertyValueFactory<S, T> implements Callback<TableColumn.CellDataFeatures<S, T>, + ObservableValue<T>> { + /** */ + private final String name; + + /** + * @param name Name. + */ + public MyPropertyValueFactory(String name) { + this.name = name; + } + + /** {@inheritDoc} */ + @Override public ObservableValue<T> call(TableColumn.CellDataFeatures<S, T> features) { + Object val = features.getValue(); + + if (val == null) + return null; + + Property prop; + + try { + Method getter = val.getClass().getMethod(name + "Property"); + + getter.setAccessible(true); + + prop = (Property)getter.invoke(val); + + Type type = ((ParameterizedType)getter.getGenericReturnType()).getActualTypeArguments()[0]; + + if (type == Boolean.class) + return (ObservableValue<T>)JavaFxUtils.booleanProperty(prop); + + if (type == String.class) + return (ObservableValue<T>)JavaFxUtils.stringProperty(prop); + + throw new RuntimeException("Unknown field type: " + type); + } + catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + } + + /** + * Create table column. + * + * @param colName Column name to display. + * @param propName Property name column is bound to. + * @param tip Column tooltip text. + * @return New {@code TableColumn} instance. + */ + public static <S, T> TableColumn<S, T> tableColumn(String colName, String propName, String tip) { + return tableColumn(colName, propName, tip, 100, 0, false); + } + + /** + * Create table column. + * + * @param colName Column name to display. + * @param propName Property name column is bound to. + * @param tip Column tooltip text. + * @param cellFactory Custom cell factory. + * @return New {@code TableColumn} instance. + */ + public static <S, T> TableColumn<S, T> customColumn(String colName, String propName, String tip, + Callback<TableColumn<S, T>, TableCell<S, T>> cellFactory) { + TableColumn<S, T> col = tableColumn(colName, propName, tip, 100, 0, true); + + col.setCellFactory(cellFactory); + + return col; + } + + /** + * Create editable boolean table column. + * + * @param colName Column name to display. + * @param propName Property name column is bound to. + * @param tip Column tooltip text. + * @return New {@code TableColumn} instance. + */ + public static <S> TableColumn<S, Boolean> booleanColumn(String colName, String propName, String tip) { + TableColumn<S, Boolean> col = tableColumn(colName, propName, tip, 50, 50, true); + + col.setCellFactory(CheckBoxTableCellEx.<S>cellFactory()); + + return col; + + } + + /** + * Create editable text table column. + * + * @param colName Column name to display. + * @param propName Property name column is bound to. + * @param tip Column tooltip text. + * @return New {@code TableColumn} instance. + */ + public static <S> TableColumn<S, String> textColumn(String colName, String propName, String tip, + TextColumnValidator<S> validator) { + TableColumn<S, String> col = tableColumn(colName, propName, tip, 100, 0, true); + + col.setCellFactory(TextFieldTableCellEx.cellFactory(validator)); + + return col; + } + + /** + * Create table view. + * + * @param placeholder Text to show if table model is empty. + * @param cols Columns to add. + * @return New {@code TableView} instance. + */ + public static <S> TableView<S> tableView(String placeholder, TableColumn<S, ?>... cols) { + TableView<S> tbl = new TableView<>(); + + tbl.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); + tbl.setEditable(true); + tbl.setMinHeight(70); + tbl.setPlaceholder(text(placeholder, 0)); + + tbl.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); + + tbl.getColumns().addAll(cols); + + return tbl; + } + + /** + * Create progress indicator. + * + * @param sz Indicator diameter. + * @return New {@code ProgressIndicator} instance. + */ + public static ProgressIndicator progressIndicator(int sz) { + ProgressIndicator pi = new ProgressIndicator(); + + pi.setMaxWidth(sz); + pi.setMaxHeight(sz); + + return pi; + } + + /** + * Create image view. + * + * @param imgFileName Image filename. + * @return New {@code ImageView} instance. + */ + public static ImageView imageView(String imgFileName, int sz) { + return new ImageView(image(imgFileName, sz)); + } + + /** + * Gets image by its filename. + * + * @param imgFileName Image filename. + * @return Loaded image. + */ + public static Image image(String imgFileName, int sz) { + return new Image(Controls.class.getClassLoader() + .getResourceAsStream(String.format("media/%1$s_%2$dx%2$d.png", imgFileName, sz))); + } + + /** + * Customized checkbox. + */ + private static class CheckBoxTableCellEx<S> extends CheckBoxTableCell<S, Boolean> { + /** Creates a ComboBox cell factory for use in TableColumn controls. */ + public static <S> Callback<TableColumn<S, Boolean>, TableCell<S, Boolean>> cellFactory() { + return new Callback<TableColumn<S, Boolean>, TableCell<S, Boolean>>() { + @Override public TableCell<S, Boolean> call(TableColumn<S, Boolean> col) { + return new CheckBoxTableCellEx<>(); + } + }; + } + + /** + * Default constructor. + */ + private CheckBoxTableCellEx() { + setAlignment(Pos.CENTER); + } + } + + /** + * Special table text field cell that commit its content on focus lost. + */ + private static class TextFieldTableCellEx<S> extends TextFieldTableCell<S, String> { + /** */ + private final TextColumnValidator<S> validator; + /** */ + private String curTxt = ""; + + /** Row value. */ + private S rowVal; + + /** Create cell factory. */ + public static <S> Callback<TableColumn<S, String>, TableCell<S, String>> + cellFactory(final TextColumnValidator<S> validator) { + return new Callback<TableColumn<S, String>, TableCell<S, String>>() { + @Override public TableCell<S, String> call(TableColumn<S, String> col) { + return new TextFieldTableCellEx<>(validator); + } + }; + } + + /** + * Text field cell constructor. + * + * @param validator Input text validator. + */ + private TextFieldTableCellEx(TextColumnValidator<S> validator) { + super(new DefaultStringConverter()); + + this.validator = validator; + } + + /** {@inheritDoc} */ + @Override public void startEdit() { + String item = getItem(); + + if (item == null || item.isEmpty()) + return; + + super.startEdit(); + + rowVal = getTableView().getSelectionModel().getSelectedItem(); + + Node g = getGraphic(); + + if (g != null) { + final TextField tf = (TextField)g; + + curTxt = tf.getText(); + + tf.textProperty().addListener(new ChangeListener<String>() { + @Override public void changed(ObservableValue<? extends String> val, String oldVal, String newVal) { + curTxt = newVal; + } + }); + + tf.setOnKeyPressed(new EventHandler<KeyEvent>() { + @Override public void handle(KeyEvent evt) { + if (KeyCode.ENTER == evt.getCode() || KeyCode.ESCAPE == evt.getCode()) + cancelEdit(); + } + }); + + tf.setOnKeyReleased(new EventHandler<KeyEvent>() { + @Override public void handle(KeyEvent evt) { + // No-op to overwrite JavaFX implementation. + } + }); + + // Special hack for editable TextFieldTableCell. + // Cancel edit when focus lost from text field, but do not cancel if focus lost to VirtualFlow. + tf.focusedProperty().addListener(new ChangeListener<Boolean>() { + @Override public void changed(ObservableValue<? extends Boolean> val, Boolean oldVal, Boolean newVal) { + Node fo = getScene().getFocusOwner(); + + if (!newVal) { + if (fo instanceof VirtualFlow) { + if (fo.getParent().getParent() != getTableView()) + cancelEdit(); + } + else + cancelEdit(); + } + } + }); + + Platform.runLater(new Runnable() { + @Override public void run() { + tf.requestFocus(); + } + }); + } + } + + /** {@inheritDoc} */ + @Override public void cancelEdit() { + boolean editing = isEditing(); + + super.cancelEdit(); + + if (editing && validator.valid(rowVal, curTxt)) + updateItem(curTxt, false); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/GridPaneEx.java ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/GridPaneEx.java b/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/GridPaneEx.java new file mode 100644 index 0000000..be1aae9 --- /dev/null +++ b/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/GridPaneEx.java @@ -0,0 +1,177 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.schema.ui; + +import javafx.geometry.*; +import javafx.scene.*; +import javafx.scene.control.*; +import javafx.scene.layout.*; + +/** + * Utility extension of {@code GridPane}. + */ +public class GridPaneEx extends GridPane { + /** Current column. */ + private int col; + + /** Current row. */ + private int row; + + /** + * Create pane. + */ + public GridPaneEx() { + setAlignment(Pos.TOP_LEFT); + setHgap(5); + setVgap(10); + } + + /** + * Add default column. + */ + public void addColumn() { + getColumnConstraints().add(new ColumnConstraints()); + } + + /** + * Add column with constraints and horizontal grow priority for the column. + * + * @param min Column minimum size. + * @param pref Column preferred size. + * @param max Column max size. + * @param hgrow Column horizontal grow priority. + */ + public void addColumn(double min, double pref, double max, Priority hgrow) { + ColumnConstraints cc = new ColumnConstraints(min, pref, max); + + cc.setHgrow(hgrow); + + getColumnConstraints().add(cc); + } + + /** + * Add default row. + */ + public void addRow() { + getRowConstraints().add(new RowConstraints()); + } + + /** + * Add default rows. + * + * @param n Number of rows to add. + */ + public void addRows(int n) { + for (int i = 0; i < n; i++) + addRow(); + } + + /** + * Add row with constraints and vertical grow priority for the row. + * + * @param min Row minimum size. + * @param pref Row preferred size. + * @param max Row max size. + * @param vgrow Row vertical grow priority. + */ + public void addRow(double min, double pref, double max, Priority vgrow) { + RowConstraints rc = new RowConstraints(min, pref, max); + + rc.setVgrow(vgrow); + + getRowConstraints().add(rc); + } + + /** + * Wrap to next row. + */ + public void wrap() { + col = 0; + + row++; + } + + /** + * Skip columns. + * + * @param span How many columns should be skipped. + */ + public void skip(int span) { + add(new Label(""), span); + } + + /** + * Move to next column. + */ + private void nextCol(int span) { + col += span; + + if (col >= getColumnConstraints().size()) + wrap(); + } + + /** + * Add control to grid pane. + * + * @param ctrl Control to add. + * @param span How many columns control should take. + * @return Added control. + */ + public <T extends Node> T add(T ctrl, int span) { + add(ctrl, col, row, span, 1); + + nextCol(span); + + return ctrl; + } + + /** + * Add control to grid pane. + * + * @param ctrl Control to add. + * @return Added control. + */ + public <T extends Node> T add(T ctrl) { + return add(ctrl, 1); + } + + /** + * Add control with label. + * + * @param text Label text. + * @param ctrl Control to add. + * @param span How many columns control should take. + * @return Added control. + */ + public <T extends Node> T addLabeled(String text, T ctrl, int span) { + add(new Label(text)); + + return add(ctrl, span); + } + + /** + * Add control with label. + * + * @param text Label text. + * @param ctrl Control to add. + * @return Added control. + */ + public <T extends Node> T addLabeled(String text, T ctrl) { + return addLabeled(text, ctrl, 1); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/JavaFxUtils.java ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/JavaFxUtils.java b/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/JavaFxUtils.java new file mode 100644 index 0000000..579b649 --- /dev/null +++ b/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/JavaFxUtils.java @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.schema.ui; + +import javafx.beans.property.*; +import javafx.beans.value.*; + +/** + * + */ +public class JavaFxUtils { + /** + * @param prop Property. + */ + public static BooleanProperty booleanProperty(org.apache.ignite.schema.utils.Property<Boolean> prop) { + BooleanProperty res = (BooleanProperty)prop.fxProperty(); + + if (res == null) { + res = new SimpleBooleanProperty(prop.get()); + + new Bridge<>(res, prop); + + prop.fxProperty(res); + } + + return res; + } + + /** + * @param prop Property. + */ + public static StringProperty stringProperty(org.apache.ignite.schema.utils.Property<String> prop) { + StringProperty res = (StringProperty)prop.fxProperty(); + + if (res == null) { + res = new SimpleStringProperty(prop.get()); + + new Bridge<>(res, prop); + + prop.fxProperty(res); + } + + return res; + } + + /** + * + * @param <T> + */ + private static class Bridge<T> implements org.apache.ignite.schema.utils.ChangeListener<T>, ChangeListener<T> { + /** */ + private final Property<T> fxProp; + + /** */ + private final org.apache.ignite.schema.utils.Property<T> igniteProp; + + /** + * @param fxProp Fx property. + * @param igniteProp Ignite property. + */ + public Bridge(Property<T> fxProp, org.apache.ignite.schema.utils.Property<T> igniteProp) { + this.fxProp = fxProp; + this.igniteProp = igniteProp; + + fxProp.addListener(this); + igniteProp.addListener(this); + } + + /** */ + private boolean notificationInProgress; + + /** {@inheritDoc} */ + @Override public void changed(org.apache.ignite.schema.utils.Property<? extends T> prop, T oldVal, T newVal) { + if (notificationInProgress) + return; + + notificationInProgress = true; + + try { + assert prop == igniteProp; + + fxProp.setValue(newVal); + } + finally { + notificationInProgress = false; + } + } + + /** {@inheritDoc} */ + @Override public void changed(ObservableValue<? extends T> prop, T oldVal, T newVal) { + if (notificationInProgress) + return; + + notificationInProgress = true; + + try { + assert prop == fxProp; + + igniteProp.set(newVal); + } + finally { + notificationInProgress = false; + } + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/MessageBox.java ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/MessageBox.java b/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/MessageBox.java new file mode 100644 index 0000000..7daf69f --- /dev/null +++ b/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/MessageBox.java @@ -0,0 +1,261 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.schema.ui; + +import javafx.beans.value.*; +import javafx.event.*; +import javafx.geometry.*; +import javafx.scene.control.*; +import javafx.scene.layout.*; +import javafx.stage.*; + +import java.util.logging.*; + +import static org.apache.ignite.schema.ui.Controls.*; + +/** + * Message box functionality. + */ +public class MessageBox extends ModalDialog { + /** Logger. */ + private static final Logger log = Logger.getLogger(MessageBox.class.getName()); + + /** Message box type. */ + private enum MessageType { + /** Information. */ + INFO, + /** Warning. */ + WARN, + /** Error. */ + ERROR, + /** Confirm. */ + CONFIRM, + /** Confirm with cancel option. */ + CANCELLABLE_CONFIRM + } + + /** Message box type. */ + public enum Result { + /** Return value if YES is chosen. */ + YES, + /** Return value if YES_TO_ALL is chosen. */ + YES_TO_ALL, + /** Return value if NO is chosen. */ + NO, + /** Return value if NO_TO_ALL is chosen. */ + NO_TO_ALL, + /** Return value if CANCEL is chosen. */ + CANCEL + } + + /** Dialog result. */ + private Result res = Result.CANCEL; + + /** + * Create message box. + * + * @param owner Owner window. + * @param type Message box type. + * @param msg Message to show. + * @param applyToAll {@code true} if "Apply to all" check box should be displayed. + */ + private MessageBox(Stage owner, MessageType type, String msg, final boolean applyToAll) { + super(owner, 480, 180); + + String title; + String iconFile; + + switch (type) { + case WARN: + title = "Warning"; + iconFile = "sign_warning"; + break; + + case ERROR: + title = "Error"; + iconFile = "error"; + break; + + case CONFIRM: + case CANCELLABLE_CONFIRM: + title = "Confirmation"; + iconFile = "question"; + break; + + default: + title = "Information"; + iconFile = "information"; + break; + } + + setTitle(title); + initStyle(StageStyle.UTILITY); + initModality(Modality.APPLICATION_MODAL); + initOwner(owner); + setResizable(false); + + GridPaneEx contentPnl = paneEx(10, 10, 0, 10); + + contentPnl.addColumn(); + contentPnl.addColumn(100, 100, Double.MAX_VALUE, Priority.ALWAYS); + + contentPnl.add(hBox(0, true, imageView(iconFile, 48))); + + final TextArea ta = new TextArea(msg); + ta.setEditable(false); + ta.setWrapText(true); + ta.setFocusTraversable(false); + + contentPnl.add(ta); + + // Workaround for vertical scrollbar. + if (msg.length() < 100 && msg.split("\r\n|\r|\n").length < 4) + showingProperty().addListener(new ChangeListener<Boolean>() { + @Override public void changed(ObservableValue<? extends Boolean> val, Boolean oldVal, Boolean newVal) { + if (newVal) { + ScrollBar scrollBar = (ScrollBar)ta.lookup(".scroll-bar:vertical"); + + if (scrollBar != null) + scrollBar.setDisable(true); + } + } + }); + + final CheckBox applyToAllCh = checkBox("Apply to all", "", false); + + if (applyToAll) { + contentPnl.skip(1); + contentPnl.add(applyToAllCh); + } + + HBox btns = hBox(10, true); + btns.setAlignment(Pos.CENTER); + + if (MessageType.CONFIRM == type || MessageType.CANCELLABLE_CONFIRM == type) { + res = Result.NO; + + btns.getChildren().addAll( + button("Yes", "Approve the request", new EventHandler<ActionEvent>() { + @Override public void handle(ActionEvent e) { + res = applyToAll && applyToAllCh.isSelected() ? Result.YES_TO_ALL : Result.YES; + + close(); + } + }), + button("No", "Reject the request", new EventHandler<ActionEvent>() { + @Override public void handle(ActionEvent e) { + res = applyToAll && applyToAllCh.isSelected() ? Result.NO_TO_ALL : Result.NO; + + close(); + } + })); + + if (MessageType.CANCELLABLE_CONFIRM == type) + btns.getChildren().addAll( + button("Cancel", "Cancel the request", new EventHandler<ActionEvent>() { + @Override public void handle(ActionEvent e) { + res = Result.CANCEL; + + close(); + } + })); + } + else + btns.getChildren().add(button("OK", "Close dialog", new EventHandler<ActionEvent>() { + @Override public void handle(ActionEvent e) { + close(); + } + })); + + setScene(scene(borderPane(null, contentPnl, btns, null, null))); + } + + /** + * Show message in modal dialog. + * + * @param owner Owner window. + * @param type Message box type. + * @param msg Message to show. + * @param applyToAll {@code true} if "Apply to all" check box should be displayed. + * @return Option selected by the user. + */ + private static Result showDialog(Stage owner, MessageType type, String msg, boolean applyToAll) { + MessageBox dlg = new MessageBox(owner, type, msg, applyToAll); + + dlg.showModal(); + + return dlg.res; + } + + /** + * Show confirmation dialog. + * + * @param owner Owner window. + * @param msg Message to show. + * @return {@code true} If user confirm. + */ + public static boolean confirmDialog(Stage owner, String msg) { + return showDialog(owner, MessageType.CONFIRM, msg, false) == Result.YES; + } + + /** + * Show confirmation dialog. + * + * @param owner Owner window. + * @param msg Message to show. + * @return User confirmation result. + */ + public static Result applyToAllChoiceDialog(Stage owner, String msg) { + return showDialog(owner, MessageType.CANCELLABLE_CONFIRM, msg, true); + } + + /** + * Show information dialog. + * + * @param owner Owner window. + * @param msg Message to show. + */ + public static void informationDialog(Stage owner, String msg) { + showDialog(owner, MessageType.INFO, msg, false); + } + + /** + * Show warning dialog. + * + * @param owner Owner window. + * @param msg Message to show. + */ + public static void warningDialog(Stage owner, String msg) { + showDialog(owner, MessageType.WARN, msg, false); + } + + /** + * Show error dialog. + * + * @param owner Owner window. + * @param msg Error message to show. + * @param e Optional exception to show. + */ + public static void errorDialog(Stage owner, String msg, Throwable e) { + log.log(Level.SEVERE, msg, e); + + String exMsg = e != null ? (e.getMessage() != null ? e.getMessage() : e.getClass().getName()) : null; + + showDialog(owner, MessageType.ERROR, exMsg != null ? msg + "\n" + exMsg : msg, false); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e8d71b55/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/ModalDialog.java ---------------------------------------------------------------------- diff --git a/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/ModalDialog.java b/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/ModalDialog.java new file mode 100644 index 0000000..6d0acb7 --- /dev/null +++ b/modules/schema-import-ui/src/main/java/org/apache/ignite/schema/ui/ModalDialog.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.schema.ui; + +import javafx.stage.*; + +/** + * Abstract base modal dialog. + */ +public abstract class ModalDialog extends Stage { + /** Owner window. */ + protected final Stage owner; + + /** + * @param owner Owner window. + * @param width Window width. + * @param height Window height. + */ + protected ModalDialog(Stage owner, int width, int height) { + this.owner = owner; + + this.setWidth(width); + this.setHeight(height); + } + + /** + * Show modal dialog. + */ + protected void showModal() { + setX(owner.getX() + owner.getWidth() / 2 - getWidth() / 2); + setY(owner.getY() + owner.getHeight() / 2 - getHeight() / 2); + + showAndWait(); + } +}