summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Suhren <suhren.stefan@fh-swf.de>2015-05-04 22:11:28 +0200
committerStefan Suhren <suhren.stefan@fh-swf.de>2015-05-04 22:11:28 +0200
commit3b5728de6f2d8d2852fbb86fa8cac21e6dccc19b (patch)
tree54965319a9aafeb294dac8e36e4ce1371ec76ef3 /src
parentaf7b9bd6a962b9a290fc5d78c08c83653961811f (diff)
downloadJava2-3b5728de6f2d8d2852fbb86fa8cac21e6dccc19b.tar.gz
Java2-3b5728de6f2d8d2852fbb86fa8cac21e6dccc19b.zip
Build a file browser looking like Finder
Diffstat (limited to 'src')
-rw-r--r--src/ch/makery/sortfilter/Main.java36
-rw-r--r--src/ch/makery/sortfilter/Person.java44
-rw-r--r--src/ch/makery/sortfilter/PersonTable.fxml25
-rw-r--r--src/ch/makery/sortfilter/PersonTableController.java91
-rw-r--r--src/de/fhswf/fbin/java2fx/entities/FXFile.java126
-rw-r--r--src/de/fhswf/fbin/java2fx/entities/Person.java50
-rw-r--r--src/de/fhswf/fbin/java2fx/tables/CheckBoxTableCellFactory.java16
-rw-r--r--src/de/fhswf/fbin/java2fx/tables/DatePickerTableCell.java88
-rw-r--r--src/de/fhswf/fbin/java2fx/tables/LocalDateTimeTableCellFactory.java37
-rw-r--r--src/de/fhswf/fbin/java2fx/tables/NumberTableCellFactory.java35
-rw-r--r--src/de/fhswf/fbin/java2fx/trees/DirectoryTreeItem.java103
-rw-r--r--src/de/fhswf/fbin/java2fx/trees/DirectoryTreeView.java20
-rw-r--r--src/de/fhswf/fbin/java2fx/util/FileUtils.java29
-rw-r--r--src/de/fhswf/in/inf/java2/aufgabe05/MainApplication.java82
-rw-r--r--src/de/fhswf/in/inf/java2/aufgabe05/view/DirectoryOverview.fxml17
-rw-r--r--src/de/fhswf/in/inf/java2/aufgabe05/view/DirectoryOverviewController.java55
-rw-r--r--src/de/fhswf/in/inf/java2/aufgabe05/view/DirectoryTableView.java88
-rw-r--r--src/de/fhswf/in/inf/java2/aufgabe05/view/RootLayout.fxml31
-rw-r--r--src/de/fhswf/in/inf/java2/aufgabe05/view/RootLayoutController.java48
19 files changed, 1021 insertions, 0 deletions
diff --git a/src/ch/makery/sortfilter/Main.java b/src/ch/makery/sortfilter/Main.java
new file mode 100644
index 0000000..6a8f562
--- /dev/null
+++ b/src/ch/makery/sortfilter/Main.java
@@ -0,0 +1,36 @@
+package ch.makery.sortfilter;
+
+import java.io.IOException;
+
+import javafx.application.Application;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Scene;
+import javafx.scene.layout.AnchorPane;
+import javafx.stage.Stage;
+
+/**
+ * Main class to start the application.
+ *
+ * @author Marco Jakob
+ */
+public class Main extends Application {
+
+ @Override
+ public void start(Stage primaryStage) {
+ primaryStage.setTitle("Sorting and Filtering");
+
+ try {
+ FXMLLoader loader = new FXMLLoader(Main.class.getResource("PersonTable.fxml"));
+ AnchorPane page = (AnchorPane) loader.load();
+ Scene scene = new Scene(page);
+ primaryStage.setScene(scene);
+ primaryStage.show();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void main(String[] args) {
+ launch(args);
+ }
+} \ No newline at end of file
diff --git a/src/ch/makery/sortfilter/Person.java b/src/ch/makery/sortfilter/Person.java
new file mode 100644
index 0000000..af6f212
--- /dev/null
+++ b/src/ch/makery/sortfilter/Person.java
@@ -0,0 +1,44 @@
+package ch.makery.sortfilter;
+
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+
+/**
+ * Simple model class for the person table.
+ *
+ * @author Marco Jakob
+ */
+public class Person {
+
+ private final StringProperty firstName;
+ private final StringProperty lastName;
+
+ public Person(String firstName, String lastName) {
+ this.firstName = new SimpleStringProperty(firstName);
+ this.lastName = new SimpleStringProperty(lastName);
+ }
+
+ public String getFirstName() {
+ return firstName.get();
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName.set(firstName);
+ }
+
+ public StringProperty firstNameProperty() {
+ return firstName;
+ }
+
+ public String getLastName() {
+ return lastName.get();
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName.set(lastName);
+ }
+
+ public StringProperty lastNameProperty() {
+ return lastName;
+ }
+} \ No newline at end of file
diff --git a/src/ch/makery/sortfilter/PersonTable.fxml b/src/ch/makery/sortfilter/PersonTable.fxml
new file mode 100644
index 0000000..aeb41b0
--- /dev/null
+++ b/src/ch/makery/sortfilter/PersonTable.fxml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import java.lang.*?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+
+<AnchorPane minWidth="315.0" prefHeight="300.0" prefWidth="315.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.makery.sortfilter.PersonTableController">
+ <children>
+ <TableView fx:id="personTable" prefHeight="-1.0" prefWidth="-1.0" tableMenuButtonVisible="false" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="40.0">
+ <columns>
+ <TableColumn fx:id="firstNameColumn" maxWidth="5000.0" minWidth="10.0" prefWidth="120.0" text="First Name" />
+ <TableColumn fx:id="lastNameColumn" maxWidth="5000.0" minWidth="10.0" prefWidth="120.0" text="Last Name" />
+ </columns>
+<columnResizePolicy>
+<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
+</columnResizePolicy>
+ </TableView>
+ <HBox id="HBox" alignment="CENTER" spacing="5.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0">
+ <children>
+ <Label text="Filter Table:" />
+ <TextField fx:id="filterField" prefWidth="-1.0" HBox.hgrow="ALWAYS" />
+ </children>
+ </HBox>
+ </children>
+</AnchorPane>
diff --git a/src/ch/makery/sortfilter/PersonTableController.java b/src/ch/makery/sortfilter/PersonTableController.java
new file mode 100644
index 0000000..98ad591
--- /dev/null
+++ b/src/ch/makery/sortfilter/PersonTableController.java
@@ -0,0 +1,91 @@
+package ch.makery.sortfilter;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.collections.transformation.FilteredList;
+import javafx.collections.transformation.SortedList;
+import javafx.fxml.FXML;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+import javafx.scene.control.TextField;
+
+
+/**
+ * View-Controller for the person table.
+ *
+ * @author Marco Jakob
+ */
+public class PersonTableController {
+
+ @FXML
+ private TextField filterField;
+ @FXML
+ private TableView<Person> personTable;
+ @FXML
+ private TableColumn<Person, String> firstNameColumn;
+ @FXML
+ private TableColumn<Person, String> lastNameColumn;
+
+ private ObservableList<Person> masterData = FXCollections.observableArrayList();
+
+ /**
+ * Just add some sample data in the constructor.
+ */
+ public PersonTableController() {
+ masterData.add(new Person("Hans", "Muster"));
+ masterData.add(new Person("Ruth", "Mueller"));
+ masterData.add(new Person("Heinz", "Kurz"));
+ masterData.add(new Person("Cornelia", "Meier"));
+ masterData.add(new Person("Werner", "Meyer"));
+ masterData.add(new Person("Lydia", "Kunz"));
+ masterData.add(new Person("Anna", "Best"));
+ masterData.add(new Person("Stefan", "Meier"));
+ masterData.add(new Person("Martin", "Mueller"));
+ }
+
+ /**
+ * Initializes the controller class. This method is automatically called
+ * after the fxml file has been loaded.
+ *
+ * Initializes the table columns and sets up sorting and filtering.
+ */
+ @FXML
+ private void initialize() {
+ // 0. Initialize the columns.
+ firstNameColumn.setCellValueFactory(cellData -> cellData.getValue().firstNameProperty());
+ lastNameColumn.setCellValueFactory(cellData -> cellData.getValue().lastNameProperty());
+
+ // 1. Wrap the ObservableList in a FilteredList (initially display all data).
+ FilteredList<Person> filteredData = new FilteredList<>(masterData, p -> true);
+
+ // 2. Set the filter Predicate whenever the filter changes.
+ filterField.textProperty().addListener((observable, oldValue, newValue) -> {
+ filteredData.setPredicate(person -> {
+ // If filter text is empty, display all persons.
+ if (newValue == null || newValue.isEmpty()) {
+ return true;
+ }
+
+ // Compare first name and last name of every person with filter text.
+ String lowerCaseFilter = newValue.toLowerCase();
+
+ if (person.getFirstName().toLowerCase().indexOf(lowerCaseFilter) != -1) {
+ return true; // Filter matches first name.
+ } else if (person.getLastName().toLowerCase().indexOf(lowerCaseFilter) != -1) {
+ return true; // Filter matches last name.
+ }
+ return false; // Does not match.
+ });
+ });
+
+ // 3. Wrap the FilteredList in a SortedList.
+ SortedList<Person> sortedData = new SortedList<>(filteredData);
+
+ // 4. Bind the SortedList comparator to the TableView comparator.
+ // Otherwise, sorting the TableView would have no effect.
+ sortedData.comparatorProperty().bind(personTable.comparatorProperty());
+
+ // 5. Add sorted (and filtered) data to the table.
+ personTable.setItems(sortedData);
+ }
+}
diff --git a/src/de/fhswf/fbin/java2fx/entities/FXFile.java b/src/de/fhswf/fbin/java2fx/entities/FXFile.java
new file mode 100644
index 0000000..be56ded
--- /dev/null
+++ b/src/de/fhswf/fbin/java2fx/entities/FXFile.java
@@ -0,0 +1,126 @@
+package de.fhswf.fbin.java2fx.entities;
+
+import java.io.File;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.LongProperty;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleBooleanProperty;
+import javafx.beans.property.SimpleLongProperty;
+import javafx.beans.property.SimpleObjectProperty;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+
+public class FXFile
+{
+ private static String separator = System.getProperty("file.separator");
+
+ private File file;
+
+ public FXFile(File file)
+ {
+ this.file = file;
+ setName(this.toString());
+ setLastModified(LocalDateTime.ofEpochSecond(file.lastModified()/1000, 0, ZoneOffset.UTC));
+ setLength(file.length());
+ setHidden(file.isHidden());
+ }
+
+ public File getFile() {
+ return this.file;
+ }
+
+ private StringProperty name;
+
+ public void setName(String value)
+ {
+ nameProperty().set(value);
+ }
+
+ public String getName()
+ {
+ return nameProperty().get();
+ }
+
+ public StringProperty nameProperty()
+ {
+ if (name == null)
+ name = new SimpleStringProperty(this, "name");
+ return name;
+ }
+
+ private ObjectProperty<LocalDateTime> lastModified;
+
+ public void setLastModified(LocalDateTime value)
+ {
+ lastModifiedProperty().set(value);
+ }
+
+ public LocalDateTime getLastModified()
+ {
+ return lastModifiedProperty().get();
+ }
+
+ public ObjectProperty<LocalDateTime> lastModifiedProperty()
+ {
+ if (lastModified == null)
+ lastModified = new SimpleObjectProperty<LocalDateTime>(this, "lastModified");
+ return lastModified;
+ }
+
+ private LongProperty length;
+
+ public LongProperty lengthProperty()
+ {
+ if (length == null)
+ length = new SimpleLongProperty(this, "length");
+ return length;
+ }
+
+ public long getLength()
+ {
+ return lengthProperty().get();
+ }
+
+ public void setLength(long length)
+ {
+ lengthProperty().set(length);
+ }
+
+ private BooleanProperty hidden;
+
+ public BooleanProperty hiddenProperty()
+ {
+ if (hidden == null)
+ hidden = new SimpleBooleanProperty(this, "hidden");
+ return this.hidden;
+ }
+
+ public boolean isHidden()
+ {
+ return hiddenProperty().get();
+ }
+
+ public void setHidden(boolean hidden)
+ {
+ hiddenProperty().set(hidden);
+ }
+
+ @Override
+ public String toString()
+ {
+ String name = file.getName();
+ if (!name.isEmpty()) {
+ int index = name.lastIndexOf(separator);
+ if (index != -1)
+ name = name.substring(index);
+ }
+ else {
+ name = file.getAbsolutePath();
+ }
+ return name;
+ }
+}
diff --git a/src/de/fhswf/fbin/java2fx/entities/Person.java b/src/de/fhswf/fbin/java2fx/entities/Person.java
new file mode 100644
index 0000000..a7de0e4
--- /dev/null
+++ b/src/de/fhswf/fbin/java2fx/entities/Person.java
@@ -0,0 +1,50 @@
+package de.fhswf.fbin.java2fx.entities;
+
+import javafx.beans.property.SimpleStringProperty;
+
+public class Person
+{
+ private final SimpleStringProperty firstName;
+
+ private final SimpleStringProperty lastName;
+
+ private final SimpleStringProperty email;
+
+ public Person(String fName, String lName, String email)
+ {
+ this.firstName = new SimpleStringProperty(fName);
+ this.lastName = new SimpleStringProperty(lName);
+ this.email = new SimpleStringProperty(email);
+ }
+
+ public String getFirstName()
+ {
+ return firstName.get();
+ }
+
+ public void setFirstName(String fName)
+ {
+ firstName.set(fName);
+ }
+
+ public String getLastName()
+ {
+ return lastName.get();
+ }
+
+ public void setLastName(String fName)
+ {
+ lastName.set(fName);
+ }
+
+ public String getEmail()
+ {
+ return email.get();
+ }
+
+ public void setEmail(String fName)
+ {
+ email.set(fName);
+ }
+
+} \ No newline at end of file
diff --git a/src/de/fhswf/fbin/java2fx/tables/CheckBoxTableCellFactory.java b/src/de/fhswf/fbin/java2fx/tables/CheckBoxTableCellFactory.java
new file mode 100644
index 0000000..f609860
--- /dev/null
+++ b/src/de/fhswf/fbin/java2fx/tables/CheckBoxTableCellFactory.java
@@ -0,0 +1,16 @@
+package de.fhswf.fbin.java2fx.tables;
+
+import javafx.scene.control.TableCell;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.cell.CheckBoxTableCell;
+import javafx.util.Callback;
+
+public class CheckBoxTableCellFactory<S> implements Callback<TableColumn<S, Boolean>, TableCell<S, Boolean>>
+{
+ @Override
+ public TableCell<S, Boolean> call(
+ TableColumn<S, Boolean> param)
+ {
+ return new CheckBoxTableCell<S, Boolean>();
+ }
+}
diff --git a/src/de/fhswf/fbin/java2fx/tables/DatePickerTableCell.java b/src/de/fhswf/fbin/java2fx/tables/DatePickerTableCell.java
new file mode 100644
index 0000000..c68edbb
--- /dev/null
+++ b/src/de/fhswf/fbin/java2fx/tables/DatePickerTableCell.java
@@ -0,0 +1,88 @@
+package de.fhswf.fbin.java2fx.tables;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.scene.control.DatePicker;
+import javafx.scene.control.TableCell;
+
+public class DatePickerTableCell<S> extends TableCell<S, LocalDate>
+{
+ private DatePicker datePicker;
+
+ @Override
+ public void startEdit()
+ {
+ if (!isEmpty())
+ {
+ super.startEdit();
+ createDatePicker();
+ setText(null);
+ setGraphic(datePicker);
+ }
+ }
+
+ @Override
+ public void cancelEdit()
+ {
+ super.cancelEdit();
+
+ setText(getItem().format(DateTimeFormatter.RFC_1123_DATE_TIME));
+ setGraphic(null);
+ }
+
+ @Override
+ public void updateItem(LocalDate item, boolean empty)
+ {
+ super.updateItem(item, empty);
+
+ if (empty)
+ {
+ setText(null);
+ setGraphic(null);
+ }
+ else
+ {
+ if (isEditing())
+ {
+ if (datePicker != null)
+ {
+ datePicker.setValue(item);
+ }
+ setText(null);
+ setGraphic(datePicker);
+ }
+ else
+ {
+ setText(item.format(DateTimeFormatter.RFC_1123_DATE_TIME));
+ setGraphic(null);
+ }
+ }
+ }
+
+ private void createDatePicker()
+ {
+ datePicker = new DatePicker();
+ datePicker.setValue(getItem());
+ datePicker.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
+ datePicker.focusedProperty().addListener(new ChangeListener<Boolean>()
+ {
+ @Override
+ public void changed(ObservableValue<? extends Boolean> arg0,
+ Boolean oldVAlue, Boolean newValue)
+ {
+ if (!newValue)
+ {
+ commitEdit(datePicker.getValue());
+ }
+ }
+ });
+ }
+
+ private String getString()
+ {
+ return getItem() == null ? "" : getItem().format(DateTimeFormatter.RFC_1123_DATE_TIME);
+ }
+}
diff --git a/src/de/fhswf/fbin/java2fx/tables/LocalDateTimeTableCellFactory.java b/src/de/fhswf/fbin/java2fx/tables/LocalDateTimeTableCellFactory.java
new file mode 100644
index 0000000..0c5c41d
--- /dev/null
+++ b/src/de/fhswf/fbin/java2fx/tables/LocalDateTimeTableCellFactory.java
@@ -0,0 +1,37 @@
+package de.fhswf.fbin.java2fx.tables;
+
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+
+import javafx.scene.control.TableCell;
+import javafx.scene.control.TableColumn;
+import javafx.util.Callback;
+
+public class LocalDateTimeTableCellFactory<S> implements
+ Callback<TableColumn<S, LocalDateTime>, TableCell<S, LocalDateTime>>
+{
+ @Override
+ public TableCell<S, LocalDateTime> call(TableColumn<S, LocalDateTime> param)
+ {
+ return new TableCell<S, LocalDateTime>()
+ {
+ @Override
+ protected void updateItem(LocalDateTime item, boolean empty)
+ {
+ super.updateItem(item, empty);
+
+ if (!empty)
+ {
+ ZonedDateTime zdt = ZonedDateTime.of(item, ZoneId.systemDefault());
+ setText(zdt.format(DateTimeFormatter.RFC_1123_DATE_TIME));
+ }
+ else
+ {
+ setText(null);
+ }
+ }
+ };
+ }
+}
diff --git a/src/de/fhswf/fbin/java2fx/tables/NumberTableCellFactory.java b/src/de/fhswf/fbin/java2fx/tables/NumberTableCellFactory.java
new file mode 100644
index 0000000..2bfce82
--- /dev/null
+++ b/src/de/fhswf/fbin/java2fx/tables/NumberTableCellFactory.java
@@ -0,0 +1,35 @@
+package de.fhswf.fbin.java2fx.tables;
+
+import javafx.geometry.Pos;
+import javafx.scene.control.TableCell;
+import javafx.scene.control.TableColumn;
+import javafx.util.Callback;
+
+public class NumberTableCellFactory<S>
+ implements
+ Callback<TableColumn<S, Number>, TableCell<S, Number>>
+{
+ @Override
+ public TableCell<S, Number> call(
+ TableColumn<S, Number> param)
+ {
+ return (TableCell<S, Number>) new TableCell<S, Number>()
+ {
+ @Override
+ protected void updateItem(Number item, boolean empty)
+ {
+ super.updateItem(item, empty);
+
+ if (!empty)
+ {
+ setText(item.toString());
+ setAlignment(Pos.TOP_RIGHT);
+ }
+ else
+ {
+ setText(null);
+ }
+ }
+ };
+ }
+}
diff --git a/src/de/fhswf/fbin/java2fx/trees/DirectoryTreeItem.java b/src/de/fhswf/fbin/java2fx/trees/DirectoryTreeItem.java
new file mode 100644
index 0000000..29afa29
--- /dev/null
+++ b/src/de/fhswf/fbin/java2fx/trees/DirectoryTreeItem.java
@@ -0,0 +1,103 @@
+package de.fhswf.fbin.java2fx.trees;
+
+import java.io.File;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.scene.control.TreeItem;
+import de.fhswf.fbin.java2fx.entities.FXFile;
+import de.fhswf.fbin.java2fx.util.FileUtils;
+
+public class DirectoryTreeItem extends TreeItem<FXFile>
+{
+ private boolean isFirstTimeChildren = true;
+
+ private boolean isFirstTimeLeaf = true;
+
+ private boolean isLeaf;
+
+ private File[] subDirectories;
+
+ private static String separator = System.getProperty("file.separator");
+
+ private static boolean isRunningOnWindows = System.getProperty("os.name")
+ .toLowerCase().contains("windows");
+
+ public DirectoryTreeItem(File file)
+ {
+ super(new FXFile(file));
+
+ if (file == null)
+// || (!separator.equals(file.getName()) && !file.isDirectory()))
+ throw new IllegalArgumentException("file is null or not a directory");
+ }
+
+ @Override
+ public boolean isLeaf()
+ {
+ if (isFirstTimeLeaf)
+ {
+ isFirstTimeLeaf = false;
+ isLeaf = getSubDirectories().length == 0;
+ }
+
+ return isLeaf;
+ }
+
+ @Override
+ public ObservableList<TreeItem<FXFile>> getChildren()
+ {
+ if (isFirstTimeChildren)
+ {
+ isFirstTimeChildren = false;
+
+ // First getChildren() call, so we actually go off and
+ // determine the children of the File contained in this TreeItem.
+ super.getChildren().setAll(buildChildren());
+ }
+
+ return super.getChildren();
+ }
+
+ private File[] getSubDirectories()
+ {
+ if (subDirectories == null)
+ {
+ FXFile dir = (FXFile) getValue();
+ System.out.println("\"" + dir.getName() + "\"");
+
+ if (isRunningOnWindows && parentProperty().getValue() == null)
+ {
+ dir.setName(separator);
+ subDirectories = File.listRoots();
+ System.out.println("windows detected");
+ }
+ else
+ {
+ subDirectories = dir.getFile().listFiles(f -> FileUtils.isPublicDirectory(f));
+ }
+
+ if (subDirectories == null)
+ {
+ System.out.println("oops, something went wrong for "
+ + dir.getName());
+ subDirectories = new File[0];
+ }
+ }
+
+ return subDirectories;
+ }
+
+ private ObservableList<TreeItem<FXFile>> buildChildren()
+ {
+ ObservableList<TreeItem<FXFile>> children = FXCollections
+ .observableArrayList();
+
+ for (File subDirectory : getSubDirectories())
+ {
+ children.add(new DirectoryTreeItem(subDirectory));
+ }
+
+ return children;
+ }
+}
diff --git a/src/de/fhswf/fbin/java2fx/trees/DirectoryTreeView.java b/src/de/fhswf/fbin/java2fx/trees/DirectoryTreeView.java
new file mode 100644
index 0000000..6885ff6
--- /dev/null
+++ b/src/de/fhswf/fbin/java2fx/trees/DirectoryTreeView.java
@@ -0,0 +1,20 @@
+package de.fhswf.fbin.java2fx.trees;
+
+import java.io.File;
+
+import javafx.scene.control.TreeView;
+import de.fhswf.fbin.java2fx.entities.FXFile;
+
+public class DirectoryTreeView extends TreeView<FXFile>
+{
+ public DirectoryTreeView()
+ {
+ super(new DirectoryTreeItem(new File(System.getProperty("file.separator"))));
+ boolean isRunningOnWindows = System.getProperty("os.name")
+ .toLowerCase().contains("windows");
+ if (isRunningOnWindows) {
+ this.setShowRoot(false);
+ this.rootProperty().getValue().setExpanded(true);;
+ }
+ }
+}
diff --git a/src/de/fhswf/fbin/java2fx/util/FileUtils.java b/src/de/fhswf/fbin/java2fx/util/FileUtils.java
new file mode 100644
index 0000000..fb67296
--- /dev/null
+++ b/src/de/fhswf/fbin/java2fx/util/FileUtils.java
@@ -0,0 +1,29 @@
+package de.fhswf.fbin.java2fx.util;
+
+import java.io.File;
+
+public final class FileUtils
+{
+ private FileUtils()
+ {
+ }
+
+ public static boolean isPublicDirectory(File dir)
+ {
+ SecurityManager security = System.getSecurityManager();
+ boolean isReadable = true;
+ if (security != null)
+ {
+ try
+ {
+ security.checkRead(dir.toURI().toString());
+ }
+ catch (Exception e)
+ {
+ isReadable = false;
+ }
+ }
+
+ return dir.isDirectory() && isReadable && !dir.isHidden();
+ }
+}
diff --git a/src/de/fhswf/in/inf/java2/aufgabe05/MainApplication.java b/src/de/fhswf/in/inf/java2/aufgabe05/MainApplication.java
new file mode 100644
index 0000000..7978cb1
--- /dev/null
+++ b/src/de/fhswf/in/inf/java2/aufgabe05/MainApplication.java
@@ -0,0 +1,82 @@
+package de.fhswf.in.inf.java2.aufgabe05;
+
+import java.io.IOException;
+
+import javafx.application.Application;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Scene;
+import javafx.scene.control.SplitPane;
+import javafx.scene.layout.AnchorPane;
+import javafx.scene.layout.BorderPane;
+import javafx.stage.Stage;
+
+public class MainApplication extends Application
+{
+
+ private Stage primaryStage;
+ private BorderPane rootLayout;
+
+ @Override
+ public void start(Stage primaryStage)
+ {
+ this.primaryStage = primaryStage;
+ this.primaryStage.setTitle("ThemeChooser");
+
+ initRootLayout();
+
+ showDirectoryOverview();
+ }
+
+ private void initRootLayout()
+ {
+ try
+ {
+ // Load root layout from fxml file.
+ FXMLLoader loader = new FXMLLoader();
+ loader.setLocation(MainApplication.class.getResource("view/RootLayout.fxml"));
+ rootLayout = (BorderPane) loader.load();
+
+ // Show the scene containing the root layout.
+ Scene scene = new Scene(rootLayout);
+ primaryStage.setScene(scene);
+
+ // Give the controller access to the main app.
+ // RootLayoutController controller = loader.getController();
+ // controller.setMainApp(this);
+
+ primaryStage.show();
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private void showDirectoryOverview()
+ {
+ try
+ {
+ // Load person overview.
+ FXMLLoader loader = new FXMLLoader();
+ loader.setLocation(MainApplication.class
+ .getResource("view/DirectoryOverview.fxml"));
+ AnchorPane personOverview = (AnchorPane) loader.load();
+
+ // Set person overview into the center of root layout.
+ rootLayout.setCenter(personOverview);
+
+ // Give the controller access to the main app.
+ // DirectoryOverviewController controller = loader.getController();
+ // controller.setMainApp(this);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ launch(args);
+ }
+}
diff --git a/src/de/fhswf/in/inf/java2/aufgabe05/view/DirectoryOverview.fxml b/src/de/fhswf/in/inf/java2/aufgabe05/view/DirectoryOverview.fxml
new file mode 100644
index 0000000..5c1c3ed
--- /dev/null
+++ b/src/de/fhswf/in/inf/java2/aufgabe05/view/DirectoryOverview.fxml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import java.lang.*?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.layout.AnchorPane?>
+
+<AnchorPane xmlns="http://javafx.com/javafx/8.0.45" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.fhswf.in.inf.java2.aufgabe05.view.DirectoryOverviewController">
+ <children>
+ <SplitPane dividerPositions="0.25" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+ <items>
+ <AnchorPane fx:id="leftPane" prefHeight="200.0" prefWidth="200.0" />
+ <AnchorPane fx:id="rightPane" prefHeight="200.0" prefWidth="200.0" />
+ </items>
+ </SplitPane>
+ </children>
+</AnchorPane>
diff --git a/src/de/fhswf/in/inf/java2/aufgabe05/view/DirectoryOverviewController.java b/src/de/fhswf/in/inf/java2/aufgabe05/view/DirectoryOverviewController.java
new file mode 100644
index 0000000..d12efee
--- /dev/null
+++ b/src/de/fhswf/in/inf/java2/aufgabe05/view/DirectoryOverviewController.java
@@ -0,0 +1,55 @@
+/**
+ *
+ */
+package de.fhswf.in.inf.java2.aufgabe05.view;
+
+import java.io.File;
+
+import javafx.fxml.FXML;
+import javafx.scene.control.TableView;
+import javafx.scene.layout.AnchorPane;
+import de.fhswf.fbin.java2fx.trees.DirectoryTreeView;
+
+/**
+ * TODO Add comment here
+ *
+ * @author $Author: $
+ * @version $Revision: $, $Date: $ UTC
+ */
+public class DirectoryOverviewController
+{
+ @FXML
+ private AnchorPane leftPane;
+
+ @FXML
+ private AnchorPane rightPane;
+
+ private DirectoryTreeView dirTree;
+
+ private DirectoryTableView dirTab;
+
+ @FXML
+ private void initialize()
+ {
+ dirTree = new DirectoryTreeView();
+ leftPane.getChildren().add(dirTree);
+ AnchorPane.setTopAnchor(dirTree, 0.0);
+ AnchorPane.setBottomAnchor(dirTree, 0.0);
+ AnchorPane.setLeftAnchor(dirTree, 0.0);
+ AnchorPane.setRightAnchor(dirTree, 0.0);
+
+ dirTab = new DirectoryTableView(dirTree.getRoot().getValue());
+ rightPane.getChildren().add(dirTab);
+ AnchorPane.setTopAnchor(dirTab, 0.0);
+ AnchorPane.setBottomAnchor(dirTab, 0.0);
+ AnchorPane.setLeftAnchor(dirTab, 0.0);
+ AnchorPane.setRightAnchor(dirTab, 0.0);
+
+ dirTab.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
+
+ dirTree.getSelectionModel().selectedItemProperty()
+ .addListener((ov, oldParent, newParent) -> {
+ dirTab.getParentDirectoryProperty().set(newParent.getValue());
+ });
+ }
+}
diff --git a/src/de/fhswf/in/inf/java2/aufgabe05/view/DirectoryTableView.java b/src/de/fhswf/in/inf/java2/aufgabe05/view/DirectoryTableView.java
new file mode 100644
index 0000000..0b76632
--- /dev/null
+++ b/src/de/fhswf/in/inf/java2/aufgabe05/view/DirectoryTableView.java
@@ -0,0 +1,88 @@
+/**
+ *
+ */
+
+package de.fhswf.in.inf.java2.aufgabe05.view;
+
+import java.io.File;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+
+import javafx.beans.property.SimpleObjectProperty;
+import javafx.collections.FXCollections;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+import javafx.scene.control.cell.PropertyValueFactory;
+import de.fhswf.fbin.java2fx.entities.FXFile;
+import de.fhswf.fbin.java2fx.tables.CheckBoxTableCellFactory;
+import de.fhswf.fbin.java2fx.tables.LocalDateTimeTableCellFactory;
+import de.fhswf.fbin.java2fx.tables.NumberTableCellFactory;
+
+/**
+ * TODO Add comment here
+ *
+ * @author $Author: $
+ * @version $Revision: $, $Date: $ UTC
+ */
+public class DirectoryTableView extends TableView<FXFile>
+{
+ private SimpleObjectProperty<FXFile> parentDirectoryProperty;
+
+ public SimpleObjectProperty<FXFile> getParentDirectoryProperty()
+ {
+ return parentDirectoryProperty;
+ }
+
+ public DirectoryTableView(FXFile parentDirectory)
+ {
+ this.parentDirectoryProperty = new SimpleObjectProperty<FXFile>(parentDirectory);
+
+ // name column with default cell factory
+ TableColumn<FXFile, String> nameCol = new TableColumn<>("Name");
+ nameCol.setCellValueFactory(new PropertyValueFactory<FXFile, String>(
+ "name"));
+
+ // length column with custom number cell factory
+ TableColumn<FXFile, Number> lengthCol = new TableColumn<>("Length");
+ lengthCol.setCellValueFactory(new PropertyValueFactory<FXFile, Number>(
+ "length"));
+ lengthCol.setCellFactory(new NumberTableCellFactory<FXFile>());
+
+ // last modified column with custom date cell factory
+ TableColumn<FXFile, LocalDateTime> lastModifiedCol = new TableColumn<>(
+ "Last Modified");
+ lastModifiedCol
+ .setCellValueFactory(new PropertyValueFactory<FXFile, LocalDateTime>(
+ "lastModified"));
+ lastModifiedCol
+ .setCellFactory(new LocalDateTimeTableCellFactory<FXFile>());
+
+ // hidden attribute column with custom checkbox cell factory
+ TableColumn<FXFile, Boolean> hiddenCol = new TableColumn<>("Hidden");
+ hiddenCol
+ .setCellValueFactory(new PropertyValueFactory<FXFile, Boolean>(
+ "hidden"));
+ hiddenCol.setCellFactory(new CheckBoxTableCellFactory<FXFile>());
+
+ this.getColumns()
+ .addAll(nameCol, lengthCol, lastModifiedCol, hiddenCol);
+
+ this.parentDirectoryProperty
+ .addListener((ov, oldParent, newParent) -> {
+ updateContent(newParent);
+ });
+ }
+
+ private void updateContent(FXFile newParent)
+ {
+ File[] files = newParent.getFile().listFiles(f -> (f.isFile()));
+ List<FXFile> fxFiles = new ArrayList<>();
+ for (File file : files)
+ {
+ fxFiles.add(new FXFile(file));
+ }
+ this.getItems().setAll(FXCollections.observableArrayList(fxFiles));
+
+ }
+}
diff --git a/src/de/fhswf/in/inf/java2/aufgabe05/view/RootLayout.fxml b/src/de/fhswf/in/inf/java2/aufgabe05/view/RootLayout.fxml
new file mode 100644
index 0000000..c060ace
--- /dev/null
+++ b/src/de/fhswf/in/inf/java2/aufgabe05/view/RootLayout.fxml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import java.lang.*?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.layout.BorderPane?>
+
+<BorderPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.45" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.fhswf.in.inf.java2.aufgabe05.view.RootLayoutController">
+ <top>
+ <MenuBar BorderPane.alignment="CENTER">
+ <menus>
+ <Menu mnemonicParsing="false" text="Datei">
+ <items>
+ <MenuItem mnemonicParsing="false" onAction="#handelBeenden" text="Beenden" />
+ </items>
+ </Menu>
+ <Menu mnemonicParsing="false" text="Themes">
+ <items>
+ <MenuItem mnemonicParsing="false" onAction="#handelModena" text="MODENA" />
+ <MenuItem mnemonicParsing="false" onAction="#handelCaspian" text="CASPIAN" />
+ </items>
+ </Menu>
+ <Menu mnemonicParsing="false" text="Hilfe">
+ <items>
+ <MenuItem mnemonicParsing="false" onAction="#handelInfo" text="Info" />
+ </items>
+ </Menu>
+ </menus>
+ </MenuBar>
+ </top>
+</BorderPane>
diff --git a/src/de/fhswf/in/inf/java2/aufgabe05/view/RootLayoutController.java b/src/de/fhswf/in/inf/java2/aufgabe05/view/RootLayoutController.java
new file mode 100644
index 0000000..efc1a10
--- /dev/null
+++ b/src/de/fhswf/in/inf/java2/aufgabe05/view/RootLayoutController.java
@@ -0,0 +1,48 @@
+/**
+ *
+ */
+package de.fhswf.in.inf.java2.aufgabe05.view;
+
+import javafx.application.Application;
+import javafx.application.Platform;
+import javafx.fxml.FXML;
+import javafx.scene.control.Alert;
+import javafx.scene.control.Alert.AlertType;
+
+
+/**
+ * TODO Add comment here
+ *
+ * @author $Author: $
+ * @version $Revision: $, $Date: $ UTC
+ */
+public class RootLayoutController
+{
+ @FXML
+ private void handelBeenden()
+ {
+ Platform.exit();
+ }
+
+ @FXML
+ private void handelModena()
+ {
+ Application.setUserAgentStylesheet(Application.STYLESHEET_MODENA);
+ }
+
+ @FXML
+ private void handelCaspian()
+ {
+ Application.setUserAgentStylesheet(Application.STYLESHEET_CASPIAN);
+ }
+
+ @FXML
+ private void handelInfo()
+ {
+ Alert info = new Alert(AlertType.INFORMATION);
+ info.setTitle("Info über das Programm");
+ info.setHeaderText("Programmierer: Stefan Suhren");
+ info.setContentText("Dieses Programm wurde programmiert.");
+ info.show();
+ }
+}