diff --git a/src/main/java/io/bitsquare/BitSquare.java b/src/main/java/io/bitsquare/BitSquare.java index bd4aa2cc2b..6badf0c95e 100644 --- a/src/main/java/io/bitsquare/BitSquare.java +++ b/src/main/java/io/bitsquare/BitSquare.java @@ -7,7 +7,7 @@ import io.bitsquare.btc.WalletFacade; import io.bitsquare.di.BitSquareModule; import io.bitsquare.di.GuiceFXMLLoader; import io.bitsquare.gui.NavigationItem; -import io.bitsquare.gui.popups.Popups; +import io.bitsquare.gui.components.Popups; import io.bitsquare.gui.util.Profiler; import io.bitsquare.msg.MessageFacade; import io.bitsquare.settings.Settings; @@ -94,7 +94,7 @@ public class BitSquare extends Application GuiceFXMLLoader.setInjector(injector); - final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(NavigationItem.MAIN.getFxmlUrl())); + final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(NavigationItem.MAIN.getFxmlUrl()), false); final Parent view = loader.load(); final Scene scene = new Scene(view, 1000, 750); scene.getStylesheets().setAll(getClass().getResource("/io/bitsquare/gui/bitsquare.css").toExternalForm()); diff --git a/src/main/java/io/bitsquare/di/GuiceFXMLLoader.java b/src/main/java/io/bitsquare/di/GuiceFXMLLoader.java index fd77306dcb..3cc1d69b6b 100644 --- a/src/main/java/io/bitsquare/di/GuiceFXMLLoader.java +++ b/src/main/java/io/bitsquare/di/GuiceFXMLLoader.java @@ -40,8 +40,6 @@ public class GuiceFXMLLoader { this.url = url; - //TODO - useCaching = false; isCached = useCaching && cachedGUIItems.containsKey(url); if (!isCached) { diff --git a/src/main/java/io/bitsquare/gui/CachedViewController.java b/src/main/java/io/bitsquare/gui/CachedViewController.java new file mode 100644 index 0000000000..ce0693bccb --- /dev/null +++ b/src/main/java/io/bitsquare/gui/CachedViewController.java @@ -0,0 +1,67 @@ +package io.bitsquare.gui; + +import java.net.URL; +import java.util.ResourceBundle; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * If caching is used for loader we use the CachedViewController for turning the controller into sleep mode if not active and awake it at reactivation. + */ +public abstract class CachedViewController extends ViewController +{ + private static final Logger log = LoggerFactory.getLogger(CachedViewController.class); + + /** + * Get called form GUI framework when the UI is ready. + * In caching controllers the initialize is only used for static UI setup. + * The activate() method is called to start resources like. + * + * @param url + * @param rb + */ + @Override + public void initialize(URL url, ResourceBundle rb) + { + log.trace("Lifecycle: initialize " + this.getClass().getSimpleName()); + root.sceneProperty().addListener((ov, oldValue, newValue) -> { + // we got removed from the scene + // lets terminate + log.trace("Lifecycle: sceneProperty changed: " + this.getClass().getSimpleName() + " / oldValue=" + oldValue + " / newValue=" + newValue); + if (oldValue == null && newValue != null) activate(); + else if (oldValue != null && newValue == null) deactivate(); + }); + } + + /** + * In caching controllers the terminate calls the deactivate method. + */ + @Override + public void terminate() + { + log.trace("Lifecycle: terminate " + this.getClass().getSimpleName()); + super.terminate(); + + deactivate(); + } + + /** + * Used for deactivating resources (removing listeners, stopping timers or animations,...) + */ + public void deactivate() + { + log.trace("Lifecycle: deactivate " + this.getClass().getSimpleName()); + if (childController instanceof CachedViewController) ((CachedViewController) childController).deactivate(); + } + + /** + * Used to activate resources (adding listeners, starting timers or animations,...) + */ + public void activate() + { + log.trace("Lifecycle: activate " + this.getClass().getSimpleName()); + if (childController instanceof CachedViewController) ((CachedViewController) childController).activate(); + } + + +} diff --git a/src/main/java/io/bitsquare/gui/ChildController.java b/src/main/java/io/bitsquare/gui/ChildController.java deleted file mode 100644 index 03a20c98db..0000000000 --- a/src/main/java/io/bitsquare/gui/ChildController.java +++ /dev/null @@ -1,8 +0,0 @@ -package io.bitsquare.gui; - -public interface ChildController -{ - void setNavigationController(NavigationController navigationController); - - void cleanup(); -} diff --git a/src/main/java/io/bitsquare/gui/Hibernate.java b/src/main/java/io/bitsquare/gui/Hibernate.java deleted file mode 100644 index 9767f74dc5..0000000000 --- a/src/main/java/io/bitsquare/gui/Hibernate.java +++ /dev/null @@ -1,9 +0,0 @@ -package io.bitsquare.gui; - -public interface Hibernate -{ - void sleep(); - - void awake(); - -} diff --git a/src/main/java/io/bitsquare/gui/MainController.java b/src/main/java/io/bitsquare/gui/MainController.java index 72995e19ce..47b22ff5db 100644 --- a/src/main/java/io/bitsquare/gui/MainController.java +++ b/src/main/java/io/bitsquare/gui/MainController.java @@ -21,8 +21,6 @@ import java.net.URL; import java.util.ResourceBundle; import javafx.application.Platform; import javafx.collections.FXCollections; -import javafx.fxml.FXML; -import javafx.fxml.Initializable; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; @@ -42,7 +40,7 @@ import org.slf4j.LoggerFactory; * We use a sequence of Platform.runLater cascaded calls to make the startup more smooth, otherwise the rendering is frozen for too long. * Pre-loading of views is not implemented yet, and after a quick test it seemed that it does not give much improvements. */ -public class MainController implements Initializable, NavigationController +public class MainController extends ViewController { private static final Logger log = LoggerFactory.getLogger(MainController.class); private static MainController INSTANCE; @@ -55,7 +53,6 @@ public class MainController implements Initializable, NavigationController private final ToggleGroup toggleGroup = new ToggleGroup(); private final ViewBuilder viewBuilder; - private ChildController childController; private ToggleButton prevToggleButton; private Image prevToggleButtonIcon; private ToggleButton buyButton, sellButton, homeButton, msgButton, ordersButton, fundsButton, settingsButton; @@ -63,7 +60,15 @@ public class MainController implements Initializable, NavigationController private boolean messageFacadeInited; private boolean walletFacadeInited; - @FXML private BorderPane root; + + /////////////////////////////////////////////////////////////////////////////////////////// + // Static + /////////////////////////////////////////////////////////////////////////////////////////// + + public static MainController GET_INSTANCE() + { + return INSTANCE; + } /////////////////////////////////////////////////////////////////////////////////////////// @@ -84,34 +89,33 @@ public class MainController implements Initializable, NavigationController MainController.INSTANCE = this; } - /////////////////////////////////////////////////////////////////////////////////////////// - // Static - /////////////////////////////////////////////////////////////////////////////////////////// - - - public static MainController GET_INSTANCE() - { - return INSTANCE; - } - /////////////////////////////////////////////////////////////////////////////////////////// - // Interface implementation: Initializable + // Lifecycle /////////////////////////////////////////////////////////////////////////////////////////// @Override public void initialize(URL url, ResourceBundle rb) { + super.initialize(url, rb); + Profiler.printMsgWithTime("MainController.initialize"); - Platform.runLater(() -> viewBuilder.buildSplashScreen(root, this)); + Platform.runLater(() -> viewBuilder.buildSplashScreen((BorderPane) root, this)); } + @Override + public void terminate() + { + super.terminate(); + } + + /////////////////////////////////////////////////////////////////////////////////////////// - // Interface implementation: NavigationController + // Navigation /////////////////////////////////////////////////////////////////////////////////////////// @Override - public ChildController navigateToView(NavigationItem navigationItem) + public ViewController loadViewAndGetChildController(NavigationItem navigationItem) { switch (navigationItem) { @@ -145,7 +149,7 @@ public class MainController implements Initializable, NavigationController // Startup Handlers /////////////////////////////////////////////////////////////////////////////////////////// - public void onViewInitialized() + void onViewInitialized() { Profiler.printMsgWithTime("MainController.onViewInitialized"); Platform.runLater(this::initFacades); @@ -282,7 +286,7 @@ public class MainController implements Initializable, NavigationController if (selectedNavigationItem == null) selectedNavigationItem = NavigationItem.BUY; - navigateToView(selectedNavigationItem); + loadViewAndGetChildController(selectedNavigationItem); Platform.runLater(this::onContentViewLoaded); } @@ -292,31 +296,25 @@ public class MainController implements Initializable, NavigationController // Private methods /////////////////////////////////////////////////////////////////////////////////////////// - private ChildController loadView(NavigationItem navigationItem) + private void loadViewFromNavButton(NavigationItem navigationItem) { - if (childController != null) - { - childController.cleanup(); - if (childController instanceof Hibernate) - ((Hibernate) childController).sleep(); - } - + + /* if (childController instanceof CachedViewController) + ((CachedViewController) childController).deactivate(); + else if (childController != null) + childController.terminate();*/ + final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl())); try { final Node view = loader.load(); viewBuilder.contentPane.getChildren().setAll(view); childController = loader.getController(); - childController.setNavigationController(this); + childController.setParentController(this); } catch (IOException e) { - e.printStackTrace(); log.error("Loading view failed. " + navigationItem.getFxmlUrl()); } - if (childController instanceof Hibernate) - ((Hibernate) childController).awake(); - - return childController; } private ToggleButton addNavButton(Pane parent, String title, NavigationItem navigationItem) @@ -335,7 +333,7 @@ public class MainController implements Initializable, NavigationController prevToggleButtonIcon = ((ImageView) (toggleButton.getGraphic())).getImage(); ((ImageView) (toggleButton.getGraphic())).setImage(ImageUtil.getIconImage(navigationItem.getActiveIcon())); - childController = loadView(navigationItem); + loadViewFromNavButton(navigationItem); persistence.write(this, "selectedNavigationItem", navigationItem); diff --git a/src/main/java/io/bitsquare/gui/MainView.fxml b/src/main/java/io/bitsquare/gui/MainView.fxml index a5c871aa24..a98e79239b 100644 --- a/src/main/java/io/bitsquare/gui/MainView.fxml +++ b/src/main/java/io/bitsquare/gui/MainView.fxml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/src/main/java/io/bitsquare/gui/NavigationController.java b/src/main/java/io/bitsquare/gui/NavigationController.java deleted file mode 100644 index cd6d7670d8..0000000000 --- a/src/main/java/io/bitsquare/gui/NavigationController.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.bitsquare.gui; - -public interface NavigationController -{ - - ChildController navigateToView(NavigationItem navigationItem); -} diff --git a/src/main/java/io/bitsquare/gui/NavigationItem.java b/src/main/java/io/bitsquare/gui/NavigationItem.java index 069af9f6bc..5d718b6abb 100644 --- a/src/main/java/io/bitsquare/gui/NavigationItem.java +++ b/src/main/java/io/bitsquare/gui/NavigationItem.java @@ -6,16 +6,16 @@ public enum NavigationItem { MAIN("/io/bitsquare/gui/MainView.fxml"), HOME("/io/bitsquare/gui/home/HomeView.fxml", ImageUtil.HOME, ImageUtil.HOME_ACTIVE), - BUY("/io/bitsquare/gui/market/BuyView.fxml", ImageUtil.NAV_BUY, ImageUtil.NAV_BUY_ACTIVE), - SELL("/io/bitsquare/gui/market/SellView.fxml", ImageUtil.NAV_SELL, ImageUtil.NAV_SELL_ACTIVE), + BUY("/io/bitsquare/gui/trade/BuyView.fxml", ImageUtil.NAV_BUY, ImageUtil.NAV_BUY_ACTIVE), + SELL("/io/bitsquare/gui/trade/SellView.fxml", ImageUtil.NAV_SELL, ImageUtil.NAV_SELL_ACTIVE), ORDERS("/io/bitsquare/gui/orders/OrdersView.fxml", ImageUtil.ORDERS, ImageUtil.ORDERS_ACTIVE), FUNDS("/io/bitsquare/gui/funds/FundsView.fxml", ImageUtil.FUNDS, ImageUtil.FUNDS_ACTIVE), MSG("/io/bitsquare/gui/msg/MsgView.fxml", ImageUtil.MSG, ImageUtil.MSG_ACTIVE), SETTINGS("/io/bitsquare/gui/settings/SettingsView.fxml", ImageUtil.SETTINGS, ImageUtil.SETTINGS_ACTIVE), - ORDER_BOOK("/io/bitsquare/gui/market/orderbook/OrderBookView.fxml"), - CREATE_OFFER("/io/bitsquare/gui/market/createOffer/CreateOfferView.fxml"), - TAKE_OFFER("/io/bitsquare/gui/market/trade/TakeOfferView.fxml"), + ORDER_BOOK("/io/bitsquare/gui/trade/orderbook/OrderBookView.fxml"), + CREATE_OFFER("/io/bitsquare/gui/trade/createoffer/CreateOfferView.fxml"), + TAKE_OFFER("/io/bitsquare/gui/trade/takeoffer/TakeOfferView.fxml"), //OFFERER_TRADE("/io/bitsquare/gui/orders/OffererTradeView.fxml"), OFFER("/io/bitsquare/gui/orders/offer/OfferView.fxml"), diff --git a/src/main/java/io/bitsquare/gui/ViewController.java b/src/main/java/io/bitsquare/gui/ViewController.java new file mode 100644 index 0000000000..9dcb451e47 --- /dev/null +++ b/src/main/java/io/bitsquare/gui/ViewController.java @@ -0,0 +1,68 @@ +package io.bitsquare.gui; + +import java.net.URL; +import java.util.ResourceBundle; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.Parent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Base class for all controllers. + */ +public abstract class ViewController implements Initializable +{ + private static final Logger log = LoggerFactory.getLogger(ViewController.class); + + protected ViewController childController; + protected ViewController parentController; + + @FXML protected Parent root; + + /** + * Get called form GUI framework when the UI is ready. + * + * @param url + * @param rb + */ + @Override + public void initialize(URL url, ResourceBundle rb) + { + log.trace("Lifecycle: initialize " + this.getClass().getSimpleName()); + root.sceneProperty().addListener((ov, oldValue, newValue) -> { + // we got removed from the scene + // lets terminate + if (oldValue != null && newValue == null) terminate(); + }); + } + + /** + * Called automatically when view gets removed. Used for house keeping (removing listeners, stopping timers or animations,...). + */ + public void terminate() + { + log.trace("Lifecycle: terminate " + this.getClass().getSimpleName()); + if (childController != null) childController.terminate(); + } + + /** + * @param parentController Controller who has created this.getClass().getSimpleName() instance (via navigateToView/FXMLLoader). + */ + public void setParentController(ViewController parentController) + { + log.trace("Lifecycle: setParentController " + this.getClass().getSimpleName() + " / parent = " + parentController); + this.parentController = parentController; + } + + /** + * @param navigationItem NavigationItem to be loaded. + * @return The ViewController of the loaded view. + */ + public ViewController loadViewAndGetChildController(NavigationItem navigationItem) + { + log.trace("Lifecycle: loadViewAndGetChildController " + this.getClass().getSimpleName() + " / navigationItem = " + navigationItem); + return null; + } + +} diff --git a/src/main/java/io/bitsquare/gui/arbitrators/overview/ArbitratorOverviewController.java b/src/main/java/io/bitsquare/gui/arbitrators/overview/ArbitratorOverviewController.java index 50bfc8b108..90ad6b7499 100644 --- a/src/main/java/io/bitsquare/gui/arbitrators/overview/ArbitratorOverviewController.java +++ b/src/main/java/io/bitsquare/gui/arbitrators/overview/ArbitratorOverviewController.java @@ -1,9 +1,9 @@ package io.bitsquare.gui.arbitrators.overview; import io.bitsquare.di.GuiceFXMLLoader; -import io.bitsquare.gui.ChildController; -import io.bitsquare.gui.NavigationController; +import io.bitsquare.gui.CachedViewController; import io.bitsquare.gui.NavigationItem; +import io.bitsquare.gui.ViewController; import io.bitsquare.gui.arbitrators.profile.ArbitratorProfileController; import io.bitsquare.locale.LanguageUtil; import io.bitsquare.msg.MessageFacade; @@ -18,10 +18,8 @@ import java.util.List; import java.util.Map; import java.util.ResourceBundle; import javafx.fxml.FXML; -import javafx.fxml.Initializable; import javafx.scene.Node; import javafx.scene.control.Button; -import javafx.scene.layout.AnchorPane; import javafx.scene.layout.Pane; import javafx.stage.Stage; import javax.inject.Inject; @@ -34,7 +32,7 @@ import net.tomp2p.storage.Data; * import net.tomp2p.storage.Data; */ @SuppressWarnings({"ALL", "UnusedParameters"}) -public class ArbitratorOverviewController implements Initializable, ChildController, NavigationController, ArbitratorListener +public class ArbitratorOverviewController extends CachedViewController implements ArbitratorListener { private final Settings settings; private final Persistence persistence; @@ -42,16 +40,11 @@ public class ArbitratorOverviewController implements Initializable, ChildControl private final MessageFacade messageFacade; private final List allArbitrators = new ArrayList<>(); private Arbitrator currentArbitrator; - private NavigationController navigationController; private ArbitratorProfileController arbitratorProfileController; private int index = -1; - @FXML - private Button prevButton, nextButton, selectButton, closeButton; - @FXML - private AnchorPane rootContainer; - @FXML - private Pane arbitratorProfile; + @FXML private Button prevButton, nextButton, selectButton, closeButton; + @FXML private Pane arbitratorProfile; /////////////////////////////////////////////////////////////////////////////////////////// // Constructor @@ -71,54 +64,57 @@ public class ArbitratorOverviewController implements Initializable, ChildControl /////////////////////////////////////////////////////////////////////////////////////////// - // Interface implementation: Initializable + // Lifecycle /////////////////////////////////////////////////////////////////////////////////////////// @Override public void initialize(URL url, ResourceBundle rb) { - navigateToView(NavigationItem.ARBITRATOR_PROFILE); + super.initialize(url, rb); + + loadViewAndGetChildController(NavigationItem.ARBITRATOR_PROFILE); checkButtonState(); } - - /////////////////////////////////////////////////////////////////////////////////////////// - // Interface implementation: ChildController - /////////////////////////////////////////////////////////////////////////////////////////// - @Override - public void setNavigationController(NavigationController navigationController) + public void terminate() { - this.navigationController = navigationController; + super.terminate(); } @Override - public void cleanup() + public void deactivate() { + super.deactivate(); + } + @Override + public void activate() + { + super.activate(); } /////////////////////////////////////////////////////////////////////////////////////////// - // Interface implementation: NavigationController + // Navigation /////////////////////////////////////////////////////////////////////////////////////////// + @Override + public void setParentController(ViewController parentController) + { + super.setParentController(parentController); + } @Override - public ChildController navigateToView(NavigationItem navigationItem) + public ViewController loadViewAndGetChildController(NavigationItem navigationItem) { - if (arbitratorProfileController != null) - { - arbitratorProfileController.cleanup(); - } - final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(navigationItem.getFxmlUrl())); try { final Node view = loader.load(); arbitratorProfileController = loader.getController(); - arbitratorProfileController.setNavigationController(this); - rootContainer.getChildren().set(0, view); + arbitratorProfileController.setParentController(this); + ((Pane) root).getChildren().set(0, view); return arbitratorProfileController; } catch (IOException e) @@ -219,7 +215,7 @@ public class ArbitratorOverviewController implements Initializable, ChildControl @FXML public void onClose() { - Stage stage = (Stage) rootContainer.getScene().getWindow(); + Stage stage = (Stage) root.getScene().getWindow(); stage.close(); } diff --git a/src/main/java/io/bitsquare/gui/arbitrators/overview/ArbitratorOverviewView.fxml b/src/main/java/io/bitsquare/gui/arbitrators/overview/ArbitratorOverviewView.fxml index 19631ae973..d4d2863070 100644 --- a/src/main/java/io/bitsquare/gui/arbitrators/overview/ArbitratorOverviewView.fxml +++ b/src/main/java/io/bitsquare/gui/arbitrators/overview/ArbitratorOverviewView.fxml @@ -2,8 +2,9 @@ - +