diff --git a/PhotoViewer.iml b/PhotoViewer.iml
index b8db988..c769145 100644
--- a/PhotoViewer.iml
+++ b/PhotoViewer.iml
@@ -7,6 +7,6 @@
-
+
\ No newline at end of file
diff --git a/pic/image1.jpg b/demoPics/image1.jpg
similarity index 100%
rename from pic/image1.jpg
rename to demoPics/image1.jpg
diff --git a/pic/image2.jpg b/demoPics/image2.jpg
similarity index 100%
rename from pic/image2.jpg
rename to demoPics/image2.jpg
diff --git a/pic/image3.jpg b/demoPics/image3.jpg
similarity index 100%
rename from pic/image3.jpg
rename to demoPics/image3.jpg
diff --git a/icons/left-arrow.png b/icons/left-arrow.png
new file mode 100644
index 0000000..d931587
Binary files /dev/null and b/icons/left-arrow.png differ
diff --git a/icons/right-arrow.png b/icons/right-arrow.png
new file mode 100644
index 0000000..54443e7
Binary files /dev/null and b/icons/right-arrow.png differ
diff --git a/src/de/thm/tlf/photoViewer/Controller.java b/src/de/thm/tlf/photoViewer/PVController.java
similarity index 67%
rename from src/de/thm/tlf/photoViewer/Controller.java
rename to src/de/thm/tlf/photoViewer/PVController.java
index 06b5ff5..8177f87 100644
--- a/src/de/thm/tlf/photoViewer/Controller.java
+++ b/src/de/thm/tlf/photoViewer/PVController.java
@@ -10,10 +10,12 @@ import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
+import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.*;
+import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
@@ -23,6 +25,8 @@ import javafx.stage.FileChooser;
import javafx.stage.Stage;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.util.List;
/**
@@ -31,12 +35,17 @@ import java.util.List;
*
* @author Tim Lukas Förster
* @version 1.0
+ * repository: https://gitlab.com/n0x_io/PhotoViewer
*/
-public class Controller extends Application {
+public class PVController extends Application {
////////////////////////////
//------ Attributes ------//
////////////////////////////
+ // Constants //
+ private static final String ARROWPREV = "icons/left-arrow.png";
+ private static final String ARROWNEXT = "icons/right-arrow.png";
+
// CENTER //
private final ScrollPane currentViewSP = new ScrollPane();
private final ImageView centerImageView = new ImageView();
@@ -46,17 +55,18 @@ public class Controller extends Application {
private final MenuBar menuBar = new MenuBar();
private final Menu fileMenu = new Menu("File");
private final Menu aboutMenu = new Menu("About");
- private final MenuItem openFiles = new MenuItem("Open");
- private final MenuItem clearViewer = new Menu("Close all");
- private final MenuItem startSlideShow = new MenuItem("Start Slide Show");
- private final MenuItem exitViewer = new Menu("Exit");
- private final MenuItem showInfo = new Menu("Information");
+ private final MenuItem menuItemOpenFiles = new MenuItem("Open");
+ private final MenuItem menuItemClearViewer = new Menu("Close all");
+ private final MenuItem menuItemStartSlideShow = new MenuItem("Start Slide Show");
+ private final MenuItem menuItemExitViewer = new Menu("Exit");
+ private final MenuItem menuItemShowInfo = new Menu("Information");
// BOTTOM //
private final VBox bottomPanel = new VBox();
- private final HBox selectionPane = new HBox();
- private final ScrollPane pictureSelector = new ScrollPane();
+ //private final HBox selectionPane = new HBox();
+ private final ListView previewPane = new ListView<>();
+ private final VBox pictureSelector = new VBox();
private final BorderPane bottomLowerPanel = new BorderPane();
private final HBox bottomLeft = new HBox();
@@ -77,11 +87,13 @@ public class Controller extends Application {
private PictureHandler picHandler;
// Etc. //
+ private Thread slideShowThread;
private boolean bIsFullScreen = false;
private boolean bSlideShowActive = false;
private final DoubleProperty slideShowSpeed = new SimpleDoubleProperty(4);
private final DoubleProperty zoomProperty = new SimpleDoubleProperty(200);
+ // Key Combinations & Shortcuts //
private final KeyCombination keyCrtlQ = new KeyCodeCombination(KeyCode.Q, KeyCombination.CONTROL_ANY);
////////////////////////////////
//------ End Attributes ------//
@@ -116,7 +128,7 @@ public class Controller extends Application {
// Create all Actions //
createSliderActions();
createMenuActions(primaryStage);
- createButtonActions(primaryStage);
+ createClickActions(primaryStage);
// Keypress Actions //
mainScene.setOnKeyPressed(event -> {
@@ -151,12 +163,11 @@ public class Controller extends Application {
primaryStage.show();
}
-
/**
* Task used to run the slideshow in separate Threat.
*/
@SuppressWarnings("rawtypes")
- Task slideShowTask = new Task(){
+ private final Task slideShowTask = new Task(){
@Override
@SuppressWarnings("BusyWait")
protected Void call() throws Exception {
@@ -179,10 +190,26 @@ public class Controller extends Application {
/**
* Event wrapper for clear function
- * @return EventHandle executing the clear function
+ * @return EventHandle executing the clearPreviewView function
*/
private EventHandler clearPreviewViewEvent(){
- return e -> clearPreviewView();
+ return e -> clearViewer();
+ }
+
+ /**
+ * Event wrapper for showAboutDialog function
+ * @return EventHandle executing the showAboutDialog function
+ */
+ private EventHandler showAboutDialogEvent(){
+ return e -> showAboutDialog();
+ }
+
+ /**
+ * Event wrapper for showAboutDialog function
+ * @return EventHandle executing the showAboutDialog function
+ */
+ private EventHandler toggleSlidesHowEvent(){
+ return e -> toggleSlideShow();
}
////////////////////////////////
@@ -192,6 +219,7 @@ public class Controller extends Application {
* Helper method for handling sliders
*/
private void createSliderActions() {
+ //TODO: Zoom kinda wonky... should be redone.
// Zoom Action //
zoomProperty.addListener(observable -> {
centerImageView.setFitWidth(zoomProperty.get() * 4);
@@ -217,18 +245,22 @@ public class Controller extends Application {
* @param stage the primary stage, used to display the file-open-dialog
*/
private void createMenuActions(Stage stage) {
- openFiles.setOnAction(openFileDialogEvent(stage));
- exitViewer.setOnAction( e -> Platform.exit());
- clearViewer.setOnAction(clearPreviewViewEvent());
+ menuItemOpenFiles.setOnAction(openFileDialogEvent(stage));
+ menuItemExitViewer.setOnAction(e -> Platform.exit());
+ menuItemClearViewer.setOnAction(clearPreviewViewEvent());
+ menuItemStartSlideShow.setOnAction(toggleSlidesHowEvent());
+ menuItemShowInfo.setOnAction(showAboutDialogEvent());
}
/**
* Helper method for handling button interaction
* @param stage the primary stage, used to display the file-open-dialog and control fullscreen functions
*/
- private void createButtonActions(Stage stage) {
+ private void createClickActions(Stage stage) {
+ // Opens the File dialog
openFilesButton.setOnAction(openFileDialogEvent(stage));
+ // Displays the previous Picture
prevPicBtn.setOnAction(e -> {
try{
centerImageView.setImage(picHandler.getPrevPicture().getImage());
@@ -236,6 +268,7 @@ public class Controller extends Application {
catch (NoPicturesLoadedException npl){ showNoPicturesLoadedWarning();}
});
+ // Displays the next picture
nextPicBtn.setOnAction(e -> {
try{
centerImageView.setImage(picHandler.getNextPicture().getImage());
@@ -243,36 +276,54 @@ public class Controller extends Application {
catch (NoPicturesLoadedException npl){ showNoPicturesLoadedWarning();}
});
+ // Sets the PictureViewer to fullscreen
fullScreenBtn.setOnAction(e -> {
stage.setFullScreen(!bIsFullScreen);
bIsFullScreen ^= true;
});
- slideShowBtn.setOnAction(new EventHandler<>() {
- Thread th;
+ //slideShowBtn.setOnAction( });
+
+ // Starts the slideshow on first click, stops it on the next one
+ slideShowBtn.setOnAction(toggleSlidesHowEvent());
+
+ // Clicking on any picture in the Previews opens said picture in the main view
+ previewPane.setOnMouseClicked(e -> {
+ try {
+ centerImageView.setImage(picHandler.getPictureByID(previewPane.getSelectionModel().getSelectedIndex()).getImage());
+ } catch (NoPicturesLoadedException ignored) {
- @Override
- public void handle(ActionEvent actionEvent) {
- try {
- if (!bSlideShowActive) {
- // This statement is to catch any errors regarding no images loaded
- centerImageView.setImage(picHandler.getNextPicture().getImage());
- bSlideShowActive = true;
- slideShowBtn.setText("Stop Slide Show");
- th = new Thread(slideShowTask);
- th.start();
- } else {
- bSlideShowActive = false;
- slideShowBtn.setText("Slide Show");
- th.interrupt();
- }
- } catch (NoPicturesLoadedException npl){
- showNoPicturesLoadedWarning();
- }
}
});
}
+ /**
+ * Method that will start and stop (toggle) the Slide show and set the corresponding texts to all buttons etc.
+ */
+ private void toggleSlideShow(){
+ try {
+ if (!bSlideShowActive) {
+ // This statement is to catch any errors regarding no images loaded
+ centerImageView.setImage(picHandler.getNextPicture().getImage());
+ bSlideShowActive = true;
+ slideShowThread = new Thread(slideShowTask);
+ slideShowThread.start();
+ // Change text of slideshow switches
+ slideShowBtn.setText("Stop Slide Show");
+ menuItemStartSlideShow.setText("Stop Slide Show");
+ } else {
+ bSlideShowActive = false;
+ // Change text of slideshow switches
+ slideShowBtn.setText("Slide Show");
+ menuItemStartSlideShow.setText("Slide Show");
+ assert slideShowThread != null;
+ slideShowThread.interrupt();
+ }
+ } catch (NoPicturesLoadedException npl){
+ showNoPicturesLoadedWarning();
+ }
+ }
+
/**
* Open file-dialog allowing to select multiple pictures (via filter),
* adds them to the PictureHandler and updates the picture preview
@@ -287,7 +338,7 @@ public class Controller extends Application {
if (selectedPictures != null) {
try {
picHandler.loadPictures(selectedPictures);
- Controller.this.updatePreviewView();
+ PVController.this.updatePreviewView();
centerImageView.setImage(picHandler.getNextPicture().getImage());
} catch (NoPicturesLoadedException npl) {
showNoPicturesLoadedWarning();
@@ -299,26 +350,55 @@ public class Controller extends Application {
* Method that updates the preview Pane with all PreviewPictures provided by the Picture Handler
*/
private void updatePreviewView(){
- clearPreviewView();
- selectionPane.setPadding(new Insets(5,5,5,5));
+ clearViewer();
+ //previewPane.setPadding(new Insets(5,5,5,5));
for(PicturePreview pp: picHandler.getPreviews()){
ImageView iv = new ImageView(pp.getImage());
iv.setFitWidth(150);
iv.setSmooth(true);
iv.setPreserveRatio(true);
- selectionPane.getChildren().add(iv);
+ previewPane.getItems().add(iv);
}
}
/**
- * Used to clear the preview and center panel when the viewer is cleared
+ * Used to clear the preview and center panel
*/
- private void clearPreviewView(){
- selectionPane.getChildren().clear();
- selectionPane.setPadding(new Insets(5,155,5,5));
+ private void clearViewer(){
+ previewPane.getItems().clear();
+ //previewPane.setPadding(new Insets(5,5,5,5));
centerImageView.setImage(null);
}
+ /**
+ * Show a dialogue displaying copyright information about the program.
+ */
+ private void showAboutDialog(){
+ Dialog aboutDialog = new Dialog<>();
+ aboutDialog.setTitle("About this program");
+ ButtonType btnType = new ButtonType("Ok", ButtonBar.ButtonData.OK_DONE);
+ aboutDialog.setContentText("""
+ Created by Tim Lukas Förster
+ Icons made by www.flaticon.com/authors/roundicons for www.flaticon.com""");
+
+
+ //Adding buttons to the aboutDialog pane
+ aboutDialog.getDialogPane().getButtonTypes().add(btnType);
+ }
+
+ /**
+ * Displays a warning dialogue informing the user that no pictures has been loaded yet
+ * and the executed action is not possible.
+ */
+ private void showNoPicturesLoadedWarning(){
+ Alert alert = new Alert(Alert.AlertType.WARNING);
+ alert.setTitle("No pictures loaded");
+ alert.setContentText("No pictures have been loaded" +
+ "\nPlease select pictures via the menu or via the open button to view them.");
+ alert.showAndWait().ifPresent(rs -> {
+ });
+ }
+
/**
* Method that handles the settings and layout of the top Panel
* @return Node, set up for displaying on the top of a GridPane
@@ -326,9 +406,9 @@ public class Controller extends Application {
private Node createTop(){
SeparatorMenuItem sep = new SeparatorMenuItem();
// File Menu
- fileMenu.getItems().addAll(openFiles, clearViewer, sep, startSlideShow, exitViewer);
+ fileMenu.getItems().addAll(menuItemOpenFiles, menuItemClearViewer, sep, menuItemStartSlideShow, menuItemExitViewer);
// About Menu
- aboutMenu.getItems().addAll(showInfo);
+ aboutMenu.getItems().addAll(menuItemShowInfo);
// Menu bar
menuBar.getMenus().addAll(fileMenu, aboutMenu);
// Adding Menus to Top Panel
@@ -372,11 +452,31 @@ public class Controller extends Application {
zoomSlider.setShowTickMarks(true);
Label zoomLabel = new Label("Zoom:");
bottomLeft.getChildren().addAll(openFilesButton, zoomLabel, zoomSlider);
- //bottomLeft.getChildren().addAll(zoomLabel, zoomSlider);
bottomLeft.setSpacing(5);
bottomLowerPanel.setLeft(bottomLeft);
// Middle Bottom Part
+ try {
+ // Set pictures as prev/next buttons
+ ImageView prevPic = new ImageView(new Image(new FileInputStream(ARROWPREV)));
+ prevPic.setFitHeight(10);
+ prevPic.setPreserveRatio(true);
+ prevPicBtn.setText(null);
+ prevPicBtn.setGraphic(prevPic);
+
+ ImageView nextPic = new ImageView(new Image(new FileInputStream(ARROWNEXT)));
+ nextPic.setFitHeight(10);
+ nextPic.setPreserveRatio(true);
+ nextPicBtn.setText(null);
+ nextPicBtn.setGraphic(nextPic);
+ } catch (FileNotFoundException ignored){
+ // fallback to text
+ prevPicBtn.setGraphic(null);
+ nextPicBtn.setGraphic(null);
+
+ prevPicBtn.setText("<-");
+ nextPicBtn.setText("->");
+ }
bottomMid.setAlignment(Pos.CENTER);
bottomMid.setSpacing(5);
bottomMid.getChildren().addAll(prevPicBtn, slideShowBtn, nextPicBtn);
@@ -391,28 +491,16 @@ public class Controller extends Application {
bottomLowerPanel.setRight(bottomRight);
// Bottom upper Part -> Picture preview
- selectionPane.setPadding(new Insets(5,5,155,5));
- selectionPane.autosize();
- selectionPane.setSpacing(5);
- pictureSelector.setContent(selectionPane);
+ pictureSelector.setPadding(new Insets(2,2,2,2));
+ previewPane.setOrientation(Orientation.HORIZONTAL);
+ previewPane.setMaxHeight(150);
+ //selectionPane.setSpacing(5);
+ pictureSelector.getChildren().add(previewPane);
bottomPanel.getChildren().addAll(pictureSelector, bottomLowerPanel);
return (bottomPanel);
}
-
- /**
- * Displays a warning dialogue informing the user that no pictures has been loaded yet
- * and the executed action is not possible.
- */
- private void showNoPicturesLoadedWarning(){
- Alert alert = new Alert(Alert.AlertType.WARNING);
- alert.setTitle("No pictures loaded");
- alert.setContentText("No pictures have been loaded" +
- "\nPlease select pictures via the menu or via the open button to view them.");
- alert.showAndWait().ifPresent(rs -> {
- });
- }
////////////////////////////////////
//------ End Helper-Methods ------//
////////////////////////////////////
diff --git a/src/de/thm/tlf/photoViewer/PictureHandler.java b/src/de/thm/tlf/photoViewer/PictureHandler.java
index fbf0653..51bac9c 100644
--- a/src/de/thm/tlf/photoViewer/PictureHandler.java
+++ b/src/de/thm/tlf/photoViewer/PictureHandler.java
@@ -62,7 +62,8 @@ public final class PictureHandler {
}
/**
- * Determines the next picture that should be displayed
+ * Determines the next picture that should be displayed.
+ * Wraps around to the beginning of the list if picture after the last one is requested.
* @return Picture object that should be displayed next from the ArrayList pictures
* @throws NoPicturesLoadedException Exception for when no pictures are loaded yet but tried to access them
*/
@@ -77,7 +78,8 @@ public final class PictureHandler {
}
/**
- * Determines the previous picture that should be displayed
+ * Determines the previous picture that should be displayed.
+ * Wraps around to the end of the list if picture before the first one is requested.
* @return Picture object that should be displayed next from the ArrayList pictures
* @throws NoPicturesLoadedException Exception for when no pictures are loaded yet but tried to access them
*/
@@ -90,6 +92,21 @@ public final class PictureHandler {
return pictures.get(currentPictureID);
}
}
+
+ /**
+ * Method to acquire picture by the list-ID of a picture
+ * @param pictureID the ID of the Picture that is being requested
+ * @return Picture from the pictures ArrayList on position of the provided ID
+ * @throws NoPicturesLoadedException Exception for when no pictures are loaded yet but tried to access them
+ */
+ public Picture getPictureByID(int pictureID) throws NoPicturesLoadedException{
+ if(pictures.size() <= 0){
+ throw new NoPicturesLoadedException("No pictures have been loaded");
+ }
+ else {
+ return pictures.get(pictureID);
+ }
+ }
//------ End Methods ------//
}