From b5f378072e9d9812ecb974961ed3bda1e2b1511f Mon Sep 17 00:00:00 2001 From: selfomat Date: Mon, 28 Sep 2020 18:07:49 +0200 Subject: [PATCH] move to git.simongehrig.de --- .idea/compiler.xml | 20 +- .idea/encodings.xml | 1 + .idea/inspectionProfiles/Project_Default.xml | 1113 +++++++++++++++++ .../Maven__com_google_guava_guava_14_0_1.xml | 13 + .idea/libraries/Maven__junit_junit_4_10.xml | 13 + .../Maven__org_hamcrest_hamcrest_all_1_3.xml | 13 + ...nit_jupiter_junit_jupiter_api_5_0_0_M4.xml | 13 + ..._jupiter_junit_jupiter_engine_5_0_0_M4.xml | 13 + ...atform_junit_platform_commons_1_0_0_M4.xml | 13 + ...latform_junit_platform_engine_1_0_0_M4.xml | 13 + ...tform_junit_platform_launcher_1_0_0_M4.xml | 13 + ...latform_junit_platform_runner_1_0_0_M4.xml | 13 + ...form_junit_platform_suite_api_1_0_0_M4.xml | 13 + .../Maven__org_loadui_testFx_3_0_0.xml | 13 + ...en__org_opentest4j_opentest4j_1_0_0_M2.xml | 13 + .idea/libraries/commons_io_commons_io_2_4.xml | 10 - .idea/misc.xml | 21 +- pom.xml | 62 +- selfomat-single-user.iml | 14 +- src/main/java/GUI/CaptureCtl.java | 24 +- src/main/java/GUI/GalleryCtl.java | 33 +- src/main/java/GUI/PictureCtl.java | 44 +- src/main/java/GUI/SOMGUI.java | 10 +- src/main/java/GUI/UploadCtl.java | 18 +- src/main/java/model/SOMConfig.java | 5 +- src/main/java/model/SOMConfigFileHandler.java | 5 - src/main/java/model/SOMEvent.java | 24 +- src/main/java/model/SOMImage.java | 124 +- src/main/java/model/SOMLayout.java | 38 +- src/main/java/workers/FilesWorker.java | 197 +-- src/main/java/workers/MachineWorker.java | 30 +- src/main/java/workers/ScaleWorker.java | 44 +- .../resources/fonts/CenturyGothicStd-Bold.otf | Bin 0 -> 29676 bytes src/main/resources/fonts/CenturyGothicStd.otf | Bin 0 -> 29592 bytes src/main/resources/fxml/gallery.fxml | 2 + src/test/java/TestRunner.java | 18 + src/test/java/TestSuite.java | 16 + src/test/java/settings.cnf | 0 src/test/java/workers/FilesWorkerTest.java | 75 ++ src/test/java/workers/MachineWorkerTest.java | 20 + src/test/java/workers/ScaleWorkerTest.java | 173 +++ src/test/resources/img/00001.jpg | Bin 0 -> 363303 bytes src/test/resources/img/00002.jpg | Bin 0 -> 249760 bytes src/test/resources/img/00003.jpg | Bin 0 -> 207258 bytes src/test/resources/img/00004.jpg | Bin 0 -> 669991 bytes src/test/resources/misc/NoImage.html | 10 + 46 files changed, 1985 insertions(+), 322 deletions(-) create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/libraries/Maven__com_google_guava_guava_14_0_1.xml create mode 100644 .idea/libraries/Maven__junit_junit_4_10.xml create mode 100644 .idea/libraries/Maven__org_hamcrest_hamcrest_all_1_3.xml create mode 100644 .idea/libraries/Maven__org_junit_jupiter_junit_jupiter_api_5_0_0_M4.xml create mode 100644 .idea/libraries/Maven__org_junit_jupiter_junit_jupiter_engine_5_0_0_M4.xml create mode 100644 .idea/libraries/Maven__org_junit_platform_junit_platform_commons_1_0_0_M4.xml create mode 100644 .idea/libraries/Maven__org_junit_platform_junit_platform_engine_1_0_0_M4.xml create mode 100644 .idea/libraries/Maven__org_junit_platform_junit_platform_launcher_1_0_0_M4.xml create mode 100644 .idea/libraries/Maven__org_junit_platform_junit_platform_runner_1_0_0_M4.xml create mode 100644 .idea/libraries/Maven__org_junit_platform_junit_platform_suite_api_1_0_0_M4.xml create mode 100644 .idea/libraries/Maven__org_loadui_testFx_3_0_0.xml create mode 100644 .idea/libraries/Maven__org_opentest4j_opentest4j_1_0_0_M2.xml delete mode 100644 .idea/libraries/commons_io_commons_io_2_4.xml create mode 100644 src/main/resources/fonts/CenturyGothicStd-Bold.otf create mode 100644 src/main/resources/fonts/CenturyGothicStd.otf create mode 100644 src/test/java/TestRunner.java create mode 100644 src/test/java/TestSuite.java delete mode 100644 src/test/java/settings.cnf create mode 100644 src/test/java/workers/FilesWorkerTest.java create mode 100644 src/test/java/workers/MachineWorkerTest.java create mode 100644 src/test/java/workers/ScaleWorkerTest.java create mode 100644 src/test/resources/img/00001.jpg create mode 100644 src/test/resources/img/00002.jpg create mode 100644 src/test/resources/img/00003.jpg create mode 100644 src/test/resources/img/00004.jpg create mode 100644 src/test/resources/misc/NoImage.html diff --git a/.idea/compiler.xml b/.idea/compiler.xml index a9e1831..515168c 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,32 +1,16 @@ - - - - - - - - - - - - - - - - + - - + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml index 3cee6c5..92257e7 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -1,6 +1,7 @@ + diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..780641d --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,1113 @@ + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_google_guava_guava_14_0_1.xml b/.idea/libraries/Maven__com_google_guava_guava_14_0_1.xml new file mode 100644 index 0000000..b71e220 --- /dev/null +++ b/.idea/libraries/Maven__com_google_guava_guava_14_0_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__junit_junit_4_10.xml b/.idea/libraries/Maven__junit_junit_4_10.xml new file mode 100644 index 0000000..ed8bf5f --- /dev/null +++ b/.idea/libraries/Maven__junit_junit_4_10.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_hamcrest_hamcrest_all_1_3.xml b/.idea/libraries/Maven__org_hamcrest_hamcrest_all_1_3.xml new file mode 100644 index 0000000..5619316 --- /dev/null +++ b/.idea/libraries/Maven__org_hamcrest_hamcrest_all_1_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_api_5_0_0_M4.xml b/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_api_5_0_0_M4.xml new file mode 100644 index 0000000..9d5417b --- /dev/null +++ b/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_api_5_0_0_M4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_engine_5_0_0_M4.xml b/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_engine_5_0_0_M4.xml new file mode 100644 index 0000000..ef0909d --- /dev/null +++ b/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_engine_5_0_0_M4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_junit_platform_junit_platform_commons_1_0_0_M4.xml b/.idea/libraries/Maven__org_junit_platform_junit_platform_commons_1_0_0_M4.xml new file mode 100644 index 0000000..1f0a149 --- /dev/null +++ b/.idea/libraries/Maven__org_junit_platform_junit_platform_commons_1_0_0_M4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_junit_platform_junit_platform_engine_1_0_0_M4.xml b/.idea/libraries/Maven__org_junit_platform_junit_platform_engine_1_0_0_M4.xml new file mode 100644 index 0000000..9908811 --- /dev/null +++ b/.idea/libraries/Maven__org_junit_platform_junit_platform_engine_1_0_0_M4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_junit_platform_junit_platform_launcher_1_0_0_M4.xml b/.idea/libraries/Maven__org_junit_platform_junit_platform_launcher_1_0_0_M4.xml new file mode 100644 index 0000000..c68fd66 --- /dev/null +++ b/.idea/libraries/Maven__org_junit_platform_junit_platform_launcher_1_0_0_M4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_junit_platform_junit_platform_runner_1_0_0_M4.xml b/.idea/libraries/Maven__org_junit_platform_junit_platform_runner_1_0_0_M4.xml new file mode 100644 index 0000000..2b3c315 --- /dev/null +++ b/.idea/libraries/Maven__org_junit_platform_junit_platform_runner_1_0_0_M4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_junit_platform_junit_platform_suite_api_1_0_0_M4.xml b/.idea/libraries/Maven__org_junit_platform_junit_platform_suite_api_1_0_0_M4.xml new file mode 100644 index 0000000..4e2c02e --- /dev/null +++ b/.idea/libraries/Maven__org_junit_platform_junit_platform_suite_api_1_0_0_M4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_loadui_testFx_3_0_0.xml b/.idea/libraries/Maven__org_loadui_testFx_3_0_0.xml new file mode 100644 index 0000000..ca10a5b --- /dev/null +++ b/.idea/libraries/Maven__org_loadui_testFx_3_0_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_opentest4j_opentest4j_1_0_0_M2.xml b/.idea/libraries/Maven__org_opentest4j_opentest4j_1_0_0_M2.xml new file mode 100644 index 0000000..c237915 --- /dev/null +++ b/.idea/libraries/Maven__org_opentest4j_opentest4j_1_0_0_M2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/commons_io_commons_io_2_4.xml b/.idea/libraries/commons_io_commons_io_2_4.xml deleted file mode 100644 index 9ca89f9..0000000 --- a/.idea/libraries/commons_io_commons_io_2_4.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 8d8fd52..0e3abdc 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -38,8 +38,23 @@ - - + + - + diff --git a/pom.xml b/pom.xml index ca1dadc..bd2c450 100644 --- a/pom.xml +++ b/pom.xml @@ -3,11 +3,12 @@ 4.0.0 de.selfomat selfomat-single-user - 0.4.1.2-SNAPSHOT + 0.4.2.0-SNAPSHOT scm:git:http://192.168.100.78/git/selfomat-software.git + @@ -30,12 +31,62 @@ 3.2.1 + + + + + + + + + + + + + + + + + + + + + + org.loadui + testFx + 3.0.0 + + + + + + + + + + org.junit.jupiter + junit-jupiter-engine + ${junit.jupiter.version} + + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test + selfomat single user Photobooth Software + + UTF-8 + 1.8 + 5.0.0-M4 + 1.0.0-M4 + + @@ -61,7 +112,16 @@ + + maven-compiler-plugin + 3.1 + + ${java.version} + ${java.version} + + + src/main/resources diff --git a/selfomat-single-user.iml b/selfomat-single-user.iml index ef9182f..ebeeeb4 100644 --- a/selfomat-single-user.iml +++ b/selfomat-single-user.iml @@ -1,6 +1,6 @@ - + @@ -19,5 +19,17 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/GUI/CaptureCtl.java b/src/main/java/GUI/CaptureCtl.java index a578aed..0ed3926 100644 --- a/src/main/java/GUI/CaptureCtl.java +++ b/src/main/java/GUI/CaptureCtl.java @@ -14,7 +14,6 @@ import model.SOMEvent; import model.SOMImage; import model.SOMLayout; import workers.FilesWorker; -import workers.ScaleWorker; import java.util.Timer; import java.util.TimerTask; @@ -53,10 +52,10 @@ public class CaptureCtl { private void setPictureLoadIndicator() { pictureLoadIndicator.setVisible(false); - pictureLoadIndicator.setPrefHeight(SOMLayout.screenHeight / 4); - pictureLoadIndicator.setPrefWidth(SOMLayout.screenHeight / 4); + pictureLoadIndicator.setPrefHeight(SOMLayout.SCREEN_HEIGHT / 4); + pictureLoadIndicator.setPrefWidth(SOMLayout.SCREEN_HEIGHT / 4); - pictureLoadIndicator.setMaxSize(SOMLayout.screenHeight / 2, SOMLayout.screenHeight / 2); + pictureLoadIndicator.setMaxSize(SOMLayout.SCREEN_HEIGHT / 2, SOMLayout.SCREEN_HEIGHT / 2); pictureLoadIndicator.setStyle("-fx-progress-color: white;"); } @@ -66,11 +65,11 @@ public class CaptureCtl { capturePane.setAlignment(Pos.CENTER); countdownText.setAlignment(Pos.CENTER); - countdownText.setPrefSize(SOMLayout.screenHeight / 2, SOMLayout.screenHeight / 2); - countdownText.setBackground(SOMLayout.getTransparentBG20rounded(SOMLayout.screenHeight / 4)); + countdownText.setPrefSize(SOMLayout.SCREEN_HEIGHT / 2, SOMLayout.SCREEN_HEIGHT / 2); + countdownText.setBackground(SOMLayout.getTransparentBG20rounded(SOMLayout.SCREEN_HEIGHT / 4)); countdownText.setText(null); - countdownText.setFont(new Font("Century Gothic Bold", SOMLayout.screenHeight / 4)); + countdownText.setFont(new Font("Century Gothic Bold", SOMLayout.SCREEN_HEIGHT / 4)); countdownText.setTextFill(SOMLayout.WHITE); } @@ -86,12 +85,12 @@ public class CaptureCtl { image.setImage(SOMLayout.LOGO_IMAGE); // make it fit the height of the Screen -// image.setFitWidth(SOMLayout.screenHeight / 2); +// image.setFitWidth(SOMLayout.SCREEN_HEIGHT / 2); // Calculate the offset to center it horizontally if the image is wider than the screen (or narrower) double aspect = image.getImage().getWidth() / image.getImage().getHeight(); - double scaledWidth = aspect * SOMLayout.screenHeight; - double offset = (scaledWidth - SOMLayout.screenWidth) / 2; + double scaledWidth = aspect * SOMLayout.SCREEN_HEIGHT; + double offset = (scaledWidth - SOMLayout.SCREEN_WIDTH) / 2; image.setX(-offset); } @@ -226,15 +225,10 @@ public class CaptureCtl { // Capture the image SOMImage newImage = FilesWorker.waitForImageAndCapture(); - //Scale the image to preview - ScaleWorker.scale(newImage, ScaleWorker.PREVIEW); // set te image to UI image.setImage(new Image(newImage.getPrv().toURI().toString())); SOMGUI.pictureCtl.image.setImage(new Image(newImage.getPrv().toURI().toString())); - // trigger the thumb calculation - ScaleWorker.scale(newImage, ScaleWorker.THUMBNAIL); - } // diff --git a/src/main/java/GUI/GalleryCtl.java b/src/main/java/GUI/GalleryCtl.java index 1a807a1..fe514ff 100644 --- a/src/main/java/GUI/GalleryCtl.java +++ b/src/main/java/GUI/GalleryCtl.java @@ -129,7 +129,6 @@ public class GalleryCtl { SOMEvent.getInstance().createAndSetImage(somPageImagesArray[finalI]); } }); - i++; } } @@ -140,8 +139,8 @@ public class GalleryCtl { imageView.setPreserveRatio(true); // make it fit the height of the Screen - imageView.setFitHeight(SOMLayout.screenHeight / 3); - imageView.setFitWidth(SOMLayout.screenWidth / 4); + imageView.setFitHeight(SOMLayout.SCREEN_HEIGHT / 3); + imageView.setFitWidth(SOMLayout.SCREEN_WIDTH / 4); // position the images in Center GridPane.setValignment(imageView, VPos.CENTER); @@ -150,22 +149,22 @@ public class GalleryCtl { } public void setPane() { - pane.setPrefSize(SOMLayout.screenWidth, SOMLayout.screenHeight); - pane.setMinSize(SOMLayout.screenWidth, SOMLayout.screenHeight); + pane.setPrefSize(SOMLayout.SCREEN_WIDTH, SOMLayout.SCREEN_HEIGHT); + pane.setMinSize(SOMLayout.SCREEN_WIDTH, SOMLayout.SCREEN_HEIGHT); pane.setBackground(SOMLayout.BLACK_BG); } public void setGrid() { - grid.setPrefHeight(SOMLayout.screenHeight); - grid.setPrefWidth(SOMLayout.screenWidth); - grid.setMinSize(SOMLayout.screenWidth, SOMLayout.screenHeight); + grid.setPrefHeight(SOMLayout.SCREEN_HEIGHT); + grid.setPrefWidth(SOMLayout.SCREEN_WIDTH); + grid.setMinSize(SOMLayout.SCREEN_WIDTH, SOMLayout.SCREEN_HEIGHT); } public void setForthButton() { // get the button height & width - int height = (SOMLayout.screenHeight / 4); + int height = (SOMLayout.SCREEN_HEIGHT / 4); // set alignment GridPane.setHalignment(forthButton, HPos.CENTER); GridPane.setValignment(forthButton, VPos.CENTER); @@ -188,7 +187,7 @@ public class GalleryCtl { forthButton.setOnMousePressed(new EventHandler() { public void handle(MouseEvent event) { // Feedback - forthButton.setBackground(SOMLayout.getTransparentBG20rounded(SOMLayout.screenHeight / 4)); + forthButton.setBackground(SOMLayout.getTransparentBG20rounded(SOMLayout.SCREEN_HEIGHT / 4)); } }); @@ -197,7 +196,7 @@ public class GalleryCtl { public void handle(MouseEvent event) { // Feedback - forthButton.setBackground(SOMLayout.getTransparentBG10rounded(SOMLayout.screenHeight / 4)); + forthButton.setBackground(SOMLayout.getTransparentBG10rounded(SOMLayout.SCREEN_HEIGHT / 4)); // Action action(); @@ -213,7 +212,7 @@ public class GalleryCtl { public void setBackButton() { // get the button height & width - int height = (SOMLayout.screenHeight / 4); + int height = (SOMLayout.SCREEN_HEIGHT / 4); // set alignment GridPane.setHalignment(backButton, HPos.CENTER); GridPane.setValignment(backButton, VPos.CENTER); @@ -236,7 +235,7 @@ public class GalleryCtl { backButton.setOnMousePressed(new EventHandler() { public void handle(MouseEvent event) { // Feedback - backButton.setBackground(SOMLayout.getTransparentBG20rounded(SOMLayout.screenHeight / 4)); + backButton.setBackground(SOMLayout.getTransparentBG20rounded(SOMLayout.SCREEN_HEIGHT / 4)); } }); @@ -245,7 +244,7 @@ public class GalleryCtl { public void handle(MouseEvent event) { // Feedback - backButton.setBackground(SOMLayout.getTransparentBG10rounded(SOMLayout.screenHeight / 4)); + backButton.setBackground(SOMLayout.getTransparentBG10rounded(SOMLayout.SCREEN_HEIGHT / 4)); // Action action(); @@ -261,7 +260,7 @@ public class GalleryCtl { public void setPictureButton() { // get the button height & width - int height = (SOMLayout.screenHeight / 4); + int height = (SOMLayout.SCREEN_HEIGHT / 4); // set alignment GridPane.setHalignment(pictureButton, HPos.CENTER); GridPane.setValignment(pictureButton, VPos.CENTER); @@ -284,7 +283,7 @@ public class GalleryCtl { pictureButton.setOnMousePressed(new EventHandler() { public void handle(MouseEvent event) { // Feedback - pictureButton.setBackground(SOMLayout.getTransparentBG20rounded(SOMLayout.screenHeight / 4)); + pictureButton.setBackground(SOMLayout.getTransparentBG20rounded(SOMLayout.SCREEN_HEIGHT / 4)); } }); @@ -293,7 +292,7 @@ public class GalleryCtl { public void handle(MouseEvent event) { // Feedback - pictureButton.setBackground(SOMLayout.getTransparentBG10rounded(SOMLayout.screenHeight / 4)); + pictureButton.setBackground(SOMLayout.getTransparentBG10rounded(SOMLayout.SCREEN_HEIGHT / 4)); // Action action(); diff --git a/src/main/java/GUI/PictureCtl.java b/src/main/java/GUI/PictureCtl.java index e023a04..8565ae5 100644 --- a/src/main/java/GUI/PictureCtl.java +++ b/src/main/java/GUI/PictureCtl.java @@ -64,12 +64,12 @@ public class PictureCtl { } private void setPane() { - pane.setPrefSize(SOMLayout.screenWidth, SOMLayout.screenHeight); + pane.setPrefSize(SOMLayout.SCREEN_WIDTH, SOMLayout.SCREEN_HEIGHT); pane.setBackground(SOMLayout.BLACK_BG); } private void setGrid() { - grid.setPrefSize(SOMLayout.screenWidth, SOMLayout.screenHeight); + grid.setPrefSize(SOMLayout.SCREEN_WIDTH, SOMLayout.SCREEN_HEIGHT); grid.setAlignment(Pos.CENTER); @@ -80,7 +80,7 @@ public class PictureCtl { private void setSingleBtn() { // get the button height & width - int height = (SOMLayout.screenHeight / 4); + int height = (SOMLayout.SCREEN_HEIGHT / 4); // set the Button height & width singleBtn.setPrefSize(height, height); @@ -100,7 +100,7 @@ public class PictureCtl { // Set the Action to run after Button is Pressed EventHandler singleCapturePressedEventHandler = new EventHandler() { public void handle(MouseEvent event) { - singleBtn.setBackground(SOMLayout.getTransparentBG20rounded(SOMLayout.screenHeight / 4)); + singleBtn.setBackground(SOMLayout.getTransparentBG20rounded(SOMLayout.SCREEN_HEIGHT / 4)); } }; @@ -109,7 +109,7 @@ public class PictureCtl { public void handle(MouseEvent event) { // Feedback (button gets less transparent) - singleBtn.setBackground(SOMLayout.getTransparentBG10rounded(SOMLayout.screenHeight / 4)); + singleBtn.setBackground(SOMLayout.getTransparentBG10rounded(SOMLayout.SCREEN_HEIGHT / 4)); // Action action(); @@ -137,7 +137,7 @@ public class PictureCtl { private void setSeriesBtn() { // get the button height & width - int height = (SOMLayout.screenHeight / 4); + int height = (SOMLayout.SCREEN_HEIGHT / 4); // set the Button height & width seriesBtn.setPrefSize(height, height); @@ -159,7 +159,7 @@ public class PictureCtl { EventHandler seriesCapturePressedEventHandler = new EventHandler() { public void handle(MouseEvent event) { // Feedback (Button gets lesstransparent) - seriesBtn.setBackground(SOMLayout.getTransparentBG20rounded(SOMLayout.screenHeight / 4)); + seriesBtn.setBackground(SOMLayout.getTransparentBG20rounded(SOMLayout.SCREEN_HEIGHT / 4)); } }; //Set Action after series Button is released @@ -167,7 +167,7 @@ public class PictureCtl { public void handle(MouseEvent event) { // Feedback (Button gets less transparent) - seriesBtn.setBackground(SOMLayout.getTransparentBG10rounded(SOMLayout.screenHeight / 4)); + seriesBtn.setBackground(SOMLayout.getTransparentBG10rounded(SOMLayout.SCREEN_HEIGHT / 4)); // Shoot series (true means series Mode) SOMGUI.captureCtl.shoot(true); @@ -177,7 +177,7 @@ public class PictureCtl { EventHandler seriesCapturePressedTouchEventHandler = new EventHandler() { public void handle(TouchEvent event) { // Feedback (Button gets lesstransparent) - seriesBtn.setBackground(SOMLayout.getTransparentBG20rounded(SOMLayout.screenHeight / 4)); + seriesBtn.setBackground(SOMLayout.getTransparentBG20rounded(SOMLayout.SCREEN_HEIGHT / 4)); } }; //Set Action after series Button is released @@ -185,7 +185,7 @@ public class PictureCtl { public void handle(TouchEvent event) { // Feedback (Button gets less transparent) - seriesBtn.setBackground(SOMLayout.getTransparentBG10rounded(SOMLayout.screenHeight / 4)); + seriesBtn.setBackground(SOMLayout.getTransparentBG10rounded(SOMLayout.SCREEN_HEIGHT / 4)); // Shoot series (true means series Mode) SOMGUI.captureCtl.shoot(true); @@ -206,7 +206,7 @@ public class PictureCtl { private void setGalleryBtn() { // get the button height & width - int height = (SOMLayout.screenHeight / 4); + int height = (SOMLayout.SCREEN_HEIGHT / 4); // set the Button height & width galleryBtn.setPrefSize(height, height); @@ -227,7 +227,7 @@ public class PictureCtl { galleryBtn.setOnMousePressed(new EventHandler() { public void handle(MouseEvent event) { // Feedback - galleryBtn.setBackground(SOMLayout.getTransparentBG20rounded(SOMLayout.screenHeight / 4)); + galleryBtn.setBackground(SOMLayout.getTransparentBG20rounded(SOMLayout.SCREEN_HEIGHT / 4)); } }); @@ -236,7 +236,7 @@ public class PictureCtl { public void handle(MouseEvent event) { // Feedback - galleryBtn.setBackground(SOMLayout.getTransparentBG10rounded(SOMLayout.screenHeight / 4)); + galleryBtn.setBackground(SOMLayout.getTransparentBG10rounded(SOMLayout.SCREEN_HEIGHT / 4)); // Action action(); @@ -253,7 +253,7 @@ public class PictureCtl { if (SOMConfig.PRINTER == true) { // get the button height & width - int height = (SOMLayout.screenHeight / 4); + int height = (SOMLayout.SCREEN_HEIGHT / 4); // set the Button height & width printBtn.setPrefSize(height, height); @@ -274,7 +274,7 @@ public class PictureCtl { printBtn.setOnMousePressed(new EventHandler() { public void handle(MouseEvent event) { // Feedback - printBtn.setBackground(SOMLayout.getTransparentBG20rounded(SOMLayout.screenHeight / 4)); + printBtn.setBackground(SOMLayout.getTransparentBG20rounded(SOMLayout.SCREEN_HEIGHT / 4)); } }); @@ -290,7 +290,7 @@ public class PictureCtl { public void handle(MouseEvent event) { // Feedback - printBtn.setBackground(SOMLayout.getTransparentBG10rounded(SOMLayout.screenHeight / 4)); + printBtn.setBackground(SOMLayout.getTransparentBG10rounded(SOMLayout.SCREEN_HEIGHT / 4)); // Action action(); @@ -315,7 +315,7 @@ public class PictureCtl { // image.setImage(splash); // // // make it fit the height of the Screen -// image.setFitWidth(SOMLayout.screenHeight/2); +// image.setFitWidth(SOMLayout.SCREEN_HEIGHT/2); // Set the image aspect ratio to be preserved image.setPreserveRatio(true); @@ -324,12 +324,12 @@ public class PictureCtl { image.setImage(SOMLayout.LOGO_IMAGE); // make it fit the height of the Screen -// image.setFitWidth(SOMLayout.screenHeight); +// image.setFitWidth(SOMLayout.SCREEN_HEIGHT); // Calculate the offset to center it horizontally if the image is wider than the screen (or narrower) double aspect = image.getImage().getWidth() / image.getImage().getHeight(); - double scaledWidth = aspect * SOMLayout.screenHeight; - double offset = (scaledWidth - SOMLayout.screenWidth) / 2; + double scaledWidth = aspect * SOMLayout.SCREEN_HEIGHT; + double offset = (scaledWidth - SOMLayout.SCREEN_WIDTH) / 2; image.setX(-offset); @@ -341,10 +341,6 @@ public class PictureCtl { // Set the last Image of the session SOMImage somImage = somImageList.get(numberOfImages - 1); - // update the Image State -// TODO Probably not necessary -- commented out to test it -// somImage.updateImageState(); - // Scale the Image if needed ScaleWorker.scale(somImage, ScaleWorker.PREVIEW); diff --git a/src/main/java/GUI/SOMGUI.java b/src/main/java/GUI/SOMGUI.java index 2d67cc6..11b54db 100644 --- a/src/main/java/GUI/SOMGUI.java +++ b/src/main/java/GUI/SOMGUI.java @@ -67,11 +67,11 @@ public class SOMGUI extends Application { warnCtl = warnLoader.getController(); // Initialize the Scenes - pictureScene = new Scene(picture, SOMLayout.screenWidth, SOMLayout.screenHeight); - galleryScene = new Scene(gallery, SOMLayout.screenWidth, SOMLayout.screenHeight); - uploadScene = new Scene(upload, SOMLayout.screenWidth, SOMLayout.screenHeight); - captureScene = new Scene(capture, SOMLayout.screenWidth, SOMLayout.screenHeight); - warnScene = new Scene(warn, SOMLayout.screenWidth, SOMLayout.screenHeight); + pictureScene = new Scene(picture, SOMLayout.SCREEN_WIDTH, SOMLayout.SCREEN_HEIGHT); + galleryScene = new Scene(gallery, SOMLayout.SCREEN_WIDTH, SOMLayout.SCREEN_HEIGHT); + uploadScene = new Scene(upload, SOMLayout.SCREEN_WIDTH, SOMLayout.SCREEN_HEIGHT); + captureScene = new Scene(capture, SOMLayout.SCREEN_WIDTH, SOMLayout.SCREEN_HEIGHT); + warnScene = new Scene(warn, SOMLayout.SCREEN_WIDTH, SOMLayout.SCREEN_HEIGHT); } public static SOMGUI getInstance() throws Exception { diff --git a/src/main/java/GUI/UploadCtl.java b/src/main/java/GUI/UploadCtl.java index 20555f6..00f3aac 100644 --- a/src/main/java/GUI/UploadCtl.java +++ b/src/main/java/GUI/UploadCtl.java @@ -77,12 +77,12 @@ public class UploadCtl { } private void setPane() { - pane.setPrefSize(SOMLayout.screenWidth, SOMLayout.screenHeight); + pane.setPrefSize(SOMLayout.SCREEN_WIDTH, SOMLayout.SCREEN_HEIGHT); pane.setBackground(SOMLayout.BLACK_BG); } private void setGrid() { - grid.setPrefSize(SOMLayout.screenWidth, SOMLayout.screenHeight); + grid.setPrefSize(SOMLayout.SCREEN_WIDTH, SOMLayout.SCREEN_HEIGHT); GridPane.setHalignment(folderImageView, HPos.CENTER); GridPane.setHalignment(folderLabel, HPos.CENTER); GridPane.setHalignment(folderProgressBar, HPos.CENTER); @@ -99,15 +99,15 @@ public class UploadCtl { } private void setFolderProg() { - folderProgressBar.setPrefSize(SOMLayout.screenWidth, 3); + folderProgressBar.setPrefSize(SOMLayout.SCREEN_WIDTH, 3); } private void setPicProg() { - pictureProgressBar.setPrefSize(SOMLayout.screenWidth, 3); + pictureProgressBar.setPrefSize(SOMLayout.SCREEN_WIDTH, 3); } private void setCleanProg() { - cleanProgressBar.setPrefSize(SOMLayout.screenWidth, 3); + cleanProgressBar.setPrefSize(SOMLayout.SCREEN_WIDTH, 3); } private void setFolderIV() { @@ -139,10 +139,10 @@ public class UploadCtl { } // set the progress -// public void setFolderProgress(double value) { -// folderProgressBar.setProgress(value); -// System.out.println("Folder Progress set to: "+ value); -// } + public void setFolderProgress(double value) { + folderProgressBar.setProgress(value); + System.out.println("Folder Progress set to: "+ value); + } public void setPicProgress(double value) { pictureProgressBar.setProgress(value); diff --git a/src/main/java/model/SOMConfig.java b/src/main/java/model/SOMConfig.java index 794819a..a75490b 100644 --- a/src/main/java/model/SOMConfig.java +++ b/src/main/java/model/SOMConfig.java @@ -2,7 +2,7 @@ package model; import workers.MachineWorker; -import java.io.*; +import java.io.File; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; @@ -49,8 +49,7 @@ public class SOMConfig { // Constructor private SOMConfig() { // get the default Displays' dimensions - - System.out.println("Creating Configuration. Sreen Size: " + SOMLayout.screenWidth + "x" + SOMLayout.screenHeight); +// System.out.println("Creating Configuration. Sreen Size: " + SOMLayout.SCREEN_WIDTH + "x" + SOMLayout.SCREEN_HEIGHT); // important Paths PICTURES_PATH = new File("images"); diff --git a/src/main/java/model/SOMConfigFileHandler.java b/src/main/java/model/SOMConfigFileHandler.java index 47c6977..83be03e 100644 --- a/src/main/java/model/SOMConfigFileHandler.java +++ b/src/main/java/model/SOMConfigFileHandler.java @@ -1,7 +1,5 @@ package model; -import workers.MachineWorker; - import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; @@ -10,9 +8,6 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import java.io.File; import java.nio.file.Files; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Calendar; @XmlRootElement(name = "Config") public class SOMConfigFileHandler { diff --git a/src/main/java/model/SOMEvent.java b/src/main/java/model/SOMEvent.java index 2e17a94..f0864bf 100644 --- a/src/main/java/model/SOMEvent.java +++ b/src/main/java/model/SOMEvent.java @@ -48,7 +48,6 @@ public class SOMEvent { // Singleton to prevent Instantiation if (event == null) { event = new SOMEvent(); - // event.currentimage = SOMImage.getFallbackImage(); } return event; @@ -61,22 +60,16 @@ public class SOMEvent { */ public void getEventImages() { // Behandelt -// if (!imagesread) { - File[] files = FilesWorker.getSourcePath().listFiles(); assert files != null; Arrays.sort(files); for (File file : files) { - SOMImage img = new SOMImage(file.getName()); + SOMImage img = new SOMImage(); img.updateImageState(); this.addImage(img); } - -// imagesread = true; -// } -// return; } /** @@ -89,15 +82,6 @@ public class SOMEvent { images.add(now); } - /** - * Returns the Events' Date - * - * @return the date - */ - public Date getDate() { - return date; - } - /** * Returns a List of all of the Events' images * @@ -105,9 +89,9 @@ public class SOMEvent { */ public List getImages() { // If there are no Event Images Collected - if (images.size() == 0) - // get all the events' images - getEventImages(); +// if (0 == images.size()) +// // get all the events' images +// this.getEventImages(); //...and return them return images; } diff --git a/src/main/java/model/SOMImage.java b/src/main/java/model/SOMImage.java index 51fea69..19f753c 100644 --- a/src/main/java/model/SOMImage.java +++ b/src/main/java/model/SOMImage.java @@ -3,11 +3,11 @@ package model; import workers.FilesWorker; import java.io.File; -import java.nio.file.Files; +import java.util.List; public class SOMImage { - private static String name; // the filename + private final String imageName; // the filename private final SOMConfig config = SOMConfig.getInstance(); @@ -22,68 +22,62 @@ public class SOMImage { private boolean srcthere; // source status private boolean fnlthere; // final status - SOMImage(String name) { - - File src = new File(FilesWorker.getSourcePath().toString() + "/" + name); - - File prv = new File(FilesWorker.getPreviewPath().toString() + "/" + name); - - File tmb = new File(FilesWorker.getThumbPath().toString() + "/" + name); - - File fnl = new File(FilesWorker.getFinalPath().toString() + "/" + name); - - File tmp = new File(FilesWorker.getTempPath().toString() + "/" + name); - - this.tmb = tmb; - this.prv = prv; - this.src = src; - this.fnl = fnl; - this.tmp = tmp; - - this.updateImageState(); - } - + /** + * Automatically generates an SOMImage Object + * with an incremented Number and all th Paths + */ public SOMImage() { - super(); +// super(); + + SOMEvent somEvent = SOMEvent.getInstance(); + int nrOfEventPics; + List somEventImages = somEvent.getImages(); + + nrOfEventPics = somEventImages.size(); - int numberOfEventPictures = SOMEvent.getInstance().getImages().size(); String fill = "00000"; - int nmb = (numberOfEventPictures + 1); + int nmb = (nrOfEventPics + 1); String number = String.valueOf(nmb); - String filledNumber = fill.substring(number.length()) + number; - name = filledNumber + ".jpg"; - File src = new File(FilesWorker.getSourcePath().toString() + "/" + name); - File prv = new File(FilesWorker.getPreviewPath().toString() + "/" + name); - File tmb = new File(FilesWorker.getThumbPath().toString() + "/" + name); - File fnl = new File(FilesWorker.getFinalPath().toString() + "/" + name); - File tmp = new File(FilesWorker.getTempPath().toString() + "/" + name); + int numberLength = number.length(); + String filledNumber = fill.substring(numberLength) + number; - this.tmb = tmb; - this.prv = prv; - this.src = src; - this.fnl = fnl; - this.tmp = tmp; + this.imageName = filledNumber + ".jpg"; + + File sourcePath = FilesWorker.getSourcePath(); + this.src = new File(sourcePath + "/" + this.imageName); + + File previewPath = FilesWorker.getPreviewPath(); + this.prv = new File(previewPath + "/" + this.imageName); + + File thumbPath = FilesWorker.getThumbPath(); + this.tmb = new File(thumbPath + "/" + this.imageName); + + File finalPath = FilesWorker.getFinalPath(); + this.fnl = new File(finalPath + "/" + this.imageName); + + File tempPath = FilesWorker.getTempPath(); + this.tmp = new File(tempPath + "/" + this.imageName); this.updateImageState(); } - public void updateImageState() { + public final void updateImageState() { // tmb - tmbthere = Files.exists(tmb.toPath()); + this.tmbthere = this.tmb.isFile(); // prv - prvthere = Files.exists(prv.toPath()); + this.prvthere = this.prv.isFile(); // src - srcthere = Files.exists(src.toPath()); + this.srcthere = this.src.isFile(); // fnl - fnlthere = Files.exists(fnl.toPath()); + this.fnlthere = this.fnl.isFile(); } /** - * @return the name + * @return the imageName */ public String getName() { - return name; + return this.imageName; } /** @@ -97,79 +91,55 @@ public class SOMImage { * @return the prv */ public File getPrv() { - return prv; + return this.prv; } /** * @return the src */ public File getSrc() { - return src; + return this.src; } /** * @return the fnl */ public File getFnl() { - return fnl; + return this.fnl; } /** * @return the tmp */ public File getTmp() { - return tmp; + return this.tmp; } /** * @return the tmbthere */ public boolean isTmbthere() { - return tmbthere; + return this.tmbthere; } /** * @return the prvthere */ public boolean isPrvthere() { - return prvthere; + return this.prvthere; } /** * @return the srcthere */ public boolean isSrcthere() { - return srcthere; + return this.srcthere; } /** * @return the fnlthere */ public boolean isFnlthere() { - return fnlthere; + return this.fnlthere; } - - /** - * @param type 0 = thumb, 1 = preview, 2 = full Size - * @return - */ -// public ImageIcon toImageIcon(int type) { -// File imagepath; -// switch (type) { -// case 0: -// imagepath = getTmb(); -// break; -// case 1: -// imagepath = getPrv(); -// break; -// case 2: -// imagepath = getSrc(); -// break; -// default: -// imagepath = null; -// break; -// } -// -// return new ImageIcon(imagepath.getPath()); -// } } diff --git a/src/main/java/model/SOMLayout.java b/src/main/java/model/SOMLayout.java index 09b57da..3e2d85b 100644 --- a/src/main/java/model/SOMLayout.java +++ b/src/main/java/model/SOMLayout.java @@ -3,16 +3,20 @@ package model; import javafx.scene.layout.Background; import javafx.scene.layout.BackgroundFill; import javafx.scene.layout.CornerRadii; +import javafx.scene.text.Font; import javafx.stage.Screen; -import java.awt.*; public class SOMLayout { // Fonts - public static final Font H_0 = new Font(Font.SANS_SERIF, 1, 150); - public static final Font H_1 = new Font(Font.SANS_SERIF, 1, 100); - public static final Font H_2 = new Font(Font.SANS_SERIF, 1, 75); - public static final Font P = new Font(Font.SANS_SERIF, 1, 50); + public static final Font H_0 = Font.loadFont("fonts/CenturyGothicStd.otf", 150); + // public static final Font H_0 = new Font(Font.SANS_SERIF, 1, 150); + public static final Font H_1 = Font.loadFont("fonts/CenturyGothicStd.otf", 100); + // public static final Font H_1 = new Font(Font.SANS_SERIF, 1, 100); + public static final Font H_2 = Font.loadFont("fonts/CenturyGothicStd.otf", 75); + // public static final Font H_2 = new Font(Font.SANS_SERIF, 1, 75); + public static final Font P = Font.loadFont("fonts/CenturyGothicStd.otf", 50); + // public static final Font P = new Font(Font.SANS_SERIF, 1, 50); // Icons & Images //UI public static final javafx.scene.image.Image GALLERY_IMAGE = new javafx.scene.image.Image(ClassLoader.class.getResource("/img/SOMIcons_Gallery.png").toString()); @@ -27,15 +31,29 @@ public class SOMLayout { public static final javafx.scene.image.Image LOGO_IMAGE = new javafx.scene.image.Image(ClassLoader.class.getResource("/img/SOMLogo.png").toString()); // public static final javafx.scene.image.Image SPLASH_IMAGE = new javafx.scene.image.Image(ClassLoader.class.getResource("/img/SOMSplash.jpg").toString()); public static final javafx.scene.paint.Color WHITE = new javafx.scene.paint.Color(1, 1, 1, 1); - public static final Background WHITE_BG = new Background(new BackgroundFill(WHITE, null, null)); + public static final Background WHITE_BG = new Background(new BackgroundFill(SOMLayout.WHITE, null, null)); // Screen // private static final GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); private static final javafx.geometry.Rectangle2D gd = Screen.getPrimary().getBounds(); - public static final int screenWidth = (int) gd.getWidth(); - public static final int screenHeight = (int) gd.getHeight(); + public static final int SCREEN_WIDTH = SOMLayout.getScreenWidth(); + + private static int getScreenWidth() { + if (null != SOMLayout.gd) { + return (int) SOMLayout.gd.getWidth(); + } else { + return 1024; + } + } + + public static final int SCREEN_HEIGHT = getHeight(); + + private static int getHeight() { + return (int) SOMLayout.gd.getHeight(); + } + // Layout - private static final int row = screenHeight / 3; - private static final int column = screenWidth / 4; + private static final int row = SOMLayout.SCREEN_HEIGHT / 3; + private static final int column = SOMLayout.SCREEN_WIDTH / 4; // Colors private static final javafx.scene.paint.Color BLACK = new javafx.scene.paint.Color(0, 0, 0, 1); //Backgrounds diff --git a/src/main/java/workers/FilesWorker.java b/src/main/java/workers/FilesWorker.java index df9705c..1332e59 100644 --- a/src/main/java/workers/FilesWorker.java +++ b/src/main/java/workers/FilesWorker.java @@ -18,27 +18,29 @@ import java.nio.file.*; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.logging.Logger; -import static java.nio.file.StandardCopyOption.ATOMIC_MOVE; import static java.nio.file.StandardWatchEventKinds.*; -public class FilesWorker { +/** + * + */ +public final class FilesWorker { private static final SOMEvent event = SOMEvent.getInstance(); + private static Logger log = Logger.getLogger(FilesWorker.class.getName()); - public FilesWorker() { - + private FilesWorker() { } /** * Returns true if a File is an image and returns false if not. * - * @param path + * @param file * @return */ - public static boolean isImage(Path path) { - File f = path.toFile(); - String mimeType = new MimetypesFileTypeMap().getContentType(f); + public static boolean isImage(File file) { + String mimeType = new MimetypesFileTypeMap().getContentType(file); String type = mimeType.split("/")[0]; return type.equals("image"); } @@ -50,7 +52,7 @@ public class FilesWorker { * @return */ public static File getSourcePath() { - File src = new File(SOMConfig.PICTURES_PATH.toString() + "/src"); + File src = new File(SOMConfig.PICTURES_PATH + "/src"); src.mkdirs(); return src; @@ -63,7 +65,7 @@ public class FilesWorker { * @return */ public static File getPreviewPath() { - File prv = new File(SOMConfig.PICTURES_PATH.toString() + "/prv"); + File prv = new File(SOMConfig.PICTURES_PATH + "/prv"); prv.mkdirs(); return prv; @@ -76,7 +78,7 @@ public class FilesWorker { * @return */ public static File getThumbPath() { - File tmb = new File(SOMConfig.PICTURES_PATH.toString() + "/tmb"); + File tmb = new File(SOMConfig.PICTURES_PATH + "/tmb"); tmb.mkdirs(); return tmb; @@ -89,7 +91,7 @@ public class FilesWorker { * @return */ public static File getFinalPath() { - File fnl = new File(SOMConfig.PICTURES_PATH.toString() + "/fnl"); + File fnl = new File(SOMConfig.PICTURES_PATH + "/fnl"); fnl.mkdirs(); return fnl; @@ -102,23 +104,27 @@ public class FilesWorker { * @return */ public static File getTempPath() { - File tmp = new File(SOMConfig.PICTURES_PATH.toString() + "/tmp"); + File tmp = new File(SOMConfig.PICTURES_PATH + "/tmp"); tmp.mkdirs(); return tmp; } + + /** + * Prints out the current image via cups + */ public static void print() { try { - System.out.println( + log.info( SOMEvent.getInstance().getCurrentimage().getSrc().toString() ); // get a process taking the image ProcessBuilder builder = new ProcessBuilder( "lp", SOMEvent.getInstance().getCurrentimage().getSrc().toString() - ); + ); builder.redirectErrorStream(true); @@ -131,17 +137,22 @@ public class FilesWorker { } } + /** + * Checks whether the Software has an Internet Connection or not + * + * @return boolean true if it has an internet connection, false if not + */ private static boolean internet() { Socket sock = new Socket(); - InetSocketAddress socketAddress = new InetSocketAddress("google.com", 80); + InetSocketAddress socketAddress = new InetSocketAddress("selfomat.de", 80); try { sock.connect(socketAddress, 3000); - System.out.println("Internet available"); + log.info("Internet available"); return true; } catch (IOException e) { - System.out.println("Internet NOT available"); + log.warning("Internet NOT available"); return false; } finally { try { @@ -152,6 +163,9 @@ public class FilesWorker { } } + /** + * Collects the Images and folders and Uploads the images from src-folder to SELFOMAT Cloud + */ public static void upload() { try { @@ -177,7 +191,7 @@ public class FilesWorker { currentdir = currentdir + "/" + split; dirs.add(new File(currentdir)); - System.out.println("DIR added:" + currentdir); + log.info("DIR added:" + currentdir); } // FILES @@ -186,7 +200,7 @@ public class FilesWorker { // get the current file File file = images.get(i); - System.out.println(file); + log.info(file.toString()); // get pics if (file.isFile() @@ -198,8 +212,8 @@ public class FilesWorker { } // REPORT TO CONSOLE - System.out.println(dirs.size() + " Directories"); - System.out.println(pics.size() + " Pics"); + log.info(dirs.size() + " Directories"); + log.info(pics.size() + " Pics"); int queueddirs = 0; int queuedfiles = 0; @@ -211,16 +225,16 @@ public class FilesWorker { queueddirs++; - System.out.println("Queueing Directories " + dir.toString()); + log.info("Queueing Directories " + dir.toString()); limitdirs.add(dir); if (limitdirs.size() >= SOMConfig.PARALLEL_UPLOADS // Upload even if limit is not reached || (dirs.size() - queueddirs) < SOMConfig.PARALLEL_UPLOADS) { - System.out.println("Launch Dir upload"); + log.info("Launch Dir upload"); uploadDir(limitdirs); - System.out.println("Clear Queue"); + log.info("Clear Queue"); limitdirs.clear(); } } @@ -232,18 +246,18 @@ public class FilesWorker { // Counter for all queued files over the whole upload process queuedfiles++; - System.out.println("Queueing File " + pic.toString()); + log.info("Queueing File " + pic.toString()); limitpics.add(pic); if ( // Check if the parallel Upload Limit is reached limitpics.size() >= SOMConfig.PARALLEL_UPLOADS - // Upload even if limit is not reached if the pics are the last ones - || (pics.size() - queuedfiles) < SOMConfig.PARALLEL_UPLOADS) { + // Upload even if limit is not reached if the pics are the last ones + || (pics.size() - queuedfiles) < SOMConfig.PARALLEL_UPLOADS) { - System.out.println("Launch File upload"); + log.info("Launch File upload"); uploadFile(limitpics); - System.out.println("Clear File Queue"); + log.info("Clear File Queue"); limitpics.clear(); } else { } @@ -261,7 +275,7 @@ public class FilesWorker { // reboot - new File("reboot").mkdirs(); +// new File("reboot").mkdirs(); // new ProcessBuilder("sudo reboot").start(); } @@ -282,14 +296,15 @@ public class FilesWorker { } } + /** + * + */ private static void archiveBackup() { Task task = new Task() { @Override protected Boolean call() throws Exception { // build the archive process - // TODO remove -k option (this option skips certificate verification) - // TODO Make Software run in SELFOMAT Directory ProcessBuilder builder = new ProcessBuilder( "bash", "SELFOMAT/sh/move-backup.sh" @@ -303,34 +318,42 @@ public class FilesWorker { // wait for the process to end if (process.waitFor() == 0) { // process ended successful - System.out.println("archiving Backup"); + log.info("archiving Backup"); return true; } else { // process ended failing - // TODO Catch failed uploads + // TODO Catch failed archives - System.out.println("Backup archiving failed!"); + log.severe("Backup archiving failed!"); return false; } } }; } + /** + * The Actual Upload of the File List. + * Loops through the Files List and uploads the images in batches of the + * given threads-counter in config + * + * @param files - The Files List + * @throws Exception + */ private static void uploadFile(final List files) throws Exception { - final Thread[] threads = new Thread[files.size()]; + final Thread[] threads = new Thread[files.size()]; for (int i = 0; i < threads.length; i++) { - System.out.println("LAUNCH Upload Process: " + i); + log.info("LAUNCH Upload Process: " + i); final File file = files.get(i); final String target = SOMConfig.CLOUD_ADDRESS + SOMConfig.getEventPicDir() + "/" + file.getName(); - System.out.println(""); - System.out.println(file.toString() + "----------->" + target); - System.out.println(""); + log.info(""); + log.info(file.toString() + "----------->" + target); + log.info(""); final int pictureCounter = i + 1; Task task = new Task() { @@ -339,7 +362,6 @@ public class FilesWorker { protected Boolean call() throws Exception { // build the upload process // TODO remove -k option (this option skips certificate verification) - // TODO Make Software run in SELFOMAT Directory ProcessBuilder builder = new ProcessBuilder( "bash", "SELFOMAT/sh/upload.sh", @@ -356,32 +378,26 @@ public class FilesWorker { // wait for the process to end if (process.waitFor() == 0) { // process ended successful - System.out.println("file uploaded: " + file); - - // TODO get the length of all threads - // TODO bind to UI - updateProgress(pictureCounter, threads.length); + log.info("file uploaded: " + file); return true; } else { // process ended failing // TODO Catch failed uploads - - System.out.println("process ended failing " + file); - Thread.sleep(1000); - + log.severe("process ended failing " + file); return false; } } }; - SOMGUI.uploadCtl.pictureProgressBar.progressProperty().bind(task.progressProperty()); +// SOMGUI.uploadCtl.pictureProgressBar.progressProperty().bind(task.progressProperty()); threads[i] = new Thread(task); threads[i].setDaemon(true); threads[i].start(); +// threads[i]. } int i = 0; while (i < threads.length) { @@ -390,12 +406,22 @@ public class FilesWorker { } } + /** + * The Actual Upload of the Directory List. + * Loops through the directories List and uploads the directories in batches of the + * given threads-counter in config + * + * @param dirs + * @throws Exception + */ + private static void uploadDir(final List dirs) throws Exception { final Thread[] threads = new Thread[dirs.size()]; + for (int i = 0; i < threads.length; i++) { - System.out.println("launch mkdir Process: " + i); + log.info("launch mkdir Process: " + i); final File dir = dirs.get(i); final int directoryCounter = i + 1; @@ -404,14 +430,12 @@ public class FilesWorker { @Override protected Boolean call() throws Exception { // build the Upload process with curl - // TODO remove -k option (this option skips certificate verification) ProcessBuilder builder = new ProcessBuilder("curl", "-u", SOMConfig.CLOUD_CREDENTIALS, "-X", "MKCOL", - SOMConfig.CLOUD_ADDRESS + dir.toString().replace("/src", ""), - "-k"); + SOMConfig.CLOUD_ADDRESS + dir.toString().replace("/src", "")); // make the process traceable builder.redirectErrorStream(true); @@ -422,23 +446,23 @@ public class FilesWorker { // wait for the process to end if (process.waitFor() == 0) { // Process ended successful - System.out.println("directory made: " + dir); + log.info("directory made: " + dir); //Set upload Progress - // TODO get the length of all threads // TODO bind to UI - updateProgress(directoryCounter, threads.length); + SOMGUI.uploadCtl.setFolderProgress(directoryCounter / dirs.size()); +// updateProgress(directoryCounter, threads.length); return true; } else { // Process ended failing - System.out.println("process ended failing " + dir); + log.info("process ended failing " + dir); return false; } } }; - SOMGUI.uploadCtl.folderProgressBar.progressProperty().bind(task.progressProperty()); +// SOMGUI.uploadCtl.folderProgressBar.progressProperty().bind(task.progressProperty()); // Start the Task threads[i] = new Thread(task); @@ -452,10 +476,14 @@ public class FilesWorker { threads[i].join(); i++; } - //TODO Catch upload fails } + /** + * Reads out all files and dirs in the Images Folder + * + * @return a File ArrayList containing all files and dirs + */ private static List allFilesForUpload() { File dir = SOMConfig.PICTURES_PATH; @@ -465,8 +493,15 @@ public class FilesWorker { return new ArrayList(filesAndDirs); } + /** + * Wraps the actual capturing function. + * Waits for an image that is served by the capture function, + * adds it into the Event and sets it to UI. + * + * @return SOMImage Object - the new Image. Null if function fails. + */ + public static SOMImage waitForImageAndCapture() { - //Behandelt try { // Set the Source Path to be watched @@ -476,11 +511,11 @@ public class FilesWorker { WatchService watcher = FileSystems.getDefault().newWatchService(); dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); - System.out.println("Watch Service registered for dir: " + log.info("Watch Service registered for dir: " + dir.getFileName()); // TRIGGER THE CAPTURE - System.out.println("START CAPTURE THREAD"); + log.info("START CAPTURE THREAD"); SOMImage newImage = CaptureWorker.now(); while (true) { @@ -500,7 +535,7 @@ public class FilesWorker { WatchEvent ev = (WatchEvent) event; Path fileName = ev.context(); - System.out.println(kind.name() + ": " + fileName); + log.info(kind.name() + ": " + fileName); // check for a file being created if ( // Make sure there is an Image created @@ -512,14 +547,26 @@ public class FilesWorker { //Set the Progress Indicator to 0.5 SOMGUI.captureCtl.pictureLoadIndicator.setProgress(0.5); + //Scale the image to preview + ScaleWorker.scale(newImage, ScaleWorker.PREVIEW); + + //Set the Progress Indicator to 0.5 + SOMGUI.captureCtl.pictureLoadIndicator.setProgress(0.75); + + // trigger the thumb calculation + ScaleWorker.scale(newImage, ScaleWorker.THUMBNAIL); + + //Set the Progress Indicator to 0.5 + SOMGUI.captureCtl.pictureLoadIndicator.setProgress(1); + // START THE "PICTURE HAS ARRIVED" ACTION - System.out.println("The image is there!!!"); + // System.out.println("The image is there!!!"); // ADD THE IMAGE TO THE EVENT FilesWorker.event.addImage(newImage); // Set last Image - System.out.println("Set the taken Picture to UI"); + // System.out.println("Set the taken Picture to UI"); FilesWorker.event.createAndSetImage(FilesWorker.event.getLastImage()); // Hide the Progress Indicator @@ -535,14 +582,14 @@ public class FilesWorker { // Check that filename is the same as expected image && !fileName.toString().equals( newImage.getSrc().getName())) { - // TODO Catch wrong pictures, only for testing, make only available for Developer (Hostname??) - // Hide the Progress Indicator - SOMGUI.captureCtl.pictureLoadIndicator.setVisible(false); - // Set back the Progress Indicator - SOMGUI.captureCtl.pictureLoadIndicator.setProgress(-1); - //Close Watcher - watcher.close(); +// // Hide the Progress Indicator +// SOMGUI.captureCtl.pictureLoadIndicator.setVisible(false); +// // Set back the Progress Indicator +// SOMGUI.captureCtl.pictureLoadIndicator.setProgress(-1); +// +// //Close Watcher +// watcher.close(); } } diff --git a/src/main/java/workers/MachineWorker.java b/src/main/java/workers/MachineWorker.java index 066590c..4a18362 100644 --- a/src/main/java/workers/MachineWorker.java +++ b/src/main/java/workers/MachineWorker.java @@ -2,29 +2,33 @@ package workers; import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.logging.Logger; /** * This Class works through all kinds of Machine-Related Values such as Screen size, Machine Name, OS etc. * Created by Simon on 12.12.2016. */ -public class MachineWorker { - static int OperatingSystem; - static String HostName; - static int[] Screen; +public final class MachineWorker { + // for multiple OS' +// static int OperatingSystem; + private static String HostName = null; + private static final Logger log = Logger.getLogger(MachineWorker.class.getName()); + + private MachineWorker() { + super(); + } + // for multiple screens +// static int[] Screen; public static String getHostName() { try { - InetAddress addr; - addr = InetAddress.getLocalHost(); - HostName = addr.getHostName(); + InetAddress addr = InetAddress.getLocalHost(); + String hostName = addr.getHostName(); + HostName = hostName; + log.info("Hostname: " + HostName); } catch (UnknownHostException ex) { - System.out.println("Hostname can not be resolved"); + log.info("Hostname can not be resolved"); } return HostName; } - - public static int[] getScreen() { - return Screen; - } - } diff --git a/src/main/java/workers/ScaleWorker.java b/src/main/java/workers/ScaleWorker.java index 13b395c..d6410ae 100644 --- a/src/main/java/workers/ScaleWorker.java +++ b/src/main/java/workers/ScaleWorker.java @@ -15,6 +15,7 @@ import java.awt.image.FilteredImageSource; import java.io.File; import java.io.IOException; import java.util.List; +import java.util.logging.Logger; //import java.awt.*; @@ -23,19 +24,14 @@ public class ScaleWorker extends Thread { public static final int SOURCE = 0; public static final int PREVIEW = 1; public static final int THUMBNAIL = 2; + private static Logger log = Logger.getLogger(ScaleWorker.class.getName()); SOMConfig config = SOMConfig.getInstance(); public static SOMImage scale(SOMImage somImage1, final int type) { final SOMImage somImage = somImage1; - Task task = new Task() { - @Override - protected SOMImage call() throws Exception { - // Do the scale work - return prepareandStart(somImage, type); - } - }; + Task task = new scaleTask(somImage, type); // open Thread Thread thread = new Thread(task); @@ -61,7 +57,7 @@ public class ScaleWorker extends Thread { return somImages; } - private static SOMImage prepareandStart(SOMImage somImage, int type) { + static SOMImage prepareAndStart(SOMImage somImage, int type) { // the image before scaling @@ -152,13 +148,13 @@ public class ScaleWorker extends Thread { // for the preview case PREVIEW: - targetWidth = SOMLayout.screenWidth; - targetHeight = SOMLayout.screenHeight; + targetWidth = SOMLayout.SCREEN_WIDTH; + targetHeight = SOMLayout.SCREEN_HEIGHT; targetFile = somImage.getPrv(); - - // for the Thumbnail break; + + // for the Thumbnail case THUMBNAIL: targetWidth = SOMLayout.getColumn(1); targetHeight = SOMLayout.getRow(1); @@ -207,10 +203,10 @@ public class ScaleWorker extends Thread { } // Probably way faster than ImageIcon - System.out.println("Scale with Graphics2D:"); + log.info("Scale with Graphics2D:"); // Print the File Path - System.out.println(sourceFile.toString()); + log.info(sourceFile.toString()); // SCALE ----------------------------------------------------------- // THE ------------------------------------------------------------- @@ -306,7 +302,7 @@ public class ScaleWorker extends Thread { somImage.updateImageState(); - System.out.println("Image State Updated: Scaled"); + log.info("Image State Updated: Scaled"); // Clean up croppedGraphics.dispose(); @@ -330,7 +326,7 @@ public class ScaleWorker extends Thread { somImage.updateImageState(); - System.out.println("Image State Updated: Scaled"); + log.info("Image State Updated: Scaled"); somImage.updateImageState(); break; @@ -348,4 +344,20 @@ public class ScaleWorker extends Thread { e.printStackTrace(); } } + + private static class scaleTask extends Task { + private final SOMImage somImage; + private final int type; + + public scaleTask(SOMImage somImage, int type) { + this.somImage = somImage; + this.type = type; + } + + @Override + protected SOMImage call() throws Exception { + // Do the scale work + return prepareAndStart(somImage, type); + } + } } diff --git a/src/main/resources/fonts/CenturyGothicStd-Bold.otf b/src/main/resources/fonts/CenturyGothicStd-Bold.otf new file mode 100644 index 0000000000000000000000000000000000000000..c5bb056a74067cc671e4f0b0bdef7be5e53cf175 GIT binary patch literal 29676 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 J2T>wL{{T3pbQ1so literal 0 HcmV?d00001 diff --git a/src/main/resources/fonts/CenturyGothicStd.otf b/src/main/resources/fonts/CenturyGothicStd.otf new file mode 100644 index 0000000000000000000000000000000000000000..079493b2ba254a141f83614b9f95ea80a3c2633c GIT binary patch literal 29592 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 R|8`O$@|On5?-K*X{R!b-3a0=7 literal 0 HcmV?d00001 diff --git a/src/main/resources/fxml/gallery.fxml b/src/main/resources/fxml/gallery.fxml index a18b736..34e35c0 100644 --- a/src/main/resources/fxml/gallery.fxml +++ b/src/main/resources/fxml/gallery.fxml @@ -27,6 +27,7 @@ +