Introduce viewfx.view.support.CachingViewLoader

... and move view.fxml package to view.support.fxml
This commit is contained in:
Chris Beams 2014-11-24 08:57:22 +01:00
parent a2c98d9ea3
commit 444948f3ca
No known key found for this signature in database
GPG key ID: 3D214F8F5BC5ED73
11 changed files with 86 additions and 42 deletions

View file

@ -39,7 +39,8 @@ import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import viewfx.view.View; import viewfx.view.View;
import viewfx.view.fxml.FxmlViewLoader; import viewfx.view.ViewLoader;
import viewfx.view.support.CachingViewLoader;
import viewfx.view.support.guice.GuiceViewFactory; import viewfx.view.support.guice.GuiceViewFactory;
import javafx.application.Application; import javafx.application.Application;
@ -95,8 +96,8 @@ public class BitsquareApp extends Application {
// load the main view and create the main scene // load the main view and create the main scene
FxmlViewLoader viewLoader = injector.getInstance(FxmlViewLoader.class); ViewLoader viewLoader = injector.getInstance(CachingViewLoader.class);
View view = viewLoader.load(Navigation.Item.MAIN.getFxmlUrl(), false); View view = viewLoader.load(Navigation.Item.MAIN.getFxmlUrl());
Scene scene = new Scene((Parent) view.getRoot(), 1000, 600); Scene scene = new Scene((Parent) view.getRoot(), 1000, 600);
scene.getStylesheets().setAll( scene.getStylesheets().setAll(

View file

@ -37,7 +37,8 @@ import java.util.ResourceBundle;
import viewfx.view.ViewFactory; import viewfx.view.ViewFactory;
import viewfx.view.ViewLoader; import viewfx.view.ViewLoader;
import viewfx.view.fxml.FxmlViewLoader; import viewfx.view.support.CachingViewLoader;
import viewfx.view.support.fxml.FxmlViewLoader;
import viewfx.view.support.guice.GuiceViewFactory; import viewfx.view.support.guice.GuiceViewFactory;
import javafx.stage.Stage; import javafx.stage.Stage;
@ -60,6 +61,7 @@ public class GuiModule extends BitsquareModule {
bind(ResourceBundle.class).toInstance(BSResources.getResourceBundle()); bind(ResourceBundle.class).toInstance(BSResources.getResourceBundle());
bind(ViewLoader.class).to(FxmlViewLoader.class).asEagerSingleton(); bind(ViewLoader.class).to(FxmlViewLoader.class).asEagerSingleton();
bind(CachingViewLoader.class).asEagerSingleton();
bind(OfferBook.class).asEagerSingleton(); bind(OfferBook.class).asEagerSingleton();
bind(Navigation.class).asEagerSingleton(); bind(Navigation.class).asEagerSingleton();

View file

@ -23,7 +23,8 @@ import io.bitsquare.gui.main.account.arbitrator.registration.ArbitratorRegistrat
import javax.inject.Inject; import javax.inject.Inject;
import viewfx.view.View; import viewfx.view.View;
import viewfx.view.fxml.FxmlViewLoader; import viewfx.view.ViewLoader;
import viewfx.view.support.CachingViewLoader;
import viewfx.view.support.AbstractView; import viewfx.view.support.AbstractView;
import javafx.fxml.FXML; import javafx.fxml.FXML;
@ -36,19 +37,19 @@ class ArbitratorSettingsView extends AbstractView {
private ArbitratorRegistrationView arbitratorRegistrationView; private ArbitratorRegistrationView arbitratorRegistrationView;
private final FxmlViewLoader viewLoader; private final ViewLoader viewLoader;
private final Navigation navigation; private final Navigation navigation;
private final Stage primaryStage; private final Stage primaryStage;
@Inject @Inject
private ArbitratorSettingsView(FxmlViewLoader viewLoader, Navigation navigation, Stage primaryStage) { private ArbitratorSettingsView(CachingViewLoader viewLoader, Navigation navigation, Stage primaryStage) {
this.viewLoader = viewLoader; this.viewLoader = viewLoader;
this.navigation = navigation; this.navigation = navigation;
this.primaryStage = primaryStage; this.primaryStage = primaryStage;
} }
private void loadView(Navigation.Item navigationItem) { private void loadView(Navigation.Item navigationItem) {
View view = viewLoader.load(navigationItem.getFxmlUrl(), false); View view = viewLoader.load(navigationItem.getFxmlUrl());
arbitratorRegistrationView = (ArbitratorRegistrationView) view; arbitratorRegistrationView = (ArbitratorRegistrationView) view;
final Stage stage = new Stage(); final Stage stage = new Stage();

View file

@ -30,8 +30,9 @@ import java.util.Locale;
import javax.inject.Inject; import javax.inject.Inject;
import viewfx.view.View; import viewfx.view.View;
import viewfx.view.fxml.FxmlViewLoader; import viewfx.view.ViewLoader;
import viewfx.view.Wizard; import viewfx.view.Wizard;
import viewfx.view.support.CachingViewLoader;
import viewfx.view.support.ActivatableViewAndModel; import viewfx.view.support.ActivatableViewAndModel;
import javafx.fxml.FXML; import javafx.fxml.FXML;
@ -56,11 +57,11 @@ public class RestrictionsView extends ActivatableViewAndModel<GridPane, Restrict
private Wizard parent; private Wizard parent;
private final FxmlViewLoader viewLoader; private final ViewLoader viewLoader;
private final Stage primaryStage; private final Stage primaryStage;
@Inject @Inject
private RestrictionsView(RestrictionsViewModel model, FxmlViewLoader viewLoader, Stage primaryStage) { private RestrictionsView(RestrictionsViewModel model, CachingViewLoader viewLoader, Stage primaryStage) {
super(model); super(model);
this.viewLoader = viewLoader; this.viewLoader = viewLoader;
this.primaryStage = primaryStage; this.primaryStage = primaryStage;
@ -146,7 +147,7 @@ public class RestrictionsView extends ActivatableViewAndModel<GridPane, Restrict
} }
private void loadView(Navigation.Item navigationItem) { private void loadView(Navigation.Item navigationItem) {
View view = viewLoader.load(navigationItem.getFxmlUrl(), false); View view = viewLoader.load(navigationItem.getFxmlUrl());
final Stage stage = new Stage(); final Stage stage = new Stage();
stage.setTitle("Arbitrator selection"); stage.setTitle("Arbitrator selection");

View file

@ -21,12 +21,12 @@ import io.bitsquare.gui.Navigation;
import javax.inject.Inject; import javax.inject.Inject;
import viewfx.view.fxml.FxmlViewLoader; import viewfx.view.support.CachingViewLoader;
class BuyView extends TradeView { class BuyView extends TradeView {
@Inject @Inject
public BuyView(FxmlViewLoader viewLoader, Navigation navigation) { public BuyView(CachingViewLoader viewLoader, Navigation navigation) {
super(viewLoader, navigation); super(viewLoader, navigation);
} }
} }

View file

@ -21,12 +21,12 @@ import io.bitsquare.gui.Navigation;
import javax.inject.Inject; import javax.inject.Inject;
import viewfx.view.fxml.FxmlViewLoader; import viewfx.view.support.CachingViewLoader;
class SellView extends TradeView { class SellView extends TradeView {
@Inject @Inject
public SellView(FxmlViewLoader viewLoader, Navigation navigation) { public SellView(CachingViewLoader viewLoader, Navigation navigation) {
super(viewLoader, navigation); super(viewLoader, navigation);
} }
} }

View file

@ -31,7 +31,8 @@ import org.bitcoinj.utils.Fiat;
import java.util.List; import java.util.List;
import viewfx.view.View; import viewfx.view.View;
import viewfx.view.fxml.FxmlViewLoader; import viewfx.view.ViewLoader;
import viewfx.view.support.CachingViewLoader;
import viewfx.view.support.ActivatableView; import viewfx.view.support.ActivatableView;
import javafx.application.Platform; import javafx.application.Platform;
@ -53,10 +54,10 @@ public class TradeView extends ActivatableView<TabPane, Void> {
private Fiat price; private Fiat price;
private Offer offer; private Offer offer;
private final FxmlViewLoader viewLoader; private final ViewLoader viewLoader;
private final Navigation navigation; private final Navigation navigation;
protected TradeView(FxmlViewLoader viewLoader, Navigation navigation) { protected TradeView(CachingViewLoader viewLoader, Navigation navigation) {
this.viewLoader = viewLoader; this.viewLoader = viewLoader;
this.navigation = navigation; this.navigation = navigation;
} }
@ -122,7 +123,7 @@ public class TradeView extends ActivatableView<TabPane, Void> {
TabPane tabPane = root; TabPane tabPane = root;
if (navigationItem == Navigation.Item.OFFER_BOOK && offerBookView == null) { if (navigationItem == Navigation.Item.OFFER_BOOK && offerBookView == null) {
// Offerbook must not be cached by ViewLoader as we use 2 instances for sell and buy screens. // Offerbook must not be cached by ViewLoader as we use 2 instances for sell and buy screens.
View view = viewLoader.load(navigationItem.getFxmlUrl(), false); View view = viewLoader.load(navigationItem.getFxmlUrl());
final Tab tab = new Tab(direction == Direction.BUY ? "Buy Bitcoin" : "Sell Bitcoin"); final Tab tab = new Tab(direction == Direction.BUY ? "Buy Bitcoin" : "Sell Bitcoin");
tab.setClosable(false); tab.setClosable(false);
tab.setContent(view.getRoot()); tab.setContent(view.getRoot());
@ -137,7 +138,7 @@ public class TradeView extends ActivatableView<TabPane, Void> {
else if (navigationItem == Navigation.Item.CREATE_OFFER && createOfferView == null) { else if (navigationItem == Navigation.Item.CREATE_OFFER && createOfferView == null) {
// CreateOffer and TakeOffer must not be cached by ViewLoader as we cannot use a view multiple times // CreateOffer and TakeOffer must not be cached by ViewLoader as we cannot use a view multiple times
// in different graphs // in different graphs
View view = viewLoader.load(navigationItem.getFxmlUrl(), false); View view = viewLoader.load(navigationItem.getFxmlUrl());
createOfferView = (CreateOfferView) view; createOfferView = (CreateOfferView) view;
createOfferView.initWithData(direction, amount, price); createOfferView.initWithData(direction, amount, price);
createOfferRoot = view.getRoot(); createOfferRoot = view.getRoot();
@ -152,7 +153,7 @@ public class TradeView extends ActivatableView<TabPane, Void> {
offer != null) { offer != null) {
// CreateOffer and TakeOffer must not be cached by ViewLoader as we cannot use a view multiple times // CreateOffer and TakeOffer must not be cached by ViewLoader as we cannot use a view multiple times
// in different graphs // in different graphs
View view = viewLoader.load(Navigation.Item.TAKE_OFFER.getFxmlUrl(), false); View view = viewLoader.load(Navigation.Item.TAKE_OFFER.getFxmlUrl());
takeOfferView = (TakeOfferView) view; takeOfferView = (TakeOfferView) view;
takeOfferView.initWithData(direction, amount, offer); takeOfferView.initWithData(direction, amount, offer);
takeOfferRoot = view.getRoot(); takeOfferRoot = view.getRoot();

View file

@ -17,6 +17,6 @@
package viewfx.view; package viewfx.view;
public interface ViewLoader<Location> { public interface ViewLoader {
View load(Location location); View load(Object location);
} }

View file

@ -0,0 +1,46 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package viewfx.view.support;
import java.util.HashMap;
import javax.inject.Inject;
import viewfx.view.View;
import viewfx.view.ViewLoader;
public class CachingViewLoader implements ViewLoader {
private final HashMap<Object, View> cache = new HashMap<>();
private final ViewLoader delegate;
@Inject
public CachingViewLoader(ViewLoader delegate) {
this.delegate = delegate;
}
@Override
public View load(Object location) {
if (cache.containsKey(location))
return cache.get(location);
View view = delegate.load(location);
cache.put(location, view);
return view;
}
}

View file

@ -15,14 +15,12 @@
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>. * along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/ */
package viewfx.view.fxml; package viewfx.view.support.fxml;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import javax.inject.Inject; import javax.inject.Inject;
@ -33,9 +31,8 @@ import viewfx.view.ViewLoader;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
public class FxmlViewLoader implements ViewLoader<URL> { public class FxmlViewLoader implements ViewLoader {
private final Map<URL, View> cache = new HashMap<>();
private final ViewFactory viewFactory; private final ViewFactory viewFactory;
private final ResourceBundle resourceBundle; private final ResourceBundle resourceBundle;
@ -45,22 +42,17 @@ public class FxmlViewLoader implements ViewLoader<URL> {
this.resourceBundle = resourceBundle; this.resourceBundle = resourceBundle;
} }
@Override public View load(Object location) {
public View load(URL url) { if (!(location instanceof URL))
return load(url, true); throw new IllegalArgumentException("FXML view locations must be of type URL");
}
public View load(URL url, boolean useCaching) { URL url = (URL) location;
if (useCaching && cache.containsKey(url))
return cache.get(url);
try { try {
FXMLLoader loader = new FXMLLoader(url, resourceBundle); FXMLLoader loader = new FXMLLoader(url, resourceBundle);
loader.setControllerFactory(viewFactory); loader.setControllerFactory(viewFactory);
loader.load(); loader.load();
View view = loader.getController(); return loader.getController();
cache.put(url, view);
return view;
} catch (IOException ex) { } catch (IOException ex) {
throw new RuntimeException("Failed to load View at location " + url, ex); throw new RuntimeException("Failed to load View at location " + url, ex);
} }

View file

@ -29,7 +29,7 @@ import java.net.MalformedURLException;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import viewfx.view.fxml.FxmlViewLoader; import viewfx.view.support.fxml.FxmlViewLoader;
import viewfx.view.support.guice.GuiceViewFactory; import viewfx.view.support.guice.GuiceViewFactory;
import javafx.application.Application; import javafx.application.Application;
@ -81,11 +81,11 @@ public class ViewLoaderTests {
@Test(expected = BitsquareException.class) @Test(expected = BitsquareException.class)
public void loadingBogusFxmlResourceShouldThrow() throws MalformedURLException { public void loadingBogusFxmlResourceShouldThrow() throws MalformedURLException {
new FxmlViewLoader(viewFactory, resourceBundle).load(Navigation.Item.BOGUS.getFxmlUrl(), false); new FxmlViewLoader(viewFactory, resourceBundle).load(Navigation.Item.BOGUS.getFxmlUrl());
} }
@Test @Test
public void loadingValidFxmlResourceShouldNotThrow() { public void loadingValidFxmlResourceShouldNotThrow() {
new FxmlViewLoader(viewFactory, resourceBundle).load(Navigation.Item.ACCOUNT.getFxmlUrl(), false); new FxmlViewLoader(viewFactory, resourceBundle).load(Navigation.Item.ACCOUNT.getFxmlUrl());
} }
} }