You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
i2p-zero/org.getmonero.i2p.zero.gui/src/org/getmonero/i2p/zero/gui/Controller.java

216 lines
7.8 KiB

package org.getmonero.i2p.zero.gui;
import javafx.application.Platform;
import javafx.beans.binding.DoubleBinding;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import org.getmonero.i2p.zero.RouterWrapper;
import static org.getmonero.i2p.zero.TunnelControl.Tunnel;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Properties;
public class Controller {
private RouterWrapper routerWrapper;
@FXML
private BorderPane rootBorderPane;
@FXML private Slider bandwidthSlider;
@FXML private Label maxBandwidthLabel;
@FXML private ImageView masterToggle;
@FXML private AnchorPane bandwidthDisabledOverlay;
@FXML private Tab bandwidthTab;
@FXML private Tab tunnelsTab;
@FXML private Tab helpTab;
@FXML private Label statusLabel;
@FXML private Button tunnelAddButton;
@FXML private Button tunnelRemoveButton;
@FXML private TableView<Tunnel> tunnelsTableView;
@FXML private TableColumn typeCol;
@FXML private TableColumn stateCol;
@FXML private TableColumn hostCol;
@FXML private TableColumn portCol;
@FXML private TableColumn i2PCol;
@FXML private Label bandwidthIn1s;
@FXML private Label bandwidthIn5m;
@FXML private Label bandwidthInAll;
@FXML private Label totalTransferredIn;
@FXML private Label bandwidthOut1s;
@FXML private Label bandwidthOut5m;
@FXML private Label bandwidthOutAll;
@FXML private Label totalTransferredOut;
DecimalFormat format2dp = new DecimalFormat("0.00");
private boolean masterState = true;
private final ObservableList<Tunnel> tunnelTableList = FXCollections.observableArrayList();
private Stage getStage() {
return (Stage) rootBorderPane.getScene().getWindow();
}
@FXML private void initialize() {
typeCol.setCellValueFactory(new PropertyValueFactory<Tunnel,String>("type"));
stateCol.setCellValueFactory(new PropertyValueFactory<Tunnel,String>("state"));
hostCol.setCellValueFactory(new PropertyValueFactory<Tunnel,String>("host"));
portCol.setCellValueFactory(new PropertyValueFactory<Tunnel,String>("port"));
i2PCol.setCellValueFactory(new PropertyValueFactory<Tunnel,String>("I2P"));
DoubleBinding usedWidth = typeCol.widthProperty().add(stateCol.widthProperty()).add(hostCol.widthProperty()).add(portCol.widthProperty());
i2PCol.prefWidthProperty().bind(tunnelsTableView.widthProperty().subtract(usedWidth).subtract(2));
tunnelsTableView.setItems(tunnelTableList);
tunnelsTableView.getSelectionModel().selectedItemProperty().addListener((observableValue, oldSelection, newSelection) -> {
if (newSelection == null) {
tunnelRemoveButton.setDisable(true);
}
else {
tunnelRemoveButton.setDisable(false);
}
});
tunnelRemoveButton.setOnAction(e->{
Tunnel t = tunnelsTableView.getSelectionModel().getSelectedItem();
getRouterWrapper().getTunnelControl().getTunnelList().removeTunnel(t);
t.destroy();
tunnelRemoveButton.setDisable(true);
});
tunnelAddButton.setOnAction(event->{
try {
Stage dialogStage = new Stage();
dialogStage.initModality(Modality.WINDOW_MODAL);
dialogStage.initOwner(getStage());
dialogStage.setResizable(false);
dialogStage.setTitle("New tunnel");
Scene dialogScene = new Scene(FXMLLoader.load(getClass().getResource("addTunnel.fxml")));
dialogScene.getStylesheets().add("org/getmonero/i2p/zero/gui/gui.css");
dialogStage.setScene(dialogScene);
dialogStage.show();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
EventHandler<Event> tabSelectionEventHandler = e->{
Stage stage = getStage();
if(bandwidthTab.isSelected()) {
stage.setWidth(360);
stage.setHeight(370);
}
else if(tunnelsTab.isSelected()) {
stage.setWidth(900);
}
};
bandwidthTab.setOnSelectionChanged(tabSelectionEventHandler);
tunnelsTab.setOnSelectionChanged(tabSelectionEventHandler);
helpTab.setOnSelectionChanged(tabSelectionEventHandler);
bandwidthSlider.valueProperty().addListener((observableValue, oldValue, newValue)-> {
maxBandwidthLabel.setText(String.format("%.1f", newValue.floatValue()) + " Mbps");
routerWrapper.debouncedUpdateBandwidthLimitKBPerSec((int) Math.round(1024d*newValue.doubleValue()/8d));
});
masterToggle.setOnMouseClicked(e->{
masterState = !masterState;
bandwidthDisabledOverlay.setVisible(!masterState);
if(masterState) {
masterToggle.setImage(new Image("org/getmonero/i2p/zero/gui/toggle-on.png"));
statusLabel.setVisible(true);
routerWrapper.start();
tunnelAddButton.setDisable(false);
}
else {
masterToggle.setImage(new Image("org/getmonero/i2p/zero/gui/toggle-off.png"));
statusLabel.setVisible(false);
routerWrapper.stop();
tunnelTableList.clear();
tunnelAddButton.setDisable(true);
}
});
startRouter();
new Thread(()->{
while(getRouterWrapper()==null || getRouterWrapper().getTunnelControl()==null) {
try { Thread.sleep(100); } catch (InterruptedException e) {}
}
var tunnelList = getRouterWrapper().getTunnelControl().getTunnelList();
tunnelList.addPropertyChangeListener(event->{
tunnelTableList.clear();
tunnelTableList.addAll((List<Tunnel>) event.getNewValue());
});
}).start();
var bandwidthUpdateThread = new Thread(()->{
while(!Gui.instance.isStopping()) {
if (routerWrapper.isStarted()) {
Platform.runLater(() -> {
bandwidthIn1s.setText(format2dp.format(routerWrapper.get1sRateInKBps()) + " KBps");
bandwidthIn5m.setText(format2dp.format(routerWrapper.get5mRateInKBps()) + " KBps");
bandwidthInAll.setText(format2dp.format(routerWrapper.getAvgRateInKBps()) + " KBps");
totalTransferredIn.setText(format2dp.format(routerWrapper.getTotalInMB()) + " MB ");
bandwidthOut1s.setText(format2dp.format(routerWrapper.get1sRateOutKBps()) + " KBps");
bandwidthOut5m.setText(format2dp.format(routerWrapper.get5mRateOutKBps()) + " KBps");
bandwidthOutAll.setText(format2dp.format(routerWrapper.getAvgRateOutKBps()) + " KBps");
totalTransferredOut.setText(format2dp.format(routerWrapper.getTotalOutMB()) + " MB ");
statusLabel.setText("Status: " + routerWrapper.getReachability().getMessage());
tunnelsTableView.refresh();
});
}
try { Thread.sleep(1000); } catch (InterruptedException e) {}
}
});
bandwidthUpdateThread.start();
Runtime.getRuntime().addShutdownHook(new Thread(()->bandwidthUpdateThread.interrupt()));
}
public RouterWrapper getRouterWrapper() {
return routerWrapper;
}
private int getBandwidthLimitKBPerSec() {
return (int)Math.round(bandwidthSlider.getValue()*1024d/8d);
}
private void startRouter() {
// need to launch Gui with parameters: --i2p.dir.base= and --i2p.dir.config=
var params = Gui.instance.getParameters().getNamed();
Properties routerProperties = new Properties();
routerProperties.put("i2np.inboundKBytesPerSecond", getBandwidthLimitKBPerSec());
routerProperties.put("i2np.outboundKBytesPerSecond", getBandwidthLimitKBPerSec());
routerProperties.put("router.sharePercentage", 80);
routerWrapper = new RouterWrapper(routerProperties);
routerWrapper.start();
}
}