Added support for profiles

This commit is contained in:
Robert Vokac 2024-03-03 13:19:59 +00:00
parent bd0bc03e38
commit b7ef2119f3
No known key found for this signature in database
GPG Key ID: 693D30BEE3329055
10 changed files with 180 additions and 42 deletions

4
.gitignore vendored
View File

@ -13,6 +13,8 @@ proxy.txt
out.txt out.txt
pocasi.txt pocasi.txt
test.txt test.txt
timecalc.conf timecalc*.conf
focus.txt focus.txt
dist/* dist/*
time-calc-current-profile.txt
time-calc-profiles.txt

View File

@ -141,13 +141,13 @@ Smileys can be colored or white-black (can be set in configuration)
* I - disable almost everything * I - disable almost everything
* E - enable or disable battery waves * E - enable or disable battery waves
* B - hide or show buttons * 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 ## Command button
## Todos ## Todos
* Custom main window title
* Profiles
* Split to Maven modules * Split to Maven modules
* Junit, Mockito, etc. * Junit, Mockito, etc.
* Checkstyle * Checkstyle

View File

@ -141,6 +141,8 @@ public class TimeCalcConfiguration {
= new BooleanProperty(TimeCalcProperty.WALKING_HUMAN_VISIBLE.getKey()); = new BooleanProperty(TimeCalcProperty.WALKING_HUMAN_VISIBLE.getKey());
public final StringProperty mainWindowCustomTitleProperty public final StringProperty mainWindowCustomTitleProperty
= new StringProperty(TimeCalcProperty.MAIN_WINDOW_CUSTOM_TITLE.getKey()); = new StringProperty(TimeCalcProperty.MAIN_WINDOW_CUSTOM_TITLE.getKey());
public final StringProperty profileNameProperty
= new StringProperty(TimeCalcProperty.PROFILE_NAME.getKey());
private final Map<TimeCalcProperty, Property> mapOfProperties = new HashMap<>(); private final Map<TimeCalcProperty, Property> mapOfProperties = new HashMap<>();
private List<Property> allProperties = new ArrayList<>(); private List<Property> allProperties = new ArrayList<>();
@ -190,7 +192,9 @@ public class TimeCalcConfiguration {
squareVisibleProperty, squareVisibleProperty,
circleVisibleProperty, circleVisibleProperty,
walkingHumanVisibleProperty, walkingHumanVisibleProperty,
mainWindowCustomTitleProperty,}) { mainWindowCustomTitleProperty,
profileNameProperty,
}) {
allProperties.add(p); allProperties.add(p);
} }
allProperties.stream().forEach(p -> mapOfProperties.put(TimeCalcProperty.forKey(p.getName()), p)); allProperties.stream().forEach(p -> mapOfProperties.put(TimeCalcProperty.forKey(p.getName()), p));
@ -219,7 +223,7 @@ public class TimeCalcConfiguration {
} }
Properties properties = new Properties(); Properties properties = new Properties();
this.allProperties.stream().forEach(p -> properties.put(p.getName(), p.getValue())); this.allProperties.stream().forEach(p -> properties.put(p.getName(), p.getValue()));
this.timeCalcProperties.save(properties); this.timeCalcProperties.save(properties, this.profileNameProperty.getValue());
} }

View File

@ -1,5 +1,7 @@
package org.nanoboot.utils.timecalc.app; package org.nanoboot.utils.timecalc.app;
import java.io.IOException;
/** /**
* @author Robert Vokac * @author Robert Vokac
* @since 21.02.2024 * @since 21.02.2024
@ -9,4 +11,8 @@ public class TimeCalcException extends RuntimeException {
public TimeCalcException(String msg) { public TimeCalcException(String msg) {
super(msg); super(msg);
} }
public TimeCalcException(Exception e) {
super(e);
}
} }

View File

@ -2,11 +2,17 @@ package org.nanoboot.utils.timecalc.app;
import org.nanoboot.utils.timecalc.entity.Visibility; import org.nanoboot.utils.timecalc.entity.Visibility;
import org.nanoboot.utils.timecalc.swing.common.MainWindow; 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.Jokes;
import org.nanoboot.utils.timecalc.utils.common.Utils; import org.nanoboot.utils.timecalc.utils.common.Utils;
import javax.swing.JOptionPane;
import java.awt.event.KeyAdapter; import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
/** /**
* @author Robert Vokac * @author Robert Vokac
@ -17,7 +23,7 @@ public class TimeCalcKeyAdapter extends KeyAdapter {
private final TimeCalcConfiguration timeCalcConfiguration; private final TimeCalcConfiguration timeCalcConfiguration;
private final TimeCalcApp timeCalcApp; private final TimeCalcApp timeCalcApp;
private final MainWindow window; private final MainWindow window;
private final File timeCalcProfilesTxtFile = new File("time-calc-profiles.txt");
public TimeCalcKeyAdapter( public TimeCalcKeyAdapter(
TimeCalcConfiguration timeCalcConfiguration, TimeCalcConfiguration timeCalcConfiguration,
TimeCalcApp timeCalcApp, TimeCalcApp timeCalcApp,
@ -157,6 +163,77 @@ public class TimeCalcKeyAdapter extends KeyAdapter {
MainWindow.hideShowCheckBox.setSelected(!MainWindow.hideShowCheckBox.isSelected()); 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(); window.repaint();
} }

View File

@ -18,17 +18,33 @@ import java.util.Properties;
*/ */
public class TimeCalcProperties { 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 TimeCalcProperties INSTANCE;
private static final File timeCalcCurrentProfileTxtFile = new File("time-calc-current-profile.txt");
private final Properties properties = new Properties(); private final Properties properties = new Properties();
private final Map<String, String> defaultProperties = new HashMap<>(); private final Map<String, String> defaultProperties = new HashMap<>();
private TimeCalcProperties() { private TimeCalcProperties() {
System.out.println("Loading configuration - start");
String profileName = "";
try { try {
this.properties.load(new FileInputStream("timecalc.conf")); profileName = timeCalcCurrentProfileTxtFile.exists() ? Utils.readTextFromFile(
timeCalcCurrentProfileTxtFile) : "";
} catch (IOException e) { } 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 { try {
String defaultConfiguration = Utils.readTextFromTextResourceInJar( String defaultConfiguration = Utils.readTextFromTextResourceInJar(
"timecalc-default.conf"); "timecalc-default.conf");
@ -38,14 +54,17 @@ public class TimeCalcProperties {
.filter(l -> l.contains("=")) .filter(l -> l.contains("="))
.forEach(l -> { .forEach(l -> {
String[] array = l.split("="); String[] array = l.split("=");
defaultProperties.put(array[0], array[1]); defaultProperties.put(array[0], array.length > 1 ? array[1] : "");
}); });
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
throw new TimeCalcException(e.getMessage()); throw new TimeCalcException(e.getMessage());
} catch (Exception e) {
e.printStackTrace();
throw e;
} }
System.out.println("Loading default configuration - end");
} }
public static TimeCalcProperties getInstance() { public static TimeCalcProperties getInstance() {
@ -111,7 +130,7 @@ public class TimeCalcProperties {
properties.replace(key, value.name()); properties.replace(key, value.name());
} }
public void save(Properties properties) { public void save(Properties properties, String profileName) {
properties.entrySet().stream().forEach(e properties.entrySet().stream().forEach(e
-> { -> {
if (this.properties.containsKey(e.getKey())) { if (this.properties.containsKey(e.getKey())) {
@ -123,12 +142,31 @@ public class TimeCalcProperties {
} }
} }
); );
File file = getFile(profileName);
try { try {
this.properties.store(new FileOutputStream(FILE), null); this.properties.store(new FileOutputStream(file), null);
System.out.println("Saving to " + FILE + " was successful"); System.out.println("Saving to " + file + " was successful");
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); 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);
} }
} }
} }

View File

@ -62,7 +62,8 @@ public enum TimeCalcProperty {
SQUARE_VISIBLE("square.visible", "Square"), SQUARE_VISIBLE("square.visible", "Square"),
CIRCLE_VISIBLE("circle.visible", "Circle"), CIRCLE_VISIBLE("circle.visible", "Circle"),
WALKING_HUMAN_VISIBLE("walking-human.visible", "Walking Human"), 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 @Getter
private final String key; private final String key;

View File

@ -137,6 +137,8 @@ public class ConfigWindow extends TWindow {
= new JCheckBox(TimeCalcProperty.WALKING_HUMAN_VISIBLE.getKey()); = new JCheckBox(TimeCalcProperty.WALKING_HUMAN_VISIBLE.getKey());
private JTextField mainWindowCustomTitleProperty private JTextField mainWindowCustomTitleProperty
= new JTextField(); = new JTextField();
private JTextField profileNameProperty
= new JTextField();
private final JPanel panelInsideScrollPane; private final JPanel panelInsideScrollPane;
public ConfigWindow(TimeCalcConfiguration timeCalcConfiguration) { public ConfigWindow(TimeCalcConfiguration timeCalcConfiguration) {
@ -272,7 +274,8 @@ public class ConfigWindow extends TWindow {
squareVisibleProperty, squareVisibleProperty,
circleVisibleProperty, circleVisibleProperty,
walkingHumanVisibleProperty, walkingHumanVisibleProperty,
mainWindowCustomTitleProperty)); mainWindowCustomTitleProperty,
profileNameProperty));
// //
propertiesList.stream().forEach(p -> { propertiesList.stream().forEach(p -> {
p.setAlignmentX(LEFT_ALIGNMENT); p.setAlignmentX(LEFT_ALIGNMENT);
@ -288,6 +291,10 @@ public class ConfigWindow extends TWindow {
addToNextRow(new JLabel(TimeCalcProperty.MAIN_WINDOW_CUSTOM_TITLE.getDescription())); addToNextRow(new JLabel(TimeCalcProperty.MAIN_WINDOW_CUSTOM_TITLE.getDescription()));
p.putClientProperty(CLIENT_PROPERTY_KEY, TimeCalcProperty.MAIN_WINDOW_CUSTOM_TITLE.getKey()); 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) { if (p instanceof JComboBox) {
JComboBox jComboBox = ((JComboBox) p); JComboBox jComboBox = ((JComboBox) p);
jComboBox.setMaximumSize(new Dimension(150, 25)); jComboBox.setMaximumSize(new Dimension(150, 25));

View File

@ -13,13 +13,13 @@ _Time Calc is written in Java programming language and uses the Swing framework.
### Start of application ### Start of application
When "Time Calc" is started", user is asked for: When "Time Calc" is started", user is asked for:
- start time ... like 7:30 - start time ... like 7:30
- overtime ... like 0:45 ... overtime is optional and the default value is 0:00 - overtime ... like 0:45 ... overtime is optional and the default value is 0:00
### Restart of application ### Restart of application
You can restart the app, if you press the **"Restart"** button. 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 ### End of application
@ -33,7 +33,7 @@ If these files are present, something special happens.
### starttime.txt ### 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. If file starttime.txt does not exist, then the default start time is 7:00.
### overtime.txt ### 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 ### 3 Visibility modes
* STRONGLY_COLORED - many colors * STRONGLY_COLORED - many colors
* WEAKLY_COLORED - darkened colors * WEAKLY_COLORED - darkened colors
* GRAY - gray colors * GRAY - gray colors
* NONE - widgets are hidden * NONE - widgets are hidden
### Widgets ### Widgets
* *
#### Analog Clock #### Analog Clock
* hour hand * hour hand
* minute hand (can be disabled in configuration) * minute hand (can be disabled in configuration)
* second hand (can be disabled in configuration) * second hand (can be disabled in configuration)
* millisecond 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 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 * 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) * hands can be long or shorter (can be set in configuration)
#### Progress Square #### Progress Square
* Show graphically day progress * Show graphically day progress
#### Progress Circle #### Progress Circle
* Show graphically day progress * Show graphically day progress
#### Hour Battery #### Hour Battery
@ -141,18 +141,19 @@ Smileys can be colored or white-black (can be set in configuration)
* I - disable almost everything * I - disable almost everything
* E - enable or disable battery waves * E - enable or disable battery waves
* B - hide or show buttons * 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 ## Command button
## Todos ## Todos
* Config window * Split to Maven modules
* Split to Maven modules * Junit, Mockito, etc.
* Junit, Mockito, etc. * Checkstyle
* Checkstyle * Sonarlint
* Sonarlint * Sonarqube
* Sonarqube * Add SQLite support and store times of arrivals and departures and time of activities
* Add SQLite support and store times of arrivals and departures and time of activities
## For Developers ## For Developers

View File

@ -44,6 +44,8 @@ smileys.colored=true
square.visible=true square.visible=true
circle.visible=true circle.visible=true
walking-human.visible=true walking-human.visible=true
main-window.custom-title=---
profile.name=
#TODO: #TODO:
logs.detailed=false logs.detailed=false