Java tutorial
/* * Licensed 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 net.rptools.gui; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.InetAddress; import java.net.URL; import java.net.URLConnection; import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.fxml.FXMLLoader; import javafx.scene.Node; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.control.TextInputControl; import javafx.scene.input.KeyEvent; import javafx.scene.layout.Pane; import javafx.scene.layout.Region; import javafx.stage.Stage; import net.rptools.gui.listeners.FXMLListener; import net.rptools.gui.listeners.ResizeListener; import org.apache.commons.lang3.StringUtils; import org.rptools.framework.Layer; import org.rptools.framework.ThreadPolicy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Class that does the main GUI construction off of the application thread. The * final staging must be done on the application thread, hence the last appendix * with runLater. */ public class GuiBuilder { // Utility private static final Logger LOGGER = LoggerFactory.getLogger(GuiBuilder.class); // Pattern to match (in pattern asset lists) private static final String PATTERN = "pattern"; // FXML Region reference private Region rootRegion; // FXML Stage reference private Stage rootStage; // Component back-reference private GuiComponentImpl component; // FXML controller private FXMLListener fxmlListener; // State private ScreenLayout layout = new ScreenLayout(); /** * Construct the scene in this contructor and later publish on the * application thread. * @param parent component back-reference */ public GuiBuilder(final GuiComponentImpl parent) { component = parent; // Basic initialization rootStage = new Stage(); final FXMLLoader fxmlLoader = new GuiFXMLLoader("main.fxml"); try { rootRegion = (Region) fxmlLoader.load(); } catch (final IOException e) { LOGGER.error("GUI can't be constructed", e); } fxmlListener = fxmlLoader.getController(); } /** Continued initialization. */ @ThreadPolicy(ThreadPolicy.ThreadId.JFX) public void init() { fxmlListener.setComponent(component); fillIn(); // Add input listeners to GUI (filters are first in the chain) rootRegion.setFocusTraversable(true); rootRegion.addEventHandler(KeyEvent.ANY, component.getKeyInputListener()); // Listener for window resize final ChangeListener<Object> resizeListener = new ResizeListener(component); rootRegion.widthProperty().addListener(resizeListener); rootRegion.heightProperty().addListener(resizeListener); component.getFramework().redraw(null); layout.parse(component.getFramework().getState("screen")); layout.toStage(rootStage); } /** Fill in all fields we know of. */ @ThreadPolicy(ThreadPolicy.ThreadId.JFX) private void fillIn() { final String server = component.getFramework().getState("server"); if (server != null) { final String[] serverParams = server.split(":"); ((TextInputControl) component.lookup("#networkServer")).setText(serverParams[0]); ((TextInputControl) component.lookup("#networkPort")).setText(serverParams[1]); } final String login = component.getFramework().getState("login"); if (login != null) { final String[] loginParams = login.split("/"); ((TextInputControl) component.lookup("#networkUser")).setText(loginParams[0]); } try { ((TextInputControl) component.lookup("#networkLocalIP")) .setText(InetAddress.getLocalHost().getHostAddress().toString()); } catch (final UnknownHostException e) { LOGGER.error("InetAddress.getLocalHost", e); } component.getFramework().submit(new Runnable() { @Override public void run() { try { final URL url = new URL("http://icanhazip.com/"); final URLConnection con = (URLConnection) url.openConnection(); try (final BufferedReader in = new BufferedReader( new InputStreamReader(con.getInputStream(), StandardCharsets.US_ASCII))) { final String response = in.readLine(); ((TextInputControl) component.lookup("#networkRemoteIP")).setText(response); } } catch (final IOException e) { LOGGER.error("No result from http://icanhazip.com/", e); } } }); AssetConnector.connect("#penTexture", PATTERN, component); AssetConnector.connect("#fillTexture", PATTERN, component); } /** Final GUI show. */ @ThreadPolicy(ThreadPolicy.ThreadId.MAIN) public void showGUI() { Platform.runLater(new Runnable() { @Override public void run() { rootStage.setTitle("Maptool"); final Scene rootScene = new Scene(rootRegion); rootScene.getStylesheets().add(StylesheetMonitor.STYLESHEET); rootStage.setScene(rootScene); component.setRootScene(rootScene); rootStage.show(); component.stopSplasher(); } }); } /** * Create all the layer panes/nodes and signal contruction end to framework. * @param layer layers to supply nodes to */ @ThreadPolicy(ThreadPolicy.ThreadId.MAIN) public void createLayerPanes(final Layer layer) { Platform.runLater(new Runnable() { @Override public void run() { final String selector = "#" + StringUtils.uncapitalize(layer.getName()); LOGGER.debug("selector={}", selector); final Node layerNode = rootRegion.lookup(selector); LOGGER.info("rootRegion={}; selector={}; layerNode={}", rootRegion, selector, layerNode); if (layerNode != null) { layer.setDrawable((Pane) layerNode); } } }); } /** * Getter. * @return FXML listener */ @ThreadPolicy(ThreadPolicy.ThreadId.ANY) public FXMLListener getFxmlListener() { return fxmlListener; } /** * Getter. * @return root region */ @ThreadPolicy(ThreadPolicy.ThreadId.JFX) public Parent getRootRegion() { return rootRegion; } /** * Getter. * @return layout as string */ @ThreadPolicy(ThreadPolicy.ThreadId.ANY) public synchronized String getLayoutAsString() { layout.fromStage(rootStage); return layout.toString(); } }