mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-07-27 00:45:23 -04:00
Add test app for DHT storage and loading
This commit is contained in:
parent
32fb720d2b
commit
f31e9b8892
6 changed files with 386 additions and 3 deletions
|
@ -23,7 +23,7 @@ import io.bitsquare.trade.Offer;
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
|
||||||
class OrderBookListItem {
|
public class OrderBookListItem {
|
||||||
private final Offer offer;
|
private final Offer offer;
|
||||||
private final ObjectProperty<Country> bankAccountCountry = new SimpleObjectProperty<>();
|
private final ObjectProperty<Country> bankAccountCountry = new SimpleObjectProperty<>();
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ class OrderBookListItem {
|
||||||
// Constructor
|
// Constructor
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
OrderBookListItem(Offer offer, Country bankAccountCountry) {
|
public OrderBookListItem(Offer offer, Country bankAccountCountry) {
|
||||||
this.offer = offer;
|
this.offer = offer;
|
||||||
setBankAccountCountry(bankAccountCountry);
|
setBankAccountCountry(bankAccountCountry);
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ class OrderBookListItem {
|
||||||
// Getters
|
// Getters
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Offer getOffer() {
|
public Offer getOffer() {
|
||||||
return offer;
|
return offer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,10 @@ import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
import javafx.beans.property.StringProperty;
|
||||||
|
|
||||||
import net.tomp2p.connection.Ports;
|
import net.tomp2p.connection.Ports;
|
||||||
import net.tomp2p.dht.PeerBuilderDHT;
|
import net.tomp2p.dht.PeerBuilderDHT;
|
||||||
import net.tomp2p.dht.PeerDHT;
|
import net.tomp2p.dht.PeerDHT;
|
||||||
|
@ -76,6 +80,7 @@ public class BootstrappedPeerFactory {
|
||||||
private final Persistence persistence;
|
private final Persistence persistence;
|
||||||
|
|
||||||
private final SettableFuture<PeerDHT> settableFuture = SettableFuture.create();
|
private final SettableFuture<PeerDHT> settableFuture = SettableFuture.create();
|
||||||
|
public final StringProperty connectionState = new SimpleStringProperty();
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -194,6 +199,9 @@ public class BootstrappedPeerFactory {
|
||||||
log.debug("We are not behind a NAT and reachable to other peers: My address visible to the " +
|
log.debug("We are not behind a NAT and reachable to other peers: My address visible to the " +
|
||||||
"outside is " + futureDiscover.peerAddress());
|
"outside is " + futureDiscover.peerAddress());
|
||||||
requestBootstrapPeerMap();
|
requestBootstrapPeerMap();
|
||||||
|
setConnectionState("We are not behind a NAT and reachable to other peers: My address visible to " +
|
||||||
|
"the " +
|
||||||
|
"outside is " + futureDiscover.peerAddress());
|
||||||
settableFuture.set(peerDHT);
|
settableFuture.set(peerDHT);
|
||||||
|
|
||||||
persistence.write(ref, "lastSuccessfulBootstrap", "default");
|
persistence.write(ref, "lastSuccessfulBootstrap", "default");
|
||||||
|
@ -203,6 +211,10 @@ public class BootstrappedPeerFactory {
|
||||||
log.warn("We are probably behind a NAT and not reachable to other peers. We try port forwarding " +
|
log.warn("We are probably behind a NAT and not reachable to other peers. We try port forwarding " +
|
||||||
"as next step.");
|
"as next step.");
|
||||||
|
|
||||||
|
setConnectionState("We are probably behind a NAT and not reachable to other peers. We try port " +
|
||||||
|
"forwarding " +
|
||||||
|
"as next step.");
|
||||||
|
|
||||||
bootstrapWithPortForwarding(peerDHT, futureDiscover);
|
bootstrapWithPortForwarding(peerDHT, futureDiscover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,6 +242,8 @@ public class BootstrappedPeerFactory {
|
||||||
log.debug("Port forwarding was successful. My address visible to the outside is " +
|
log.debug("Port forwarding was successful. My address visible to the outside is " +
|
||||||
futureNAT.peerAddress());
|
futureNAT.peerAddress());
|
||||||
requestBootstrapPeerMap();
|
requestBootstrapPeerMap();
|
||||||
|
setConnectionState("Port forwarding was successful. My address visible to the outside is " +
|
||||||
|
futureNAT.peerAddress());
|
||||||
settableFuture.set(peerDHT);
|
settableFuture.set(peerDHT);
|
||||||
|
|
||||||
persistence.write(ref, "lastSuccessfulBootstrap", "portForwarding");
|
persistence.write(ref, "lastSuccessfulBootstrap", "portForwarding");
|
||||||
|
@ -238,6 +252,8 @@ public class BootstrappedPeerFactory {
|
||||||
log.warn("Port forwarding has failed. Reason: " + futureNAT.failedReason());
|
log.warn("Port forwarding has failed. Reason: " + futureNAT.failedReason());
|
||||||
log.warn("We try to use a relay as next step.");
|
log.warn("We try to use a relay as next step.");
|
||||||
|
|
||||||
|
setConnectionState("We try to use a relay as next step.");
|
||||||
|
|
||||||
bootstrapWithRelay(peerDHT, nodeBehindNat);
|
bootstrapWithRelay(peerDHT, nodeBehindNat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,6 +340,8 @@ public class BootstrappedPeerFactory {
|
||||||
if (future.isSuccess()) {
|
if (future.isSuccess()) {
|
||||||
log.debug("Final bootstrap was successful. bootstrapTo = " + futureBootstrap2.bootstrapTo());
|
log.debug("Final bootstrap was successful. bootstrapTo = " + futureBootstrap2.bootstrapTo());
|
||||||
requestBootstrapPeerMap();
|
requestBootstrapPeerMap();
|
||||||
|
setConnectionState("Final bootstrap was successful. bootstrapTo = " + futureBootstrap2
|
||||||
|
.bootstrapTo());
|
||||||
settableFuture.set(peerDHT);
|
settableFuture.set(peerDHT);
|
||||||
|
|
||||||
persistence.write(ref, "lastSuccessfulBootstrap", "relay");
|
persistence.write(ref, "lastSuccessfulBootstrap", "relay");
|
||||||
|
@ -348,4 +366,8 @@ public class BootstrappedPeerFactory {
|
||||||
private void requestBootstrapPeerMap() {
|
private void requestBootstrapPeerMap() {
|
||||||
log.debug("getBootstrapPeerMap");
|
log.debug("getBootstrapPeerMap");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setConnectionState(String state) {
|
||||||
|
Platform.runLater(() -> connectionState.set(state));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,6 +177,7 @@ public class MessageFacade implements MessageBroker {
|
||||||
try {
|
try {
|
||||||
Object offerDataObject = offerData.object();
|
Object offerDataObject = offerData.object();
|
||||||
if (offerDataObject instanceof Offer) {
|
if (offerDataObject instanceof Offer) {
|
||||||
|
log.error("Added offer to DHT with ID: " + ((Offer) offerDataObject).getId());
|
||||||
listener.onOfferAdded((Offer) offerDataObject);
|
listener.onOfferAdded((Offer) offerDataObject);
|
||||||
}
|
}
|
||||||
} catch (ClassNotFoundException | IOException e) {
|
} catch (ClassNotFoundException | IOException e) {
|
||||||
|
|
182
src/test/java/io/bitsquare/msg/dhttest/DHTTestController.java
Normal file
182
src/test/java/io/bitsquare/msg/dhttest/DHTTestController.java
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
/*
|
||||||
|
* 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.msg.dhttest;
|
||||||
|
|
||||||
|
import io.bitsquare.bank.BankAccountType;
|
||||||
|
import io.bitsquare.gui.main.trade.orderbook.OrderBookListItem;
|
||||||
|
import io.bitsquare.locale.CountryUtil;
|
||||||
|
import io.bitsquare.msg.BootstrappedPeerFactory;
|
||||||
|
import io.bitsquare.msg.MessageFacade;
|
||||||
|
import io.bitsquare.msg.listeners.AddOfferListener;
|
||||||
|
import io.bitsquare.msg.listeners.BootstrapListener;
|
||||||
|
import io.bitsquare.msg.listeners.OrderBookListener;
|
||||||
|
import io.bitsquare.trade.Direction;
|
||||||
|
import io.bitsquare.trade.Offer;
|
||||||
|
import io.bitsquare.user.User;
|
||||||
|
|
||||||
|
import org.bitcoinj.core.Coin;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Currency;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.fxml.Initializable;
|
||||||
|
import javafx.scene.control.*;
|
||||||
|
import javafx.util.Callback;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class DHTTestController implements Initializable {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(DHTTestController.class);
|
||||||
|
|
||||||
|
private final MessageFacade messageFacade;
|
||||||
|
private BootstrappedPeerFactory bootstrappedPeerFactory;
|
||||||
|
private User user;
|
||||||
|
private final ObservableList<OrderBookListItem> orderBookListItems = FXCollections.observableArrayList();
|
||||||
|
|
||||||
|
@FXML TableView table;
|
||||||
|
@FXML TextArea stateLabel;
|
||||||
|
@FXML TextField toSaveTextField;
|
||||||
|
@FXML TableColumn<OrderBookListItem, OrderBookListItem> idColumn;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private DHTTestController(MessageFacade messageFacade, User user,
|
||||||
|
BootstrappedPeerFactory bootstrappedPeerFactory) {
|
||||||
|
this.user = user;
|
||||||
|
this.messageFacade = messageFacade;
|
||||||
|
this.bootstrappedPeerFactory = bootstrappedPeerFactory;
|
||||||
|
|
||||||
|
user.applyPersistedUser(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(URL url, ResourceBundle rb) {
|
||||||
|
messageFacade.init(new BootstrapListener() {
|
||||||
|
@Override
|
||||||
|
public void onCompleted() {
|
||||||
|
onMessageFacadeInitialised();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailed(Throwable throwable) {
|
||||||
|
log.error(throwable.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
messageFacade.addOrderBookListener(new OrderBookListener() {
|
||||||
|
@Override
|
||||||
|
public void onOfferAdded(Offer offer) {
|
||||||
|
log.debug("offer added " + offer.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOffersReceived(List<Offer> offers) {
|
||||||
|
//TODO use deltas instead replacing the whole list
|
||||||
|
orderBookListItems.clear();
|
||||||
|
offers.stream().forEach(offer -> {
|
||||||
|
if (offer != null) {
|
||||||
|
orderBookListItems.add(new OrderBookListItem(offer, CountryUtil.getDefaultCountry()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOfferRemoved(Offer offer) {
|
||||||
|
orderBookListItems.removeIf(item -> item.getOffer().getId().equals(offer.getId()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setIDColumnCellFactory();
|
||||||
|
table.setItems(orderBookListItems);
|
||||||
|
|
||||||
|
bootstrappedPeerFactory.connectionState.addListener((ov, oldValue, newValue) -> {
|
||||||
|
stateLabel.setText(newValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void onAddOffer() {
|
||||||
|
Offer offer = new Offer(toSaveTextField.getText(),
|
||||||
|
user.getMessagePublicKey(),
|
||||||
|
Direction.BUY,
|
||||||
|
500,
|
||||||
|
Coin.COIN,
|
||||||
|
Coin.COIN,
|
||||||
|
BankAccountType.SEPA,
|
||||||
|
Currency.getInstance("EUR"),
|
||||||
|
CountryUtil.getDefaultCountry(),
|
||||||
|
"bankAccountUID",
|
||||||
|
new ArrayList<>(),
|
||||||
|
10,
|
||||||
|
new ArrayList<>(),
|
||||||
|
new ArrayList<>());
|
||||||
|
|
||||||
|
messageFacade.addOffer(offer, new AddOfferListener() {
|
||||||
|
@Override
|
||||||
|
public void onComplete() {
|
||||||
|
log.debug("onAddOffer onComplete");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailed(String reason, Throwable throwable) {
|
||||||
|
log.debug("onAddOffer onFailed");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onGetOffers() {
|
||||||
|
log.debug("onLoad");
|
||||||
|
messageFacade.getOffers("EUR");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onMessageFacadeInitialised() {
|
||||||
|
log.debug("onMessageFacadeInitialised");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setIDColumnCellFactory() {
|
||||||
|
idColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
||||||
|
idColumn.setCellFactory(
|
||||||
|
new Callback<TableColumn<OrderBookListItem, OrderBookListItem>, TableCell<OrderBookListItem,
|
||||||
|
OrderBookListItem>>() {
|
||||||
|
@Override
|
||||||
|
public TableCell<OrderBookListItem, OrderBookListItem> call(
|
||||||
|
TableColumn<OrderBookListItem, OrderBookListItem> column) {
|
||||||
|
return new TableCell<OrderBookListItem, OrderBookListItem>() {
|
||||||
|
@Override
|
||||||
|
public void updateItem(final OrderBookListItem item, boolean empty) {
|
||||||
|
super.updateItem(item, empty);
|
||||||
|
if (item != null && item.getOffer() != null && item.getOffer().getAmount() != null)
|
||||||
|
setText(item.getOffer().getId());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
102
src/test/java/io/bitsquare/msg/dhttest/DHTTestRunner.java
Normal file
102
src/test/java/io/bitsquare/msg/dhttest/DHTTestRunner.java
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* 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.msg.dhttest;
|
||||||
|
|
||||||
|
import io.bitsquare.di.BitSquareModule;
|
||||||
|
import io.bitsquare.util.ViewLoader;
|
||||||
|
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import javafx.application.Application;
|
||||||
|
import javafx.scene.*;
|
||||||
|
import javafx.scene.input.*;
|
||||||
|
import javafx.scene.layout.*;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class DHTTestRunner extends Application {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(DHTTestRunner.class);
|
||||||
|
private Scene scene;
|
||||||
|
private Parent view;
|
||||||
|
private Pane pane;
|
||||||
|
private boolean devTest = true;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
launch(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(Stage primaryStage) throws IOException {
|
||||||
|
Injector injector = Guice.createInjector(new BitSquareModule());
|
||||||
|
ViewLoader.setInjector(injector);
|
||||||
|
|
||||||
|
pane = new StackPane();
|
||||||
|
scene = new Scene(pane, 1000, 630);
|
||||||
|
scene.getAccelerators().put(KeyCombination.valueOf("Shortcut+S"), this::loadMainWindow);
|
||||||
|
loadMainWindow();
|
||||||
|
primaryStage.setScene(scene);
|
||||||
|
primaryStage.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadMainWindow() {
|
||||||
|
log.debug("re load");
|
||||||
|
pane.getChildren().removeAll();
|
||||||
|
ViewLoader loader = new ViewLoader(
|
||||||
|
getUrl("/io/bitsquare/msg/dhttest/DHTTestView.fxml")
|
||||||
|
, false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
view = loader.load();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
pane.getChildren().setAll(view);
|
||||||
|
refreshStylesheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshStylesheets() {
|
||||||
|
scene.getStylesheets().clear();
|
||||||
|
scene.getStylesheets().setAll(getUrl("/io/bitsquare/gui/bitsquare.css").toExternalForm());
|
||||||
|
}
|
||||||
|
|
||||||
|
private URL getUrl(String subPath) {
|
||||||
|
if (devTest) {
|
||||||
|
try {
|
||||||
|
// load from file system location to make a reload possible. makes dev process easier with hot reload
|
||||||
|
return new URL("file:///Users/mk/Documents/_intellij/bitsquare/src/test/java" + subPath);
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return getClass().getResource(subPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
76
src/test/java/io/bitsquare/msg/dhttest/DHTTestView.fxml
Normal file
76
src/test/java/io/bitsquare/msg/dhttest/DHTTestView.fxml
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ 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/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<?import javafx.geometry.Insets?>
|
||||||
|
<?import javafx.scene.control.*?>
|
||||||
|
<?import javafx.scene.layout.*?>
|
||||||
|
<AnchorPane fx:id="root" prefHeight="630.0" prefWidth="1000.0" style="-fx-background-color: f4f4f4;"
|
||||||
|
AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0"
|
||||||
|
AnchorPane.topAnchor="10.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
|
||||||
|
fx:controller="io.bitsquare.msg.dhttest.DHTTestController">
|
||||||
|
<children>
|
||||||
|
<GridPane fx:id="gridPane" hgap="5.0" vgap="5.0" AnchorPane.leftAnchor="10" AnchorPane.topAnchor="10">
|
||||||
|
<children>
|
||||||
|
<Label text="State:" GridPane.rowIndex="0">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets bottom="20.0"/>
|
||||||
|
</GridPane.margin>
|
||||||
|
</Label>
|
||||||
|
<TextArea fx:id="stateLabel" text="connecting..." editable="false" focusTraversable="false"
|
||||||
|
GridPane.rowIndex="0" prefWidth="750"
|
||||||
|
GridPane.columnIndex="1">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets bottom="20.0"/>
|
||||||
|
</GridPane.margin>
|
||||||
|
</TextArea>
|
||||||
|
|
||||||
|
<Label text="Store offer to DHT with ID:" GridPane.rowIndex="1"/>
|
||||||
|
<TextField fx:id="toSaveTextField" text="test value" GridPane.columnIndex="1"
|
||||||
|
GridPane.rowIndex="1" prefWidth="300"/>
|
||||||
|
|
||||||
|
<Button text="Save offer" onAction="#onAddOffer" GridPane.columnIndex="1"
|
||||||
|
GridPane.rowIndex="2">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets bottom="20.0"/>
|
||||||
|
</GridPane.margin>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
|
||||||
|
<Label text="Offerbook:" GridPane.rowIndex="3"/>
|
||||||
|
<Button text="Load offers" onAction="#onGetOffers" GridPane.columnIndex="1"
|
||||||
|
GridPane.rowIndex="3"/>
|
||||||
|
|
||||||
|
<TableView fx:id="table" GridPane.rowIndex="4" GridPane.columnIndex="0" GridPane.columnSpan="2"
|
||||||
|
prefHeight="300">
|
||||||
|
<columns>
|
||||||
|
<TableColumn text="ID" fx:id="idColumn" minWidth="130"/>
|
||||||
|
</columns>
|
||||||
|
</TableView>
|
||||||
|
|
||||||
|
</children>
|
||||||
|
|
||||||
|
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="200"/>
|
||||||
|
<ColumnConstraints hgrow="ALWAYS"/>
|
||||||
|
</columnConstraints>
|
||||||
|
|
||||||
|
</GridPane>
|
||||||
|
</children>
|
||||||
|
</AnchorPane>
|
Loading…
Add table
Add a link
Reference in a new issue