This commit is contained in:
Sebastian Stenzel
2014-12-15 09:39:11 +01:00
9 changed files with 108 additions and 25 deletions

View File

@@ -16,12 +16,15 @@ import java.util.ResourceBundle;
import java.util.stream.Collectors;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.HBox;
@@ -44,6 +47,9 @@ public class MainController implements Initializable, InitializationListener, Un
private Stage stage;
@FXML
private ContextMenu directoryContextMenu;
@FXML
private HBox rootPane;
@@ -58,9 +64,11 @@ public class MainController implements Initializable, InitializationListener, Un
@Override
public void initialize(URL url, ResourceBundle rb) {
this.rb = rb;
final ObservableList<Directory> items = FXCollections.observableList(Settings.load().getDirectories());
directoryList.setItems(items);
directoryList.setCellFactory(this::createDirecoryListCell);
directoryList.getSelectionModel().getSelectedItems().addListener(this::selectedDirectoryDidChange);
directoryList.getItems().addAll(Settings.load().getDirectories());
}
@FXML
@@ -70,22 +78,38 @@ public class MainController implements Initializable, InitializationListener, Un
if (file != null && file.canWrite()) {
final Directory dir = new Directory(file.toPath());
directoryList.getItems().add(dir);
Settings.load().getDirectories().clear();
Settings.load().getDirectories().addAll(directoryList.getItems());
directoryList.getSelectionModel().selectLast();
}
}
private ListCell<Directory> createDirecoryListCell(ListView<Directory> param) {
return new DirectoryListCell();
final DirectoryListCell cell = new DirectoryListCell();
cell.setContextMenu(directoryContextMenu);
return cell;
}
private void selectedDirectoryDidChange(ListChangeListener.Change<? extends Directory> change) {
final Directory selectedDir = directoryList.getSelectionModel().getSelectedItem();
stage.setTitle(selectedDir.getName());
showDirectory(selectedDir);
if (selectedDir == null) {
stage.setTitle(rb.getString("app.name"));
showWelcomeView();
} else {
stage.setTitle(selectedDir.getName());
showDirectory(selectedDir);
}
}
@FXML
private void didClickRemoveSelectedEntry(ActionEvent e) {
final Directory selectedDir = directoryList.getSelectionModel().getSelectedItem();
directoryList.getItems().remove(selectedDir);
directoryList.getSelectionModel().clearSelection();
}
// ****************************************
// Subcontroller for right panel
// ****************************************
private void showDirectory(Directory directory) {
try {
if (directory.isUnlocked()) {
@@ -100,10 +124,6 @@ public class MainController implements Initializable, InitializationListener, Un
}
}
// ****************************************
// Subcontroller for right panel
// ****************************************
private <T> T showView(String fxml) {
try {
final FXMLLoader loader = new FXMLLoader(getClass().getResource(fxml), rb);
@@ -116,6 +136,10 @@ public class MainController implements Initializable, InitializationListener, Un
}
}
private void showWelcomeView() {
this.showView("/welcome.fxml");
}
private void showInitializeView(Directory directory) {
final InitializeController ctrl = showView("/initialize.fxml");
ctrl.setDirectory(directory);

View File

@@ -77,7 +77,7 @@ public class UnlockController implements Initializable {
// ****************************************
@FXML
protected void didClickUnlockButton(ActionEvent event) {
private void didClickUnlockButton(ActionEvent event) {
final String masterKeyFileName = usernameBox.getValue() + Aes256Cryptor.MASTERKEY_FILE_EXT;
final Path masterKeyPath = directory.getPath().resolve(masterKeyFileName);
final CharSequence password = passwordField.getCharacters();

View File

@@ -52,7 +52,7 @@ public class UnlockedController implements Initializable {
}
@FXML
protected void closeVault(ActionEvent event) {
private void didClickCloseVault(ActionEvent event) {
directory.unmount();
directory.stopServer();
directory.setUnlocked(false);
@@ -82,7 +82,7 @@ public class UnlockedController implements Initializable {
private class IoSamplingAnimationHandler implements EventHandler<ActionEvent> {
private static final double BYTES_TO_MEGABYTES_FACTOR = IO_SAMPLING_INTERVAL / 1024.0 / 1024.0;
private static final double BYTES_TO_MEGABYTES_FACTOR = 1.0 / IO_SAMPLING_INTERVAL / 1024.0 / 1024.0;
private final CryptorIOSampling sampler;
private final Series<Number, Number> decryptedBytes;
private final Series<Number, Number> encryptedBytes;

View File

@@ -1,19 +1,55 @@
package org.cryptomator.ui.controls;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.ListCell;
import javafx.scene.control.Tooltip;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import org.cryptomator.ui.model.Directory;
public class DirectoryListCell extends ListCell<Directory> {
public class DirectoryListCell extends ListCell<Directory> implements ChangeListener<Boolean> {
// TODO: fancy graphics instead of circles ;-)
private final Circle statusIndicator = new Circle(3.0);
public DirectoryListCell() {
setGraphic(statusIndicator);
setGraphicTextGap(12.0);
setContentDisplay(ContentDisplay.LEFT);
}
@Override
protected void updateItem(Directory item, boolean empty) {
final Directory oldItem = super.getItem();
if (oldItem != null) {
oldItem.unlockedProperty().removeListener(this);
}
super.updateItem(item, empty);
if (item == null) {
setText(null);
setTooltip(null);
statusIndicator.setVisible(false);
} else {
setText(item.getName());
setTooltip(new Tooltip(item.getPath().toString()));
statusIndicator.setVisible(true);
item.unlockedProperty().addListener(this);
updateStatusIndicator();
}
}
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
updateStatusIndicator();
}
private void updateStatusIndicator() {
final Paint statusColor = getItem().isUnlocked() ? Color.LIME : Color.RED;
statusIndicator.setFill(statusColor);
}
}

View File

@@ -5,6 +5,9 @@ import java.io.Serializable;
import java.nio.file.Files;
import java.nio.file.Path;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import org.apache.commons.lang3.StringUtils;
import org.cryptomator.crypto.Cryptor;
import org.cryptomator.crypto.SamplingDecorator;
@@ -29,8 +32,9 @@ public class Directory implements Serializable {
private final WebDAVServer server = new WebDAVServer();
private final Cryptor cryptor = SamplingDecorator.decorate(new Aes256Cryptor());
private final ObjectProperty<Boolean> unlocked = new SimpleObjectProperty<Boolean>(this, "unlocked", Boolean.FALSE);
private final Path path;
private boolean unlocked;
// private boolean unlocked;
private String unmountCommand;
private final Runnable shutdownTask = new ShutdownTask();
@@ -103,12 +107,16 @@ public class Directory implements Serializable {
return cryptor;
}
public boolean isUnlocked() {
public ObjectProperty<Boolean> unlockedProperty() {
return unlocked;
}
public boolean isUnlocked() {
return unlocked.get();
}
public void setUnlocked(boolean unlocked) {
this.unlocked = unlocked;
this.unlocked.set(unlocked);
}
public WebDAVServer getServer() {

View File

@@ -18,7 +18,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.ui.model.Directory;
@@ -54,7 +54,7 @@ public class Settings implements Serializable {
}
}
private Collection<Directory> directories;
private List<Directory> directories;
private String username;
private Settings() {
@@ -96,14 +96,14 @@ public class Settings implements Serializable {
/* Getter/Setter */
public Collection<Directory> getDirectories() {
public List<Directory> getDirectories() {
if (directories == null) {
directories = new ArrayList<>();
}
return directories;
}
public void setDirectories(Collection<Directory> directories) {
public void setDirectories(List<Directory> directories) {
this.directories = directories;
}

View File

@@ -9,6 +9,11 @@
app.name=Cryptomator
# main.fxml
main.directoryList.contextMenu.remove=Remove from list
main.directoryList.contextMenu.addUser=Add user
main.directoryList.contextMenu.changePassword=Change password
# welcome.fxml
welcome.welcomeLabel=Welcome to Cryptomator

View File

@@ -14,13 +14,23 @@
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ContextMenu?>
<?import javafx.scene.control.MenuItem?>
<HBox fx:id="rootPane" prefHeight="400.0" prefWidth="600.0" fx:controller="org.cryptomator.ui.MainController" xmlns:fx="http://javafx.com/fxml">
<fx:define>
<fx:include fx:id="welcomeView" source="welcome.fxml" />
<ContextMenu fx:id="directoryContextMenu">
<items>
<MenuItem text="%main.directoryList.contextMenu.remove" onAction="#didClickRemoveSelectedEntry" />
<!-- TODO: -->
<MenuItem text="%main.directoryList.contextMenu.addUser" disable="true" />
<MenuItem text="%main.directoryList.contextMenu.changePassword" disable="true" />
</items>
</ContextMenu>
</fx:define>
<children>
<VBox prefWidth="200.0">
<children>
@@ -34,7 +44,7 @@
</VBox>
<Pane fx:id="contentPane">
<children>
<fx:reference source="welcomeView"/>
<fx:reference source="welcomeView" />
</children>
</Pane>
</children>

View File

@@ -33,7 +33,7 @@
<Label fx:id="messageLabel" GridPane.rowIndex="0" GridPane.columnIndex="0" GridPane.columnSpan="2" />
<!-- Row 1 -->
<Button text="%unlocked.button.lock" defaultButton="true" GridPane.rowIndex="1" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.halignment="RIGHT" prefWidth="150.0" onAction="#closeVault" focusTraversable="false"/>
<Button text="%unlocked.button.lock" defaultButton="true" GridPane.rowIndex="1" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.halignment="RIGHT" prefWidth="150.0" onAction="#didClickCloseVault" focusTraversable="false"/>
<!-- Row 2 -->
<LineChart fx:id="ioGraph" GridPane.rowIndex="2" GridPane.columnIndex="0" GridPane.columnSpan="2" animated="false" createSymbols="false" prefHeight="300.0" legendVisible="true" legendSide="BOTTOM" verticalZeroLineVisible="false" verticalGridLinesVisible="false" horizontalGridLinesVisible="true">