package com.insightfullogic.honest_profiler.ports.javafx.controller; import java.util.ResourceBundle; import com.insightfullogic.honest_profiler.ports.javafx.model.ApplicationContext; import javafx.scene.Node; import javafx.scene.control.Tab; /** * Superclass for all Controllers in the application. It holds the {@link ApplicationContext}, a context which is shared * by all controllers. * <p> * The class interacts with the {@link ApplicationContext} for I18N, retrieving the resources for keys. It also manages * what is displayed in the InfoBar, an application-level text area displayed at the bottem of the root window, used for * displaying contextual help and information messages. * <p> * NOTE : Any controllers extending this class, and which in turn contain other ApplicationController controllers, * should override {@link #setApplicationContext(ApplicationContext)} using the following pattern : * * <pre> * <code> * public setApplicationContext(ApplicationContext context) * { * super.setApplicationContext(context); * <includedController1>.setApplicationContext(context); * <includedController2>.setApplicationContext(context); * ... * } * </code> * </pre> */ public abstract class AbstractController { // Instance Properties private ApplicationContext applicationContext; // FXML Implementation /** * This method must be called by subclasses in their FXML initialize(). * <p> * The idea is to streamline similar tasks happening in the initialization method, and encourage decluttering of the * initialize() methods by extracting similar tasks to separate methods. */ protected void initialize() { initializeInfoText(); initializeHandlers(); } /** * Link nodes with "InfoBar" messages. * <p> * The InfoBar is the info- or status bar at the bottom of the UI. While hovering over various {@link Node}s or when * specific events occur, helpful information should appear in the InfoBar. */ protected abstract void initializeInfoText(); /** * Associate various Handlers and/or Listeners with the {@link Node}s managed by the subclassing controller. */ protected abstract void initializeHandlers(); // Instance Accessors /** * Returns the {@link ApplicationContext}. The name has been shortened to unclutter code in subclasses. * <p> * * @return the {@link ApplicationContext} of this application */ protected ApplicationContext appCtx() { return applicationContext; } /** * Sets the application context. * <p> * NOTE : Any controllers extending this class, and which in turn contain other ApplicationController controllers, * should override this method using the following pattern : * * <pre> * <code> * public setApplicationContext(ApplicationContext context) * { * super.setApplicationContext(context); * <includedController1>.setApplicationContext(context); * <includedController2>.setApplicationContext(context); * ... * } * </code> * </pre> * <p> * * @param applicationContext the ApplicationContext of this application */ public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } // I18N-related Methods /** * Look up the String associated with this key in the current {@link ResourceBundle}. * <p> * * @param key the key in the ResourceBundle * @return the String associated with the key in the current {@link ResourceBundle} */ protected final String getText(String key) { return applicationContext.textFor(key); } /** * Construct the String based on the pattern associated with this key in the current {@link ResourceBundle}, using * the provided arguments. * <p> * * @param key the key in the ResourceBundle * @param args the arguments needed by the pattern * @return the String constructed using the pattern and provided arguments */ protected final String getText(String key, Object... args) { return applicationContext.textFor(key, args); } // InfoBar-related Methods /** * Display a message in the InfoBar, by retrieving the message from the current {@link ResourceBundle} using the * provided key. * <p> * * @param key the key to the message in the {@link ResourceBundle} */ protected final void infoFromBundle(String key) { applicationContext.setInfoFromBundle(key); } /** * Display a message in the InfoBar, by retrieving the pattern from the current {@link ResourceBundle} using the * provided key and formatting it using the provided arguments. * <p> * * @param key the key to the message pattern in the {@link ResourceBundle} * @param args the arguments needed by the pattern */ protected final void infoFromBundle(String key, Object... args) { applicationContext.setInfoFromBundle(key, args); } /** * Clears the InfoBar. */ protected final void clearInfo() { applicationContext.clearInfo(); } /** * Associates a message with a given {@link Node}. The message is retrieved from the current {@link ResourceBundle} * using the provided key, and is displayed while the InfoBar whenever the mouse hovers over the {@link Node}. * <p> * * @param node the target {@link Node} * @param key the key to the message in the {@link ResourceBundle} */ protected void info(Node node, final String key) { node.onMouseEnteredProperty().set(event -> infoFromBundle(key)); node.onMouseExitedProperty().set(event -> clearInfo()); } /** * Associates a message with a given {@link Node}. The message pattern is retrieved from the current * {@link ResourceBundle} using the provided key, formatted using the provided arguments, and displayed while the * InfoBar whenever the mouse hovers over the {@link Node}. * <p> * * @param node the target Node * @param key the key to the message in the {@link ResourceBundle} * @param args the arguments needed by the pattern */ protected void info(Node node, final String key, Object... args) { node.onMouseEnteredProperty().set(event -> infoFromBundle(key, args)); node.onMouseExitedProperty().set(event -> clearInfo()); } /** * Associates a message with a {@link Tab} Header, as per {@link #info(Node, String)}. * <p> * * @param tab the target {@link Tab} * @param key the key to the message in the {@link ResourceBundle} */ protected void info(Tab tab, final String key) { info(tab.getGraphic(), key); } /** * Associates a message with a {@link Tab} Header, as per {@link #info(Node, String, Object...)}. * <p> * * @param tab the target {@link Tab} * @param key the key to the message in the {@link ResourceBundle} * @param args the arguments needed by the pattern */ protected void info(Tab tab, final String key, Object... args) { info(tab.getGraphic(), key, args); } }