/*******************************************************************************
* Copyright (c) 2016 comtel inc.
*
* Licensed under the Apache License, version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*******************************************************************************/
package org.jfxvnc.app.presentation;
import java.awt.Toolkit;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ResourceBundle;
import javax.inject.Inject;
import org.jfxvnc.app.persist.SessionContext;
import org.jfxvnc.app.presentation.detail.DetailView;
import org.jfxvnc.app.presentation.vnc.VncView;
import org.jfxvnc.net.rfb.render.ProtocolConfiguration;
import org.jfxvnc.ui.service.VncRenderService;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.css.PseudoClass;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.Slider;
import javafx.scene.control.SplitPane;
import javafx.scene.control.ToggleButton;
import javafx.scene.layout.BorderPane;
import javafx.util.Duration;
public class MainViewPresenter implements Initializable {
@Inject
SessionContext ctx;
@Inject
VncRenderService service;
@FXML
BorderPane mainPane;
@FXML
private Label statusLabel;
@FXML
private ProgressIndicator progress;
@FXML
private Button connectBtn;
@FXML
private Button disconnectBtn;
@FXML
private ToggleButton gearBtn;
@FXML
private Slider zoomSlider;
@FXML
private ToggleButton fullScreenBtn;
@FXML
private SplitPane splitPane;
private volatile long lastPing = 0;
private final static PseudoClass CONNECT_CLASS = PseudoClass.getPseudoClass("connect");
private final static PseudoClass ONLINE_CLASS = PseudoClass.getPseudoClass("online");
private final static PseudoClass WINDOW_CLASS = PseudoClass.getPseudoClass("window");
private final StringProperty statusProperty = new SimpleStringProperty("-", "mainview.status");
@Override
public void initialize(URL location, ResourceBundle rb) {
ctx.addBinding(statusProperty);
VncView vncView = new VncView();
DetailView detailView = new DetailView();
splitPane.getItems().addAll(vncView.getView(), detailView.getView());
splitPane.getDividers().get(0).setPosition(1.0);
statusLabel.textProperty().bind(statusProperty);
gearBtn.selectedProperty().addListener(l -> {
SplitPane.Divider divider = splitPane.getDividers().get(0);
KeyValue value = new KeyValue(divider.positionProperty(), gearBtn.isSelected() ? 0.80 : 1.0);
new Timeline(new KeyFrame(Duration.seconds(0.2), value)).play();
});
gearBtn.setSelected(true);
connectBtn.textProperty().bind(Bindings.createStringBinding(
() -> service.listeningModeProperty().get() ? rb.getString("button.listening") : rb.getString("button.connect"), service.listeningModeProperty()));
disconnectBtn.textProperty().bind(Bindings.createStringBinding(
() -> service.listeningModeProperty().get() ? rb.getString("button.cancel") : rb.getString("button.disconnect"), service.listeningModeProperty()));
disconnectBtn.disableProperty().bind(connectBtn.disabledProperty().not());
fullScreenBtn.selectedProperty().bindBidirectional(service.fullSceenProperty());
fullScreenBtn.selectedProperty().addListener((l, o, n) -> fullScreenBtn.pseudoClassStateChanged(WINDOW_CLASS, n));
progress.visibleProperty().bind(service.connectingProperty());
zoomSlider.valueProperty().bindBidirectional(service.zoomLevelProperty());
vncView.getView().setOnScroll(e -> service.zoomLevelProperty().set(service.zoomLevelProperty().get() + (e.getDeltaY() > 0.0 ? 0.01 : -0.01)));
service.zoomLevelProperty()
.addListener((l, o, z) -> statusProperty.set(MessageFormat.format(rb.getString("status.zoom.scale"), Math.floor(z.doubleValue() * 100))));
service.protocolStateProperty().addListener((l, o, event) -> Platform.runLater(() -> {
switch (event) {
case LISTENING:
statusProperty.set(rb.getString("status.listening"));
break;
case CLOSED:
statusProperty.set(rb.getString("status.closed"));
break;
case HANDSHAKE_STARTED:
ProtocolConfiguration config = service.getConfiguration();
statusProperty.set(MessageFormat.format(rb.getString("status.try.connect"), config.hostProperty().get(), config.portProperty().get()));
break;
case HANDSHAKE_COMPLETE:
statusProperty.set(rb.getString("status.open"));
gearBtn.setSelected(false);
break;
case SECURITY_FAILED:
statusProperty.set(rb.getString("status.auth.failed"));
break;
case SECURITY_COMPLETE:
statusProperty.set(rb.getString("status.auth.done"));
break;
default:
break;
}
}));
service.connectedProperty().addListener((l, o, n) -> Platform.runLater(() -> connectBtn.setDisable(n)));
service.connectingProperty().addListener((l, o, n) -> Platform.runLater(() -> gearBtn.pseudoClassStateChanged(CONNECT_CLASS, n)));
service.onlineProperty().addListener((l, o, n) -> Platform.runLater(() -> gearBtn.pseudoClassStateChanged(ONLINE_CLASS, n)));
service.exceptionCaughtProperty().addListener((l, o, n) -> Platform.runLater(() -> {
// Notifications.create().owner(mainPane).position(Pos.TOP_CENTER).text(n.getMessage()).showError();
statusProperty.set(n.getMessage());
}));
service.bellProperty().addListener(l -> bell());
}
@FXML
void connect(ActionEvent event) {
service.connect();
}
@FXML
void disconnect(ActionEvent event) {
service.disconnect();
}
private void bell() {
long time = System.currentTimeMillis();
if (lastPing > time - 2000) {
return;
}
lastPing = time;
Toolkit.getDefaultToolkit().beep();
Platform.runLater(() -> statusProperty.set("Bell"));
}
}