mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-06-09 07:33:12 -04:00
fixed app dir problem with update to gradle.
This commit is contained in:
parent
fb7397eb48
commit
fb89f087f0
18 changed files with 206 additions and 242 deletions
9
.idea/copyright/Bitsquare_Affero_GPLv3.xml
generated
9
.idea/copyright/Bitsquare_Affero_GPLv3.xml
generated
|
@ -1,9 +0,0 @@
|
||||||
<component name="CopyrightManager">
|
|
||||||
<copyright>
|
|
||||||
<option name="notice" value="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/>." />
|
|
||||||
<option name="keyword" value="GNU Affero General Public License" />
|
|
||||||
<option name="allowReplaceKeyword" value="" />
|
|
||||||
<option name="myName" value="Bitsquare Affero GPLv3" />
|
|
||||||
<option name="myLocal" value="true" />
|
|
||||||
</copyright>
|
|
||||||
</component>
|
|
2
.idea/copyright/profiles_settings.xml
generated
2
.idea/copyright/profiles_settings.xml
generated
|
@ -1,3 +1,3 @@
|
||||||
<component name="CopyrightManager">
|
<component name="CopyrightManager">
|
||||||
<settings default="Bitsquare Affero GPLv3" />
|
<settings default="" />
|
||||||
</component>
|
</component>
|
23
Development-notes.md
Normal file
23
Development-notes.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
## UI Architecure pattern:
|
||||||
|
We use the Presentation Model pattern which has some similarities with MVVM (Silverlight, WPF) as we use data
|
||||||
|
bindings, though there are differences in the way the view and the "code behind" is organized (different framework
|
||||||
|
support).
|
||||||
|
We don't use the term controller for the JavaFX controller it has too much association with the classical MVC
|
||||||
|
controller.
|
||||||
|
|
||||||
|
View: FXML or code based View
|
||||||
|
CodeBehind (CB): JavaFX controller associated with FXML View
|
||||||
|
Presentation Model (PM)
|
||||||
|
Model: Domain data
|
||||||
|
|
||||||
|
* State is stored in the presenter.
|
||||||
|
* Logic is stored in presenter.
|
||||||
|
* Presenter represents a abstract view of the UI.
|
||||||
|
* Presenter is not aware of the view.
|
||||||
|
* View is aware of the presenter.
|
||||||
|
* View is completely isolated from the model.
|
||||||
|
|
||||||
|
|
||||||
|
## References:
|
||||||
|
[Presentation Model](http://martinfowler.com/eaaDev/PresentationModel.html)
|
||||||
|
[Model View ViewModel - MVVM](http://msdn.microsoft.com/en-us/magazine/dd419663.aspx)
|
|
@ -28,14 +28,12 @@ import io.bitsquare.persistence.Persistence;
|
||||||
import io.bitsquare.settings.Settings;
|
import io.bitsquare.settings.Settings;
|
||||||
import io.bitsquare.user.User;
|
import io.bitsquare.user.User;
|
||||||
import io.bitsquare.util.AWTSystemTray;
|
import io.bitsquare.util.AWTSystemTray;
|
||||||
import io.bitsquare.util.AppDirectoryUtil;
|
|
||||||
|
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
|
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -48,6 +46,8 @@ import javafx.stage.Stage;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import lighthouse.files.AppDirectory;
|
||||||
|
|
||||||
public class BitSquare extends Application {
|
public class BitSquare extends Application {
|
||||||
private static final Logger log = LoggerFactory.getLogger(BitSquare.class);
|
private static final Logger log = LoggerFactory.getLogger(BitSquare.class);
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ public class BitSquare extends Application {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Profiler.init();
|
Profiler.init();
|
||||||
Profiler.printMsgWithTime("BitSquare.main called with args " + Arrays.asList(args).toString());
|
Profiler.printMsgWithTime("BitSquare.main called with args " + Arrays.asList(args).toString());
|
||||||
if (args != null && args.length > 0) APP_NAME = args[0];
|
if (args.length > 0) APP_NAME = APP_NAME + "_" + args[0];
|
||||||
|
|
||||||
launch(args);
|
launch(args);
|
||||||
}
|
}
|
||||||
|
@ -82,8 +82,7 @@ public class BitSquare extends Application {
|
||||||
Thread.currentThread().setUncaughtExceptionHandler((thread, throwable) -> Popups.handleUncaughtExceptions
|
Thread.currentThread().setUncaughtExceptionHandler((thread, throwable) -> Popups.handleUncaughtExceptions
|
||||||
(Throwables.getRootCause(throwable)));
|
(Throwables.getRootCause(throwable)));
|
||||||
|
|
||||||
AppDirectoryUtil.setStorageDirectory(
|
AppDirectory.initAppDir(APP_NAME);
|
||||||
new File(AppDirectoryUtil.getApplicationDirectory().getCanonicalPath() + "/data"));
|
|
||||||
|
|
||||||
// currently there is not SystemTray support for java fx (planned for version 3) so we use the old AWT
|
// currently there is not SystemTray support for java fx (planned for version 3) so we use the old AWT
|
||||||
AWTSystemTray.createSystemTray(primaryStage);
|
AWTSystemTray.createSystemTray(primaryStage);
|
||||||
|
|
|
@ -22,7 +22,6 @@ import io.bitsquare.btc.listeners.BalanceListener;
|
||||||
import io.bitsquare.btc.listeners.ConfidenceListener;
|
import io.bitsquare.btc.listeners.ConfidenceListener;
|
||||||
import io.bitsquare.crypto.CryptoFacade;
|
import io.bitsquare.crypto.CryptoFacade;
|
||||||
import io.bitsquare.persistence.Persistence;
|
import io.bitsquare.persistence.Persistence;
|
||||||
import io.bitsquare.util.AppDirectoryUtil;
|
|
||||||
|
|
||||||
import com.google.bitcoin.core.Address;
|
import com.google.bitcoin.core.Address;
|
||||||
import com.google.bitcoin.core.AddressFormatException;
|
import com.google.bitcoin.core.AddressFormatException;
|
||||||
|
@ -78,6 +77,8 @@ import javafx.util.Pair;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import lighthouse.files.AppDirectory;
|
||||||
|
|
||||||
import static com.google.bitcoin.script.ScriptOpCodes.OP_RETURN;
|
import static com.google.bitcoin.script.ScriptOpCodes.OP_RETURN;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -139,7 +140,7 @@ public class WalletFacade {
|
||||||
Threading.USER_THREAD = Platform::runLater;
|
Threading.USER_THREAD = Platform::runLater;
|
||||||
|
|
||||||
// If seed is non-null it means we are restoring from backup.
|
// If seed is non-null it means we are restoring from backup.
|
||||||
walletAppKit = new WalletAppKit(params, AppDirectoryUtil.getStorageDirectory(), WALLET_PREFIX) {
|
walletAppKit = new WalletAppKit(params, AppDirectory.dir().toFile(), WALLET_PREFIX) {
|
||||||
@Override
|
@Override
|
||||||
protected void onSetupCompleted() {
|
protected void onSetupCompleted() {
|
||||||
// Don't make the user wait for confirmations for now, as the intention is they're sending it
|
// Don't make the user wait for confirmations for now, as the intention is they're sending it
|
||||||
|
@ -223,8 +224,8 @@ public class WalletFacade {
|
||||||
wallet.addEventListener(walletEventListener);
|
wallet.addEventListener(walletEventListener);
|
||||||
|
|
||||||
Serializable serializable = persistence.read(this, "addressEntryList");
|
Serializable serializable = persistence.read(this, "addressEntryList");
|
||||||
List<AddressEntry> persistedAddressEntryList = (List<AddressEntry>) serializable;
|
|
||||||
if (serializable instanceof List) {
|
if (serializable instanceof List) {
|
||||||
|
List<AddressEntry> persistedAddressEntryList = (List<AddressEntry>) serializable;
|
||||||
for (AddressEntry persistedAddressEntry : persistedAddressEntryList) {
|
for (AddressEntry persistedAddressEntry : persistedAddressEntryList) {
|
||||||
persistedAddressEntry.setDeterministicKey(
|
persistedAddressEntry.setDeterministicKey(
|
||||||
(DeterministicKey) wallet.findKeyFromPubHash(persistedAddressEntry.getPubKeyHash()));
|
(DeterministicKey) wallet.findKeyFromPubHash(persistedAddressEntry.getPubKeyHash()));
|
||||||
|
|
|
@ -22,7 +22,7 @@ import io.bitsquare.gui.CachedViewController;
|
||||||
import io.bitsquare.gui.NavigationItem;
|
import io.bitsquare.gui.NavigationItem;
|
||||||
import io.bitsquare.gui.ViewController;
|
import io.bitsquare.gui.ViewController;
|
||||||
import io.bitsquare.gui.components.ValidatingTextField;
|
import io.bitsquare.gui.components.ValidatingTextField;
|
||||||
import io.bitsquare.gui.trade.createoffer.CreateOfferCodeBehind;
|
import io.bitsquare.gui.trade.createoffer.CreateOfferCB;
|
||||||
import io.bitsquare.gui.trade.orderbook.OrderBookController;
|
import io.bitsquare.gui.trade.orderbook.OrderBookController;
|
||||||
import io.bitsquare.gui.trade.takeoffer.TakeOfferController;
|
import io.bitsquare.gui.trade.takeoffer.TakeOfferController;
|
||||||
import io.bitsquare.trade.Direction;
|
import io.bitsquare.trade.Direction;
|
||||||
|
@ -46,7 +46,7 @@ public class TradeController extends CachedViewController {
|
||||||
private static final Logger log = LoggerFactory.getLogger(TradeController.class);
|
private static final Logger log = LoggerFactory.getLogger(TradeController.class);
|
||||||
|
|
||||||
protected OrderBookController orderBookController;
|
protected OrderBookController orderBookController;
|
||||||
protected CreateOfferCodeBehind createOfferCodeBehind;
|
protected CreateOfferCB createOfferCodeBehind;
|
||||||
protected TakeOfferController takeOfferController;
|
protected TakeOfferController takeOfferController;
|
||||||
protected GuiceFXMLLoader orderBookLoader;
|
protected GuiceFXMLLoader orderBookLoader;
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ public class TradeController extends CachedViewController {
|
||||||
// TODO find better solution
|
// TODO find better solution
|
||||||
// Textfield focus out triggers validation, use runLater as quick fix...
|
// Textfield focus out triggers validation, use runLater as quick fix...
|
||||||
((TabPane) root).getSelectionModel().selectedIndexProperty().addListener((observableValue) ->
|
((TabPane) root).getSelectionModel().selectedIndexProperty().addListener((observableValue) ->
|
||||||
Platform.runLater(() -> ValidatingTextField.hidePopover()));
|
Platform.runLater(ValidatingTextField::hidePopover));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -43,31 +43,34 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Code behind (FXML Controller is part of View, not a classical MVC controller):
|
* Code behind (We don't call it controller as controller is associated with the classical MVC controller):
|
||||||
* <p>
|
* <p>
|
||||||
* Creates Presenter and passes Model from DI to Presenter. Does not hold a reference to Model
|
* - Knows the presentation model, does not know the model
|
||||||
|
* - Has no logic and no state
|
||||||
* <p>
|
* <p>
|
||||||
* - Setup binding from Presenter to View elements (also bidirectional - Inputs). Binding are only to presenters
|
* - Creates presentation model and passes model from Guice injection to the presenter. Does not hold any reference to the model.
|
||||||
* properties, not logical bindings or cross-view element bindings.
|
* //TODO is there a better way for DI of model?
|
||||||
* - Listen to UI events (Action) from View and call method in Presenter.
|
* - Setup binding from presenter to view elements (also bidirectional - used for input data). Binding are only to plain
|
||||||
* - Is entry node for hierarchical view graphs. Passes method calls to Presenter. Calls methods on sub views.
|
* presenter properties. There are no logical bindings or cross-view element bindings.
|
||||||
|
* - Listens to UI events (Actions) from view and calls method in presentation model.
|
||||||
|
* - Is entry node for view graph and responsible for navigation and creation of new views.
|
||||||
|
* - Passes application API method calls to Presenter. Calls application methods on sub views.
|
||||||
* - Handle lifecycle and self removal from scene graph.
|
* - Handle lifecycle and self removal from scene graph.
|
||||||
* - Non declarative (dynamic) view definitions (if it gets larger, then user a ViewBuilder)
|
* - Can contain non-declarative (dynamic) view definitions (if it gets larger, then use a dedicated ViewBuilder)
|
||||||
* - Has no logic and no state, only view elements and a presenter reference!
|
|
||||||
* <p>
|
* <p>
|
||||||
* View:
|
* View:
|
||||||
* - Mostly declared in FXML. Dynamic parts are declared in Controller. If more view elements need to be defined in
|
* - Typically declared in FXML. Dynamic parts are declared in Controller. If more view elements need to be defined in
|
||||||
* code then use ViewBuilder.
|
* code then use a ViewBuilder.
|
||||||
* <p>
|
* <p>
|
||||||
* Optional ViewBuilder:
|
* ViewBuilder (optional):
|
||||||
* - Replacement for FXML view definitions.
|
* - Additionally or instead of FXML view. If no FXML then controller setup need to be handles by ViewBuilder.
|
||||||
* <p>
|
* <p>
|
||||||
* Note: Don't assign the root node as it is defined in the base class!
|
* Note: Don't assign the root node as it is defined in the base class!
|
||||||
*/
|
*/
|
||||||
public class CreateOfferCodeBehind extends CachedViewController {
|
public class CreateOfferCB extends CachedViewController {
|
||||||
private static final Logger log = LoggerFactory.getLogger(CreateOfferCodeBehind.class);
|
private static final Logger log = LoggerFactory.getLogger(CreateOfferCB.class);
|
||||||
|
|
||||||
private final CreateOfferPresenter presenter;
|
private final CreateOfferPM pm;
|
||||||
|
|
||||||
@FXML private Label buyLabel, confirmationLabel, txTitleLabel, collateralLabel;
|
@FXML private Label buyLabel, confirmationLabel, txTitleLabel, collateralLabel;
|
||||||
@FXML private ValidatingTextField amountTextField, minAmountTextField, priceTextField, volumeTextField;
|
@FXML private ValidatingTextField amountTextField, minAmountTextField, priceTextField, volumeTextField;
|
||||||
|
@ -86,8 +89,8 @@ public class CreateOfferCodeBehind extends CachedViewController {
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public CreateOfferCodeBehind(CreateOfferModel model) {
|
public CreateOfferCB(CreateOfferModel model) {
|
||||||
presenter = new CreateOfferPresenter(model);
|
pm = new CreateOfferPM(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -99,17 +102,18 @@ public class CreateOfferCodeBehind extends CachedViewController {
|
||||||
public void initialize(URL url, ResourceBundle rb) {
|
public void initialize(URL url, ResourceBundle rb) {
|
||||||
super.initialize(url, rb);
|
super.initialize(url, rb);
|
||||||
|
|
||||||
presenter.onViewInitialized();
|
pm.onViewInitialized();
|
||||||
|
|
||||||
balanceTextField.setup(presenter.getWalletFacade(), presenter.address.get());
|
balanceTextField.setup(pm.getWalletFacade(), pm.address.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deactivate() {
|
public void deactivate() {
|
||||||
super.deactivate();
|
super.deactivate();
|
||||||
|
|
||||||
presenter.deactivate();
|
pm.deactivate();
|
||||||
|
|
||||||
|
//TODO check that again
|
||||||
((TradeController) parentController).onCreateOfferViewRemoved();
|
((TradeController) parentController).onCreateOfferViewRemoved();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +121,7 @@ public class CreateOfferCodeBehind extends CachedViewController {
|
||||||
public void activate() {
|
public void activate() {
|
||||||
super.activate();
|
super.activate();
|
||||||
|
|
||||||
presenter.activate();
|
pm.activate();
|
||||||
|
|
||||||
setupBindings();
|
setupBindings();
|
||||||
setupListeners();
|
setupListeners();
|
||||||
|
@ -130,7 +134,7 @@ public class CreateOfferCodeBehind extends CachedViewController {
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void setOrderBookFilter(OrderBookFilter orderBookFilter) {
|
public void setOrderBookFilter(OrderBookFilter orderBookFilter) {
|
||||||
presenter.setOrderBookFilter(orderBookFilter);
|
pm.setOrderBookFilter(orderBookFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -140,12 +144,12 @@ public class CreateOfferCodeBehind extends CachedViewController {
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void onPlaceOffer() {
|
public void onPlaceOffer() {
|
||||||
presenter.placeOffer();
|
pm.placeOffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void onClose() {
|
public void onClose() {
|
||||||
presenter.close();
|
pm.close();
|
||||||
|
|
||||||
TabPane tabPane = ((TabPane) (root.getParent().getParent()));
|
TabPane tabPane = ((TabPane) (root.getParent().getParent()));
|
||||||
tabPane.getTabs().remove(tabPane.getSelectionModel().getSelectedItem());
|
tabPane.getTabs().remove(tabPane.getSelectionModel().getSelectedItem());
|
||||||
|
@ -158,26 +162,26 @@ public class CreateOfferCodeBehind extends CachedViewController {
|
||||||
|
|
||||||
private void setupListeners() {
|
private void setupListeners() {
|
||||||
volumeTextField.focusedProperty().addListener((o, oldValue, newValue) -> {
|
volumeTextField.focusedProperty().addListener((o, oldValue, newValue) -> {
|
||||||
presenter.onFocusOutVolumeTextField(oldValue, newValue, volumeTextField.getText());
|
pm.onFocusOutVolumeTextField(oldValue, newValue, volumeTextField.getText());
|
||||||
volumeTextField.setText(presenter.volume.get());
|
volumeTextField.setText(pm.volume.get());
|
||||||
});
|
});
|
||||||
|
|
||||||
amountTextField.focusedProperty().addListener((o, oldValue, newValue) -> {
|
amountTextField.focusedProperty().addListener((o, oldValue, newValue) -> {
|
||||||
presenter.onFocusOutAmountTextField(oldValue, newValue);
|
pm.onFocusOutAmountTextField(oldValue, newValue);
|
||||||
amountTextField.setText(presenter.amount.get());
|
amountTextField.setText(pm.amount.get());
|
||||||
});
|
});
|
||||||
|
|
||||||
priceTextField.focusedProperty().addListener((o, oldValue, newValue) -> {
|
priceTextField.focusedProperty().addListener((o, oldValue, newValue) -> {
|
||||||
presenter.onFocusOutPriceTextField(oldValue, newValue);
|
pm.onFocusOutPriceTextField(oldValue, newValue);
|
||||||
priceTextField.setText(presenter.price.get());
|
priceTextField.setText(pm.price.get());
|
||||||
});
|
});
|
||||||
|
|
||||||
minAmountTextField.focusedProperty().addListener((o, oldValue, newValue) -> {
|
minAmountTextField.focusedProperty().addListener((o, oldValue, newValue) -> {
|
||||||
presenter.onFocusOutMinAmountTextField(oldValue, newValue);
|
pm.onFocusOutMinAmountTextField(oldValue, newValue);
|
||||||
minAmountTextField.setText(presenter.minAmount.get());
|
minAmountTextField.setText(pm.minAmount.get());
|
||||||
});
|
});
|
||||||
|
|
||||||
presenter.needsInputValidation.addListener((o, oldValue, newValue) -> {
|
pm.needsInputValidation.addListener((o, oldValue, newValue) -> {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
amountTextField.reValidate();
|
amountTextField.reValidate();
|
||||||
minAmountTextField.reValidate();
|
minAmountTextField.reValidate();
|
||||||
|
@ -186,67 +190,67 @@ public class CreateOfferCodeBehind extends CachedViewController {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
presenter.showWarningInvalidBtcDecimalPlaces.addListener((o, oldValue, newValue) -> {
|
pm.showWarningInvalidBtcDecimalPlaces.addListener((o, oldValue, newValue) -> {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
Popups.openWarningPopup("Warning", "The amount you have entered exceeds the number of allowed decimal" +
|
Popups.openWarningPopup("Warning", "The amount you have entered exceeds the number of allowed decimal" +
|
||||||
" places.\nThe amount has been adjusted to 4 decimal places.");
|
" places.\nThe amount has been adjusted to 4 decimal places.");
|
||||||
presenter.showWarningInvalidBtcDecimalPlaces.set(false);
|
pm.showWarningInvalidBtcDecimalPlaces.set(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
presenter.showWarningInvalidFiatDecimalPlaces.addListener((o, oldValue, newValue) -> {
|
pm.showWarningInvalidFiatDecimalPlaces.addListener((o, oldValue, newValue) -> {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
Popups.openWarningPopup("Warning", "The amount you have entered exceeds the number of allowed decimal" +
|
Popups.openWarningPopup("Warning", "The amount you have entered exceeds the number of allowed decimal" +
|
||||||
" places.\nThe amount has been adjusted to 2 decimal places.");
|
" places.\nThe amount has been adjusted to 2 decimal places.");
|
||||||
presenter.showWarningInvalidFiatDecimalPlaces.set(false);
|
pm.showWarningInvalidFiatDecimalPlaces.set(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
presenter.showWarningInvalidBtcFractions.addListener((o, oldValue, newValue) -> {
|
pm.showWarningInvalidBtcFractions.addListener((o, oldValue, newValue) -> {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
Popups.openWarningPopup("Warning", "The total volume you have entered leads to invalid fractional " +
|
Popups.openWarningPopup("Warning", "The total volume you have entered leads to invalid fractional " +
|
||||||
"Bitcoin amounts.\nThe amount has been adjusted and a new total volume be calculated from it.");
|
"Bitcoin amounts.\nThe amount has been adjusted and a new total volume be calculated from it.");
|
||||||
presenter.showWarningInvalidBtcFractions.set(false);
|
pm.showWarningInvalidBtcFractions.set(false);
|
||||||
volumeTextField.setText(presenter.volume.get());
|
volumeTextField.setText(pm.volume.get());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
presenter.requestPlaceOfferFailed.addListener((o, oldValue, newValue) -> {
|
pm.requestPlaceOfferFailed.addListener((o, oldValue, newValue) -> {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
Popups.openErrorPopup("Error", "An error occurred when placing the offer.\n" +
|
Popups.openErrorPopup("Error", "An error occurred when placing the offer.\n" +
|
||||||
presenter.requestPlaceOfferErrorMessage);
|
pm.requestPlaceOfferErrorMessage);
|
||||||
presenter.requestPlaceOfferFailed.set(false);
|
pm.requestPlaceOfferFailed.set(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupBindings() {
|
private void setupBindings() {
|
||||||
buyLabel.textProperty().bind(presenter.directionLabel);
|
buyLabel.textProperty().bind(pm.directionLabel);
|
||||||
amountTextField.textProperty().bindBidirectional(presenter.amount);
|
amountTextField.textProperty().bindBidirectional(pm.amount);
|
||||||
priceTextField.textProperty().bindBidirectional(presenter.price);
|
priceTextField.textProperty().bindBidirectional(pm.price);
|
||||||
volumeTextField.textProperty().bindBidirectional(presenter.volume);
|
volumeTextField.textProperty().bindBidirectional(pm.volume);
|
||||||
|
|
||||||
minAmountTextField.textProperty().bindBidirectional(presenter.minAmount);
|
minAmountTextField.textProperty().bindBidirectional(pm.minAmount);
|
||||||
collateralLabel.textProperty().bind(presenter.collateralLabel);
|
collateralLabel.textProperty().bind(pm.collateralLabel);
|
||||||
collateralTextField.textProperty().bind(presenter.collateral);
|
collateralTextField.textProperty().bind(pm.collateral);
|
||||||
totalToPayTextField.textProperty().bind(presenter.totalToPay);
|
totalToPayTextField.textProperty().bind(pm.totalToPay);
|
||||||
|
|
||||||
addressTextField.amountAsCoinProperty().bind(presenter.totalToPayAsCoin);
|
addressTextField.amountAsCoinProperty().bind(pm.totalToPayAsCoin);
|
||||||
addressTextField.paymentLabelProperty().bind(presenter.paymentLabel);
|
addressTextField.paymentLabelProperty().bind(pm.paymentLabel);
|
||||||
addressTextField.addressProperty().bind(presenter.addressAsString);
|
addressTextField.addressProperty().bind(pm.addressAsString);
|
||||||
|
|
||||||
bankAccountTypeTextField.textProperty().bind(presenter.bankAccountType);
|
bankAccountTypeTextField.textProperty().bind(pm.bankAccountType);
|
||||||
bankAccountCurrencyTextField.textProperty().bind(presenter.bankAccountCurrency);
|
bankAccountCurrencyTextField.textProperty().bind(pm.bankAccountCurrency);
|
||||||
bankAccountCountyTextField.textProperty().bind(presenter.bankAccountCounty);
|
bankAccountCountyTextField.textProperty().bind(pm.bankAccountCounty);
|
||||||
|
|
||||||
acceptedCountriesTextField.textProperty().bind(presenter.acceptedCountries);
|
acceptedCountriesTextField.textProperty().bind(pm.acceptedCountries);
|
||||||
acceptedLanguagesTextField.textProperty().bind(presenter.acceptedLanguages);
|
acceptedLanguagesTextField.textProperty().bind(pm.acceptedLanguages);
|
||||||
totalFeesTextField.textProperty().bind(presenter.totalFees);
|
totalFeesTextField.textProperty().bind(pm.totalFees);
|
||||||
transactionIdTextField.textProperty().bind(presenter.transactionId);
|
transactionIdTextField.textProperty().bind(pm.transactionId);
|
||||||
|
|
||||||
placeOfferButton.visibleProperty().bind(presenter.isPlaceOfferButtonVisible);
|
placeOfferButton.visibleProperty().bind(pm.isPlaceOfferButtonVisible);
|
||||||
placeOfferButton.disableProperty().bind(presenter.isPlaceOfferButtonDisabled);
|
placeOfferButton.disableProperty().bind(pm.isPlaceOfferButtonDisabled);
|
||||||
closeButton.visibleProperty().bind(presenter.isCloseButtonVisible);
|
closeButton.visibleProperty().bind(pm.isCloseButtonVisible);
|
||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
/* progressIndicator.visibleProperty().bind(viewModel.isOfferPlacedScreen);
|
/* progressIndicator.visibleProperty().bind(viewModel.isOfferPlacedScreen);
|
||||||
|
@ -280,8 +284,8 @@ public class CreateOfferCodeBehind extends CachedViewController {
|
||||||
|
|
||||||
ValidationHelper.setupMinAmountInRangeOfAmountValidation(amountTextField,
|
ValidationHelper.setupMinAmountInRangeOfAmountValidation(amountTextField,
|
||||||
minAmountTextField,
|
minAmountTextField,
|
||||||
presenter.amount,
|
pm.amount,
|
||||||
presenter.minAmount,
|
pm.minAmount,
|
||||||
amountValidator,
|
amountValidator,
|
||||||
minAmountValidator);
|
minAmountValidator);
|
||||||
}
|
}
|
|
@ -43,18 +43,18 @@ import static io.bitsquare.gui.util.BSFormatter.*;
|
||||||
import static javafx.beans.binding.Bindings.createStringBinding;
|
import static javafx.beans.binding.Bindings.createStringBinding;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Presenter:
|
* Presentation model:
|
||||||
* Knows Model, does not know the View (CodeBehind)
|
* Knows Model, does not know the View (CodeBehind)
|
||||||
* <p>
|
* <p>
|
||||||
* - Holds data and state of the View (formatting,...)
|
* - Holds data and state of the View (formatting,...)
|
||||||
* - Receive user input via method calls from CodeBehind.
|
* - Receive user input via method calls from CodeBehind.
|
||||||
* - Validates input, applies business logic and converts input to Model.
|
* - Validates input, applies business logic and converts input to Model.
|
||||||
* - Format model data to properties used for binding from the view.
|
* - Format model data to properties used for binding from the view (The view setup the bindings).
|
||||||
* - Listen to updates from Model via Bindings.
|
* - Listen to updates from Model via Bindings (The PM setup the bindings to the model).
|
||||||
* - Is testable
|
* - Can be used for unit testing
|
||||||
*/
|
*/
|
||||||
class CreateOfferPresenter {
|
class CreateOfferPM {
|
||||||
private static final Logger log = LoggerFactory.getLogger(CreateOfferPresenter.class);
|
private static final Logger log = LoggerFactory.getLogger(CreateOfferPM.class);
|
||||||
|
|
||||||
private CreateOfferModel model;
|
private CreateOfferModel model;
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ class CreateOfferPresenter {
|
||||||
// Constructor
|
// Constructor
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
CreateOfferPresenter(CreateOfferModel model) {
|
CreateOfferPM(CreateOfferModel model) {
|
||||||
this.model = model;
|
this.model = model;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import javafx.scene.control.*?>
|
<?import javafx.scene.control.*?>
|
||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.*?>
|
||||||
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.trade.createoffer.CreateOfferCodeBehind"
|
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.trade.createoffer.CreateOfferCB"
|
||||||
prefHeight="500" prefWidth="800" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0"
|
prefHeight="500" prefWidth="800" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0"
|
||||||
AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0"
|
AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0"
|
||||||
xmlns:fx="http://javafx.com/fxml">
|
xmlns:fx="http://javafx.com/fxml">
|
||||||
|
|
|
@ -25,7 +25,7 @@ import io.bitsquare.gui.MainController;
|
||||||
import io.bitsquare.gui.NavigationItem;
|
import io.bitsquare.gui.NavigationItem;
|
||||||
import io.bitsquare.gui.ViewController;
|
import io.bitsquare.gui.ViewController;
|
||||||
import io.bitsquare.gui.components.Popups;
|
import io.bitsquare.gui.components.Popups;
|
||||||
import io.bitsquare.gui.trade.createoffer.CreateOfferCodeBehind;
|
import io.bitsquare.gui.trade.createoffer.CreateOfferCB;
|
||||||
import io.bitsquare.gui.trade.takeoffer.TakeOfferController;
|
import io.bitsquare.gui.trade.takeoffer.TakeOfferController;
|
||||||
import io.bitsquare.gui.util.BSFormatter;
|
import io.bitsquare.gui.util.BSFormatter;
|
||||||
import io.bitsquare.gui.util.ImageUtil;
|
import io.bitsquare.gui.util.ImageUtil;
|
||||||
|
@ -229,7 +229,7 @@ public class OrderBookController extends CachedViewController {
|
||||||
createOfferButton.setDisable(true);
|
createOfferButton.setDisable(true);
|
||||||
ViewController nextController = parentController.loadViewAndGetChildController(NavigationItem.CREATE_OFFER);
|
ViewController nextController = parentController.loadViewAndGetChildController(NavigationItem.CREATE_OFFER);
|
||||||
if (nextController != null)
|
if (nextController != null)
|
||||||
((CreateOfferCodeBehind) nextController).setOrderBookFilter(orderBookFilter);
|
((CreateOfferCB) nextController).setOrderBookFilter(orderBookFilter);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
showRegistrationDialog();
|
showRegistrationDialog();
|
||||||
|
|
|
@ -70,6 +70,7 @@ public class BSFormatter {
|
||||||
|
|
||||||
static {
|
static {
|
||||||
//useMilliBitFormat(true);
|
//useMilliBitFormat(true);
|
||||||
|
setLocale(Locale.US);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,6 @@
|
||||||
|
|
||||||
package io.bitsquare.msg;
|
package io.bitsquare.msg;
|
||||||
|
|
||||||
import io.bitsquare.BitSquare;
|
|
||||||
import io.bitsquare.util.AppDirectoryUtil;
|
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
@ -61,6 +58,8 @@ import org.jetbrains.annotations.NotNull;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import lighthouse.files.AppDirectory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The fully bootstrapped P2PNode which is responsible himself for his availability in the messaging system. It saves
|
* The fully bootstrapped P2PNode which is responsible himself for his availability in the messaging system. It saves
|
||||||
* for instance the IP address periodically.
|
* for instance the IP address periodically.
|
||||||
|
@ -70,12 +69,8 @@ import org.slf4j.LoggerFactory;
|
||||||
public class P2PNode {
|
public class P2PNode {
|
||||||
private static final Logger log = LoggerFactory.getLogger(P2PNode.class);
|
private static final Logger log = LoggerFactory.getLogger(P2PNode.class);
|
||||||
|
|
||||||
private Thread bootstrapToLocalhostThread;
|
|
||||||
private Thread bootstrapToServerThread;
|
|
||||||
|
|
||||||
private KeyPair keyPair;
|
private KeyPair keyPair;
|
||||||
private final Boolean useDiskStorage;
|
private final Boolean useDiskStorage;
|
||||||
private final SeedNodeAddress.StaticSeedNodeAddresses defaultStaticSeedNodeAddresses;
|
|
||||||
private MessageBroker messageBroker;
|
private MessageBroker messageBroker;
|
||||||
|
|
||||||
private PeerAddress storedPeerAddress;
|
private PeerAddress storedPeerAddress;
|
||||||
|
@ -90,11 +85,9 @@ public class P2PNode {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public P2PNode(BootstrappedPeerFactory bootstrappedPeerFactory,
|
public P2PNode(BootstrappedPeerFactory bootstrappedPeerFactory,
|
||||||
@Named("useDiskStorage") Boolean useDiskStorage,
|
@Named("useDiskStorage") Boolean useDiskStorage) {
|
||||||
@Named("defaultSeedNode") SeedNodeAddress.StaticSeedNodeAddresses defaultStaticSeedNodeAddresses) {
|
|
||||||
this.bootstrappedPeerFactory = bootstrappedPeerFactory;
|
this.bootstrappedPeerFactory = bootstrappedPeerFactory;
|
||||||
this.useDiskStorage = useDiskStorage;
|
this.useDiskStorage = useDiskStorage;
|
||||||
this.defaultStaticSeedNodeAddresses = defaultStaticSeedNodeAddresses;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// for unit testing
|
// for unit testing
|
||||||
|
@ -105,7 +98,6 @@ public class P2PNode {
|
||||||
messageBroker = (message, peerAddress) -> {
|
messageBroker = (message, peerAddress) -> {
|
||||||
};
|
};
|
||||||
useDiskStorage = false;
|
useDiskStorage = false;
|
||||||
defaultStaticSeedNodeAddresses = SeedNodeAddress.StaticSeedNodeAddresses.LOCALHOST;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -300,20 +292,13 @@ public class P2PNode {
|
||||||
|
|
||||||
private void useDiscStorage(boolean useDiscStorage) {
|
private void useDiscStorage(boolean useDiscStorage) {
|
||||||
if (useDiscStorage) {
|
if (useDiscStorage) {
|
||||||
try {
|
File path = new File(AppDirectory.dir().toFile() + "/tomP2P");
|
||||||
|
if (!path.exists()) {
|
||||||
File path = new File(AppDirectoryUtil.getStorageDirectory().getCanonicalPath() + "/" + BitSquare
|
boolean created = path.mkdir();
|
||||||
.getAppName() + "_tomP2P");
|
if (!created)
|
||||||
if (!path.exists()) {
|
throw new RuntimeException("Could not create the directory '" + path + "'");
|
||||||
boolean created = path.mkdir();
|
|
||||||
if (!created)
|
|
||||||
throw new RuntimeException("Could not create the directory '" + path + "'");
|
|
||||||
}
|
|
||||||
storage = new StorageDisk(Number160.ZERO, path, new DSASignatureFactory());
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
storage = new StorageDisk(Number160.ZERO, path, new DSASignatureFactory());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
storage = new StorageMemory();
|
storage = new StorageMemory();
|
||||||
|
|
|
@ -1,98 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 io.bitsquare.util;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class AppDirectoryUtil {
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(AppDirectoryUtil.class);
|
|
||||||
private static File storageDirectory;
|
|
||||||
|
|
||||||
static {
|
|
||||||
useApplicationDirectory();
|
|
||||||
log.info("Default application data directory = " + storageDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static File getStorageDirectory() {
|
|
||||||
return storageDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setStorageDirectory(File directory) {
|
|
||||||
storageDirectory = directory;
|
|
||||||
log.info("User defined application data directory = " + directory);
|
|
||||||
|
|
||||||
createDirIfNotExists();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void useApplicationDirectory() {
|
|
||||||
setStorageDirectory(getApplicationDirectory());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void useSystemApplicationDataDirectory() {
|
|
||||||
setStorageDirectory(getSystemApplicationDataDirectory());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static File getApplicationDirectory() {
|
|
||||||
File executionRoot =
|
|
||||||
new File(AppDirectoryUtil.class.getProtectionDomain().getCodeSource().getLocation().getFile());
|
|
||||||
try {
|
|
||||||
log.trace("executionRoot " + executionRoot.getCanonicalPath());
|
|
||||||
|
|
||||||
// check if it is packed into a mac app (e.g.: "$HOME/Desktop/bitsquare.app/Contents/Java/bitsquare.jar")
|
|
||||||
if (executionRoot.getCanonicalPath().endsWith(".app/Contents/Java/bitsquare.jar") &&
|
|
||||||
System.getProperty("os.name").startsWith("Mac"))
|
|
||||||
return executionRoot.getParentFile().getParentFile().getParentFile().getParentFile();
|
|
||||||
else if (executionRoot.getCanonicalPath().endsWith(File.separator + "target" + File.separator + "classes"))
|
|
||||||
return executionRoot.getParentFile(); // dev e.g.:
|
|
||||||
// $HOME/Documents/_intellij/bitsquare/target/classes -> use target as root
|
|
||||||
else if (executionRoot.getCanonicalPath().endsWith(File.separator + "bitsquare.jar"))
|
|
||||||
return executionRoot.getParentFile(); // dev with jar e.g.:
|
|
||||||
// $HOME/Documents/_intellij/bitsquare/out/artifacts/bitsquare2/bitsquare.jar -> use target as root
|
|
||||||
else
|
|
||||||
return executionRoot;
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static File getSystemApplicationDataDirectory() {
|
|
||||||
String osName = System.getProperty("os.name");
|
|
||||||
if (osName != null && osName.startsWith("Windows"))
|
|
||||||
return new File(System.getenv("APPDATA") + File.separator + "BitSquare");
|
|
||||||
else if (osName != null && osName.startsWith("Mac"))
|
|
||||||
return new File(System.getProperty("user.home") + "/Library/Application Support/BitSquare");
|
|
||||||
else
|
|
||||||
return new File(System.getProperty("user.home") + File.separator + "BitSquare");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void createDirIfNotExists() {
|
|
||||||
if (!storageDirectory.exists()) {
|
|
||||||
boolean created = storageDirectory.mkdir();
|
|
||||||
if (!created)
|
|
||||||
throw new RuntimeException(
|
|
||||||
"Could not create the application data directory of '" + storageDirectory + "'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -25,15 +25,17 @@ import java.io.IOException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import lighthouse.files.AppDirectory;
|
||||||
|
|
||||||
public class FileUtil {
|
public class FileUtil {
|
||||||
private static final Logger log = LoggerFactory.getLogger(FileUtil.class);
|
private static final Logger log = LoggerFactory.getLogger(FileUtil.class);
|
||||||
|
|
||||||
public static File getFile(String name, String suffix) {
|
public static File getFile(String name, String suffix) {
|
||||||
return new File(AppDirectoryUtil.getStorageDirectory(), name + "." + suffix);
|
return new File(AppDirectory.dir().toFile(), name + "." + suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getTempFile(String prefix) throws IOException {
|
public static File getTempFile(String prefix) throws IOException {
|
||||||
return File.createTempFile("temp_" + prefix, null, AppDirectoryUtil.getStorageDirectory());
|
return File.createTempFile("temp_" + prefix, null, AppDirectory.dir().toFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void writeTempFileToFile(File tempFile, File file) throws IOException {
|
public static void writeTempFileToFile(File tempFile, File file) throws IOException {
|
||||||
|
|
56
src/main/java/lighthouse/files/AppDirectory.java
Normal file
56
src/main/java/lighthouse/files/AppDirectory.java
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
package lighthouse.files;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
// TODO update to open source file when its released
|
||||||
|
|
||||||
|
/** Manages the directory where the app stores all its files. */
|
||||||
|
public class AppDirectory {
|
||||||
|
public static Path getUserDataDir() {
|
||||||
|
String os = System.getProperty("os.name").toLowerCase();
|
||||||
|
if (os.contains("win")) {
|
||||||
|
return Paths.get(System.getenv("APPDATA"));
|
||||||
|
} else if (os.contains("mac")) {
|
||||||
|
return Paths.get(System.getProperty("user.home"), "Library", "Application Support");
|
||||||
|
} else {
|
||||||
|
// Linux and other similar systems, we hope (not Android).
|
||||||
|
return Paths.get(System.getProperty("user.home"), ".local", "share");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Path getUserDataDir(String appName) {
|
||||||
|
return getUserDataDir().resolve(appName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Path initAppDir(String appName) throws IOException {
|
||||||
|
AppDirectory.appName = appName;
|
||||||
|
|
||||||
|
Path dir = dir();
|
||||||
|
if (!Files.exists(dir))
|
||||||
|
Files.createDirectory(dir);
|
||||||
|
else if (!Files.isWritable(dir))
|
||||||
|
throw new IOException("App directory is not writeable");
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String appName;
|
||||||
|
|
||||||
|
private static Path dir;
|
||||||
|
|
||||||
|
public static Path dir() {
|
||||||
|
if (dir == null)
|
||||||
|
return getUserDataDir(appName);
|
||||||
|
else
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void overrideAppDir(Path newDir) {
|
||||||
|
dir = checkNotNull(newDir);
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,24 +31,24 @@
|
||||||
<logger name="io.netty.channel" level="WARN"/>
|
<logger name="io.netty.channel" level="WARN"/>
|
||||||
<logger name="io.netty.buffer" level="WARN"/>
|
<logger name="io.netty.buffer" level="WARN"/>
|
||||||
|
|
||||||
<!--
|
|
||||||
<logger name="io.bitsquare.gui.ViewController" level="OFF"/>
|
<logger name="io.bitsquare.gui.ViewController" level="OFF"/>
|
||||||
<logger name="io.bitsquare.gui.CachedViewController" level="OFF"/>
|
<logger name="io.bitsquare.gui.CachedViewController" level="OFF"/>
|
||||||
<logger name="io.bitsquare.gui.util.Profiler" level="OFF"/>
|
<logger name="io.bitsquare.gui.util.Profiler" level="OFF"/>
|
||||||
|
<!--
|
||||||
|
|
||||||
<logger name="com.google.bitcoin.core.Wallet" level="OFF"/>
|
<logger name="com.google.bitcoin.core.Wallet" level="OFF"/>
|
||||||
<logger name="com.google.bitcoin.core.MemoryPool" level="OFF"/>
|
<logger name="com.google.bitcoin.core.MemoryPool" level="OFF"/>
|
||||||
<logger name="com.google.bitcoin.net.discovery.DnsDiscovery" level="OFF"/>
|
<logger name="com.google.bitcoin.net.discovery.DnsDiscovery" level="OFF"/>
|
||||||
|
|
||||||
<logger name="com.google.bitcoin.core.DownloadListener" level="OFF"/>
|
<logger name="com.google.bitcoin.core.DownloadListener" level="OFF"/>
|
||||||
<logger name="com.google.bitcoin.core.TransactionOutput" level="OFF"/>
|
<logger name="com.google.bitcoin.core.TransactionOutput" level="OFF"/>
|
||||||
<logger name="com.google.bitcoin.core.BitcoinSerializer" level="OFF"/>
|
<logger name="com.google.bitcoin.core.BitcoinSerializer" level="OFF"/>
|
||||||
<logger name="com.google.bitcoin.core.Peer" level="OFF"/>
|
<logger name="com.google.bitcoin.core.Peer" level="OFF"/>
|
||||||
<logger name="com.google.bitcoin.core.PeerGroup" level="OFF"/>
|
<logger name="com.google.bitcoin.core.PeerGroup" level="OFF"/>
|
||||||
<logger name="com.google.bitcoin.core.PeerSocketHandler" level="OFF"/>
|
<logger name="com.google.bitcoin.core.PeerSocketHandler" level="OFF"/>
|
||||||
<logger name="com.google.bitcoin.net.NioClientManager" level="OFF"/>
|
<logger name="com.google.bitcoin.net.NioClientManager" level="OFF"/>
|
||||||
<logger name="com.google.bitcoin.net.ConnectionHandler" level="OFF"/>
|
<logger name="com.google.bitcoin.net.ConnectionHandler" level="OFF"/>
|
||||||
-->
|
-->
|
||||||
|
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
package io.bitsquare;
|
package io.bitsquare;
|
||||||
|
|
||||||
import io.bitsquare.btc.RestrictionsTest;
|
import io.bitsquare.btc.RestrictionsTest;
|
||||||
import io.bitsquare.gui.trade.createoffer.CreateOfferPresenterTest;
|
import io.bitsquare.gui.trade.createoffer.CreateOfferPMTest;
|
||||||
import io.bitsquare.gui.util.BSFormatterTest;
|
import io.bitsquare.gui.util.BSFormatterTest;
|
||||||
import io.bitsquare.gui.util.BitSquareConverterTest;
|
import io.bitsquare.gui.util.BitSquareConverterTest;
|
||||||
import io.bitsquare.gui.util.BitSquareNumberValidatorTest;
|
import io.bitsquare.gui.util.BitSquareNumberValidatorTest;
|
||||||
|
@ -36,7 +36,7 @@ import org.junit.runners.Suite;
|
||||||
P2PNodeTest.class,
|
P2PNodeTest.class,
|
||||||
FiatValidatorTest.class,
|
FiatValidatorTest.class,
|
||||||
RestrictionsTest.class,
|
RestrictionsTest.class,
|
||||||
CreateOfferPresenterTest.class,
|
CreateOfferPMTest.class,
|
||||||
BSFormatterTest.class
|
BSFormatterTest.class
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -33,8 +33,8 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
public class CreateOfferPresenterTest {
|
public class CreateOfferPMTest {
|
||||||
private static final Logger log = LoggerFactory.getLogger(CreateOfferPresenterTest.class);
|
private static final Logger log = LoggerFactory.getLogger(CreateOfferPMTest.class);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBindings() {
|
public void testBindings() {
|
||||||
|
@ -43,7 +43,7 @@ public class CreateOfferPresenterTest {
|
||||||
BSFormatter.setLocale(Locale.US);
|
BSFormatter.setLocale(Locale.US);
|
||||||
BSFormatter.setFiatCurrencyCode("USD");
|
BSFormatter.setFiatCurrencyCode("USD");
|
||||||
|
|
||||||
CreateOfferPresenter presenter = new CreateOfferPresenter(model);
|
CreateOfferPM presenter = new CreateOfferPM(model);
|
||||||
presenter.onViewInitialized();
|
presenter.onViewInitialized();
|
||||||
|
|
||||||
model.collateralAsLong.set(100);
|
model.collateralAsLong.set(100);
|
Loading…
Add table
Add a link
Reference in a new issue