diff --git a/.gitignore b/.gitignore index cf94503..199fbcd 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,8 @@ proxy.txt out.txt pocasi.txt test.txt -timecalc.conf +timecalc*.conf focus.txt dist/* +time-calc-current-profile.txt +time-calc-profiles.txt diff --git a/Readme.md b/Readme.md index 578025c..69f6cfd 100644 --- a/Readme.md +++ b/Readme.md @@ -141,13 +141,13 @@ Smileys can be colored or white-black (can be set in configuration) * I - disable almost everything * E - enable or disable battery waves * B - hide or show buttons +* 0,1,2,3,4,5,6,7,8 or 9 - activates a profile +* F - show numbers for profiles ## Command button ## Todos - * Custom main window title - * Profiles * Split to Maven modules * Junit, Mockito, etc. * Checkstyle diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcConfiguration.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcConfiguration.java index b9f2268..7912779 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcConfiguration.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcConfiguration.java @@ -141,6 +141,8 @@ public class TimeCalcConfiguration { = new BooleanProperty(TimeCalcProperty.WALKING_HUMAN_VISIBLE.getKey()); public final StringProperty mainWindowCustomTitleProperty = new StringProperty(TimeCalcProperty.MAIN_WINDOW_CUSTOM_TITLE.getKey()); + public final StringProperty profileNameProperty + = new StringProperty(TimeCalcProperty.PROFILE_NAME.getKey()); private final Map mapOfProperties = new HashMap<>(); private List allProperties = new ArrayList<>(); @@ -190,7 +192,9 @@ public class TimeCalcConfiguration { squareVisibleProperty, circleVisibleProperty, walkingHumanVisibleProperty, - mainWindowCustomTitleProperty,}) { + mainWindowCustomTitleProperty, + profileNameProperty, + }) { allProperties.add(p); } allProperties.stream().forEach(p -> mapOfProperties.put(TimeCalcProperty.forKey(p.getName()), p)); @@ -219,7 +223,7 @@ public class TimeCalcConfiguration { } Properties properties = new Properties(); this.allProperties.stream().forEach(p -> properties.put(p.getName(), p.getValue())); - this.timeCalcProperties.save(properties); + this.timeCalcProperties.save(properties, this.profileNameProperty.getValue()); } diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcException.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcException.java index b79ecaa..ef77d5e 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcException.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcException.java @@ -1,5 +1,7 @@ package org.nanoboot.utils.timecalc.app; +import java.io.IOException; + /** * @author Robert Vokac * @since 21.02.2024 @@ -9,4 +11,8 @@ public class TimeCalcException extends RuntimeException { public TimeCalcException(String msg) { super(msg); } + + public TimeCalcException(Exception e) { + super(e); + } } diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcKeyAdapter.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcKeyAdapter.java index c9d0345..e26e2c5 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcKeyAdapter.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcKeyAdapter.java @@ -2,11 +2,17 @@ package org.nanoboot.utils.timecalc.app; import org.nanoboot.utils.timecalc.entity.Visibility; import org.nanoboot.utils.timecalc.swing.common.MainWindow; +import org.nanoboot.utils.timecalc.swing.common.Toaster; import org.nanoboot.utils.timecalc.utils.common.Jokes; import org.nanoboot.utils.timecalc.utils.common.Utils; +import javax.swing.JOptionPane; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Properties; /** * @author Robert Vokac @@ -17,7 +23,7 @@ public class TimeCalcKeyAdapter extends KeyAdapter { private final TimeCalcConfiguration timeCalcConfiguration; private final TimeCalcApp timeCalcApp; private final MainWindow window; - + private final File timeCalcProfilesTxtFile = new File("time-calc-profiles.txt"); public TimeCalcKeyAdapter( TimeCalcConfiguration timeCalcConfiguration, TimeCalcApp timeCalcApp, @@ -157,6 +163,77 @@ public class TimeCalcKeyAdapter extends KeyAdapter { MainWindow.hideShowCheckBox.setSelected(!MainWindow.hideShowCheckBox.isSelected()); } + boolean numberKeyWasPressed = e.getKeyCode() == KeyEvent.VK_0 || + e.getKeyCode() == KeyEvent.VK_1 || + e.getKeyCode() == KeyEvent.VK_2 || + e.getKeyCode() == KeyEvent.VK_3 || + e.getKeyCode() == KeyEvent.VK_4 || + e.getKeyCode() == KeyEvent.VK_5 || + e.getKeyCode() == KeyEvent.VK_6 || + e.getKeyCode() == KeyEvent.VK_7 || + e.getKeyCode() == KeyEvent.VK_8 || + e.getKeyCode() == KeyEvent.VK_9; + + if(numberKeyWasPressed &&!timeCalcProfilesTxtFile.exists()) { + JOptionPane.showMessageDialog(null, "Warning: There is no profile assigned to Key with number, you pressed.", "Warning", JOptionPane.WARNING_MESSAGE); + } + if (numberKeyWasPressed && timeCalcProfilesTxtFile.exists()) { + + Properties properties = new Properties(); + try { + properties.load(new FileInputStream(timeCalcProfilesTxtFile)); + } catch (IOException ioException) { + ioException.printStackTrace(); + } + int profileNumber = 0; + Toaster toaster = new Toaster(); + toaster.setDisplayTime(5000); + switch(e.getKeyCode()) { + case KeyEvent.VK_0: profileNumber = 0;break; + case KeyEvent.VK_1: profileNumber = 1;break; + case KeyEvent.VK_2: profileNumber = 2;break; + case KeyEvent.VK_3: profileNumber = 3;break; + case KeyEvent.VK_4: profileNumber = 4;break; + case KeyEvent.VK_5: profileNumber = 5;break; + case KeyEvent.VK_6: profileNumber = 6;break; + case KeyEvent.VK_7: profileNumber = 7;break; + case KeyEvent.VK_8: profileNumber = 8;break; + case KeyEvent.VK_9: profileNumber = 9;break; + } + String key = String.valueOf(profileNumber); + if(properties.containsKey(key)) { + String profileName = (String) properties.get(key); + if(profileName.equals( timeCalcConfiguration.profileNameProperty)) { + toaster.showToaster("Profile \"" + profileName + "\" is already active. Nothing to do"); + } else { + toaster.showToaster("Info: Changing profile to: " + (( + profileName.isEmpty() ? "{Default profile}" : + profileName))); + TimeCalcProperties.getInstance().loadProfile(profileName); + timeCalcConfiguration.loadFromTimeCalcProperties( + TimeCalcProperties.getInstance()); + } + + } else { + JOptionPane.showMessageDialog(null, "Warning: There is no profile assigned to Key " + profileNumber, "Warning", JOptionPane.WARNING_MESSAGE); + } + } + if (e.getKeyCode() == KeyEvent.VK_F) { + Toaster toaster = new Toaster(); + if(timeCalcProfilesTxtFile.exists()) { + toaster.setDisplayTime(15000); + try { + toaster.showToaster(Utils.readTextFromFile(timeCalcProfilesTxtFile)); + } catch (IOException ioException) { + ioException.printStackTrace(); + toaster.showToaster("Error: " + ioException.getMessage()); + } + } else { + toaster.setDisplayTime(15000); + toaster.showToaster("Warning: There are no numbers assigned to profiles. Update file: " + timeCalcProfilesTxtFile.getAbsolutePath() + "."); + } + + } window.repaint(); } diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcProperties.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcProperties.java index 1bc692c..6583d81 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcProperties.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcProperties.java @@ -18,17 +18,33 @@ import java.util.Properties; */ public class TimeCalcProperties { - public static final File FILE = new File("timecalc.conf"); + public static final File FILE_WITHOUT_ANY_PROFILE = new File("timecalc.conf"); private static TimeCalcProperties INSTANCE; + private static final File timeCalcCurrentProfileTxtFile = new File("time-calc-current-profile.txt"); private final Properties properties = new Properties(); private final Map defaultProperties = new HashMap<>(); private TimeCalcProperties() { + System.out.println("Loading configuration - start"); + String profileName = ""; try { - this.properties.load(new FileInputStream("timecalc.conf")); + profileName = timeCalcCurrentProfileTxtFile.exists() ? Utils.readTextFromFile( + timeCalcCurrentProfileTxtFile) : ""; } catch (IOException e) { - System.err.println(e); + e.printStackTrace(); + throw new TimeCalcException(e); } + File file = getFile(profileName); + if(file.exists()) { + try { + this.properties.load(new FileInputStream(file)); + } catch (IOException e) { + e.printStackTrace(); + System.err.println(e); + } + } + System.out.println("Loading configuration - end"); + System.out.println("Loading default configuration - start"); try { String defaultConfiguration = Utils.readTextFromTextResourceInJar( "timecalc-default.conf"); @@ -38,14 +54,17 @@ public class TimeCalcProperties { .filter(l -> l.contains("=")) .forEach(l -> { String[] array = l.split("="); - defaultProperties.put(array[0], array[1]); + defaultProperties.put(array[0], array.length > 1 ? array[1] : ""); }); } catch (IOException e) { e.printStackTrace(); throw new TimeCalcException(e.getMessage()); + } catch (Exception e) { + e.printStackTrace(); + throw e; } - + System.out.println("Loading default configuration - end"); } public static TimeCalcProperties getInstance() { @@ -111,7 +130,7 @@ public class TimeCalcProperties { properties.replace(key, value.name()); } - public void save(Properties properties) { + public void save(Properties properties, String profileName) { properties.entrySet().stream().forEach(e -> { if (this.properties.containsKey(e.getKey())) { @@ -123,12 +142,31 @@ public class TimeCalcProperties { } } ); + File file = getFile(profileName); try { - this.properties.store(new FileOutputStream(FILE), null); - System.out.println("Saving to " + FILE + " was successful"); + this.properties.store(new FileOutputStream(file), null); + System.out.println("Saving to " + file + " was successful"); } catch (IOException e) { e.printStackTrace(); - System.out.println("Saving to " + FILE + " failed: " + e.getMessage()); + System.out.println( + "Saving to " + file + " failed: " + e.getMessage()); + } + + Utils.writeTextToFile(timeCalcCurrentProfileTxtFile, profileName); + } + + private File getFile(String profileName) { + return profileName == null || profileName.isEmpty() ? + FILE_WITHOUT_ANY_PROFILE : + new File("timecalc." + profileName + ".conf"); + } + + public void loadProfile(String profileName) { + try { + this.properties.load( new FileInputStream(getFile(profileName))); + } catch (IOException e) { + System.err.println(e); } } + } diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcProperty.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcProperty.java index e18ea9d..d5724f3 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcProperty.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/app/TimeCalcProperty.java @@ -62,7 +62,8 @@ public enum TimeCalcProperty { SQUARE_VISIBLE("square.visible", "Square"), CIRCLE_VISIBLE("circle.visible", "Circle"), WALKING_HUMAN_VISIBLE("walking-human.visible", "Walking Human"), - MAIN_WINDOW_CUSTOM_TITLE("main-window.custom-title", "Main Window : Custom Title"); + MAIN_WINDOW_CUSTOM_TITLE("main-window.custom-title", "Main Window : Custom Title"), + PROFILE_NAME("profile.name", "Profile : Name"); @Getter private final String key; diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/ConfigWindow.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/ConfigWindow.java index ce73c9c..e74e834 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/ConfigWindow.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/ConfigWindow.java @@ -137,6 +137,8 @@ public class ConfigWindow extends TWindow { = new JCheckBox(TimeCalcProperty.WALKING_HUMAN_VISIBLE.getKey()); private JTextField mainWindowCustomTitleProperty = new JTextField(); + private JTextField profileNameProperty + = new JTextField(); private final JPanel panelInsideScrollPane; public ConfigWindow(TimeCalcConfiguration timeCalcConfiguration) { @@ -272,7 +274,8 @@ public class ConfigWindow extends TWindow { squareVisibleProperty, circleVisibleProperty, walkingHumanVisibleProperty, - mainWindowCustomTitleProperty)); + mainWindowCustomTitleProperty, + profileNameProperty)); // propertiesList.stream().forEach(p -> { p.setAlignmentX(LEFT_ALIGNMENT); @@ -288,6 +291,10 @@ public class ConfigWindow extends TWindow { addToNextRow(new JLabel(TimeCalcProperty.MAIN_WINDOW_CUSTOM_TITLE.getDescription())); p.putClientProperty(CLIENT_PROPERTY_KEY, TimeCalcProperty.MAIN_WINDOW_CUSTOM_TITLE.getKey()); } + if (p == profileNameProperty) { + addToNextRow(new JLabel(TimeCalcProperty.PROFILE_NAME.getDescription())); + p.putClientProperty(CLIENT_PROPERTY_KEY, TimeCalcProperty.PROFILE_NAME.getKey()); + } if (p instanceof JComboBox) { JComboBox jComboBox = ((JComboBox) p); jComboBox.setMaximumSize(new Dimension(150, 25)); diff --git a/modules/time-calc-app/src/main/resources/help/Readme.md b/modules/time-calc-app/src/main/resources/help/Readme.md index e67ed54..d8de907 100644 --- a/modules/time-calc-app/src/main/resources/help/Readme.md +++ b/modules/time-calc-app/src/main/resources/help/Readme.md @@ -13,13 +13,13 @@ _Time Calc is written in Java programming language and uses the Swing framework. ### Start of application When "Time Calc" is started", user is asked for: - - start time ... like 7:30 - - overtime ... like 0:45 ... overtime is optional and the default value is 0:00 +- start time ... like 7:30 +- overtime ... like 0:45 ... overtime is optional and the default value is 0:00 ### Restart of application You can restart the app, if you press the **"Restart"** button. - - Then you are asked again for start time and overtime. +- Then you are asked again for start time and overtime. ### End of application @@ -33,7 +33,7 @@ If these files are present, something special happens. ### starttime.txt -This file contains the default start time - used during the previous run of the app. +This file contains the default start time - used during the previous run of the app. If file starttime.txt does not exist, then the default start time is 7:00. ### overtime.txt @@ -48,30 +48,30 @@ If file test.txt exists, then user is not asked for start time and overtime. Ins ### 3 Visibility modes - * STRONGLY_COLORED - many colors - * WEAKLY_COLORED - darkened colors - * GRAY - gray colors - * NONE - widgets are hidden +* STRONGLY_COLORED - many colors +* WEAKLY_COLORED - darkened colors +* GRAY - gray colors +* NONE - widgets are hidden ### Widgets - * +* #### Analog Clock - * hour hand - * minute hand (can be disabled in configuration) - * second hand (can be disabled in configuration) - * millisecond hand (can be disabled in configuration) - * shows current year, month, day of month and day of week, if analog clock is hovered by mouse cursor and Visibility is STRONGLY_COLORED - * shows yellow highlighted remaining time until end of today working hours, if analog clock is hovered by mouse cursor and Visibility is STRONGLY_COLORED - * hands can be long or shorter (can be set in configuration) +* hour hand +* minute hand (can be disabled in configuration) +* second hand (can be disabled in configuration) +* millisecond hand (can be disabled in configuration) +* shows current year, month, day of month and day of week, if analog clock is hovered by mouse cursor and Visibility is STRONGLY_COLORED +* shows yellow highlighted remaining time until end of today working hours, if analog clock is hovered by mouse cursor and Visibility is STRONGLY_COLORED +* hands can be long or shorter (can be set in configuration) #### Progress Square - * Show graphically day progress +* Show graphically day progress #### Progress Circle - * Show graphically day progress +* Show graphically day progress #### Hour Battery @@ -141,18 +141,19 @@ Smileys can be colored or white-black (can be set in configuration) * I - disable almost everything * E - enable or disable battery waves * B - hide or show buttons +* 0,1,2,3,4,5,6,7,8 or 9 - activates a profile +* F - show numbers for profiles ## Command button ## Todos - * Config window - * Split to Maven modules - * Junit, Mockito, etc. - * Checkstyle - * Sonarlint - * Sonarqube - * Add SQLite support and store times of arrivals and departures and time of activities +* Split to Maven modules +* Junit, Mockito, etc. +* Checkstyle +* Sonarlint +* Sonarqube +* Add SQLite support and store times of arrivals and departures and time of activities ## For Developers diff --git a/modules/time-calc-app/src/main/resources/timecalc-default.conf b/modules/time-calc-app/src/main/resources/timecalc-default.conf index e3353bf..590ad4d 100644 --- a/modules/time-calc-app/src/main/resources/timecalc-default.conf +++ b/modules/time-calc-app/src/main/resources/timecalc-default.conf @@ -44,6 +44,8 @@ smileys.colored=true square.visible=true circle.visible=true walking-human.visible=true +main-window.custom-title=--- +profile.name= #TODO: logs.detailed=false