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 c87162b..eef9015 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 @@ -27,7 +27,7 @@ public class TimeCalcKeyAdapter extends KeyAdapter { private final TimeCalcApp timeCalcApp; private final MainWindow mainWindow; private final Time time; - private boolean changeByOneHour = false; + private boolean changeByFiveMinutes = false; public TimeCalcKeyAdapter( TimeCalcConfiguration timeCalcConfiguration, @@ -78,7 +78,7 @@ public class TimeCalcKeyAdapter extends KeyAdapter { boolean increase = shiftDown; boolean decrease = ctrlDown; boolean reset = altDown; - TTime changeTTime = changeByOneHour ? TTime.T_TIME_ONE_HOUR : TTime.T_TIME_ONE_MINUTE; + TTime changeTTime = changeByFiveMinutes ? TTime.T_TIME_FIVE_MINUTES : TTime.T_TIME_ONE_MINUTE; switch (keyCode) { case KeyEvent.VK_Y: { //Utils.showNotification((increase ? "Increasing" : (decrease ? "Decreasing" : "Reseting")) + " year."); @@ -161,8 +161,8 @@ public class TimeCalcKeyAdapter extends KeyAdapter { break; } case KeyEvent.VK_C: { - this.changeByOneHour = increase; - Utils.showNotification("Time will be changed by 1 " + (increase ? "hour" : "minute") + "."); + this.changeByFiveMinutes = increase; + Utils.showNotification("Time will be changed by " + (increase ? "5 minutes" : "1 minute") + "."); break; } case KeyEvent.VK_E: { diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/controls/TTextField.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/controls/TTextField.java index 1874b0c..05715e9 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/controls/TTextField.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/controls/TTextField.java @@ -1,20 +1,24 @@ package org.nanoboot.utils.timecalc.swing.controls; +import lombok.Getter; +import lombok.Setter; import org.nanoboot.utils.timecalc.app.GetProperty; import org.nanoboot.utils.timecalc.entity.Visibility; +import org.nanoboot.utils.timecalc.swing.common.SwingUtils; +import org.nanoboot.utils.timecalc.swing.windows.MainWindow; import org.nanoboot.utils.timecalc.utils.common.TTime; import org.nanoboot.utils.timecalc.utils.property.BooleanProperty; +import org.nanoboot.utils.timecalc.utils.property.ChangeListener; import org.nanoboot.utils.timecalc.utils.property.Property; import org.nanoboot.utils.timecalc.utils.property.StringProperty; import javax.swing.JComponent; +import javax.swing.JOptionPane; import javax.swing.JTextField; import javax.swing.Timer; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import java.awt.Color; -import org.nanoboot.utils.timecalc.swing.windows.MainWindow; -import org.nanoboot.utils.timecalc.swing.common.SwingUtils; /** * @author Robert Vokac @@ -35,7 +39,13 @@ public class TTextField extends JTextField implements GetProperty { = new StringProperty("visibilityProperty", Visibility.STRONGLY_COLORED.name()); public final StringProperty valueProperty = new StringProperty(); + @Getter + @Setter + private ChangeListener vetoableChangeListener = null; + @Getter + @Setter + private boolean editingOnlyInDialog = false; public TTextField() { this("", 0); } @@ -45,9 +55,23 @@ public class TTextField extends JTextField implements GetProperty { } public TTextField(String s, int customWidth) { + this(s, customWidth, false); + } + + public TTextField(String s, int customWidth, boolean editingOnlyInDialog) { + this(s, customWidth, editingOnlyInDialog, null); + } + public TTextField(String s, int customWidth, boolean editingOnlyInDialog, ChangeListener vetoableChangeListener) { super(s); + setEditingOnlyInDialog(editingOnlyInDialog); + setVetoableChangeListener(vetoableChangeListener); this.customWidth = customWidth; valueProperty.setValue(s); + new Timer(100, e -> { + if (editingOnlyInDialog) { + setEditable(false); + } + }).start(); getDocument() .addDocumentListener(new DocumentListener() { public void changedUpdate(DocumentEvent e) { @@ -67,6 +91,40 @@ public class TTextField extends JTextField implements GetProperty { } }); + + addMouseListener((MouseClickedListener) f -> { + if(editingOnlyInDialog) { + String result = (String) JOptionPane.showInputDialog( + null, + "Select new value", + "New value", + JOptionPane.PLAIN_MESSAGE, + null, + null, + getText() + ); + if (result != null) { + String oldText = getText(); + boolean vetoed = false; + if(vetoableChangeListener != null) { + try { + vetoableChangeListener + .changed(null, oldText, result); + } catch (Exception e) { + e.printStackTrace(); + System.err.println(e.getMessage()); + vetoed = true; + } + } + if(!vetoed) { + TTime tTime = new TTime(result); + result = tTime.toString().substring(0, tTime.isNegative() ? 6 : 5); + setText(result); + valueProperty.setValue(result); + } + } + }}); + valueProperty.addListener(e -> { if (!valueProperty.getValue().equals(getText())) { diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/windows/MainWindow.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/windows/MainWindow.java index 0576423..2942d9d 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/windows/MainWindow.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/windows/MainWindow.java @@ -1,12 +1,5 @@ package org.nanoboot.utils.timecalc.swing.windows; -import org.nanoboot.utils.timecalc.swing.controls.SmallTButton; -import org.nanoboot.utils.timecalc.swing.controls.TTextField; -import org.nanoboot.utils.timecalc.swing.controls.TLabel; -import org.nanoboot.utils.timecalc.swing.controls.TCheckBox; -import org.nanoboot.utils.timecalc.swing.controls.TButton; -import org.nanoboot.utils.timecalc.swing.controls.TWindow; -import org.nanoboot.utils.timecalc.swing.controls.ComponentRegistry; import org.nanoboot.utils.timecalc.app.CommandActionListener; import org.nanoboot.utils.timecalc.app.GetProperty; import org.nanoboot.utils.timecalc.app.TimeCalcApp; @@ -15,6 +8,22 @@ import org.nanoboot.utils.timecalc.app.TimeCalcKeyAdapter; import org.nanoboot.utils.timecalc.app.TimeCalcProperties; import org.nanoboot.utils.timecalc.app.TimeCalcProperty; import org.nanoboot.utils.timecalc.entity.Visibility; +import org.nanoboot.utils.timecalc.entity.WorkingDay; +import org.nanoboot.utils.timecalc.persistence.api.ActivityRepositoryApi; +import org.nanoboot.utils.timecalc.persistence.impl.sqlite.ActivityRepositorySQLiteImpl; +import org.nanoboot.utils.timecalc.persistence.impl.sqlite.WorkingDayRepositorySQLiteImpl; +import org.nanoboot.utils.timecalc.swing.common.AboutButton; +import org.nanoboot.utils.timecalc.swing.common.SwingUtils; +import org.nanoboot.utils.timecalc.swing.common.Toaster; +import org.nanoboot.utils.timecalc.swing.common.WeekStatistics; +import org.nanoboot.utils.timecalc.swing.common.Widget; +import org.nanoboot.utils.timecalc.swing.controls.ComponentRegistry; +import org.nanoboot.utils.timecalc.swing.controls.SmallTButton; +import org.nanoboot.utils.timecalc.swing.controls.TButton; +import org.nanoboot.utils.timecalc.swing.controls.TCheckBox; +import org.nanoboot.utils.timecalc.swing.controls.TLabel; +import org.nanoboot.utils.timecalc.swing.controls.TTextField; +import org.nanoboot.utils.timecalc.swing.controls.TWindow; import org.nanoboot.utils.timecalc.swing.progress.AnalogClock; import org.nanoboot.utils.timecalc.swing.progress.Battery; import org.nanoboot.utils.timecalc.swing.progress.DayBattery; @@ -33,6 +42,9 @@ import org.nanoboot.utils.timecalc.utils.common.FileConstants; import org.nanoboot.utils.timecalc.utils.common.Jokes; import org.nanoboot.utils.timecalc.utils.common.TTime; import org.nanoboot.utils.timecalc.utils.common.Utils; +import org.nanoboot.utils.timecalc.utils.property.ChangeListener; +import org.nanoboot.utils.timecalc.utils.property.IntegerProperty; +import org.nanoboot.utils.timecalc.utils.property.Property; import javax.swing.JCheckBox; import javax.swing.JFrame; @@ -44,19 +56,11 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.StandardCopyOption; +import java.util.ArrayList; import java.util.Calendar; import java.util.Date; - -import org.nanoboot.utils.timecalc.entity.WorkingDay; -import org.nanoboot.utils.timecalc.persistence.api.ActivityRepositoryApi; -import org.nanoboot.utils.timecalc.persistence.impl.sqlite.ActivityRepositorySQLiteImpl; -import org.nanoboot.utils.timecalc.persistence.impl.sqlite.WorkingDayRepositorySQLiteImpl; -import org.nanoboot.utils.timecalc.swing.common.AboutButton; -import org.nanoboot.utils.timecalc.swing.common.SwingUtils; -import org.nanoboot.utils.timecalc.swing.common.Toaster; -import org.nanoboot.utils.timecalc.swing.common.WeekStatistics; -import org.nanoboot.utils.timecalc.swing.common.Widget; -import org.nanoboot.utils.timecalc.utils.property.IntegerProperty; +import java.util.List; +import java.util.stream.Collectors; /** * @author Robert Vokac @@ -103,10 +107,18 @@ public class MainWindow extends TWindow { { - this.arrivalTextField = new TTextField(Constants.DEFAULT_ARRIVAL_TIME, 40); - this.overtimeTextField = new TTextField(Constants.DEFAULT_OVERTIME, 40); - this.workingTimeTextField = new TTextField("8:00", 40); - this.pauseTimeTextField = new TTextField("0:30", 40); + ChangeListener valueMustBeTime = new ChangeListener() { + @Override + public void changed(Property property, Object oldValue, + Object newValue) { + new TTime((String) newValue); + } + }; + this.arrivalTextField = new TTextField(Constants.DEFAULT_ARRIVAL_TIME, 40, true,valueMustBeTime); + this.overtimeTextField = new TTextField(Constants.DEFAULT_OVERTIME, 40, true,valueMustBeTime); + this.workingTimeTextField = new TTextField("08:00", 40, true,valueMustBeTime); + this.pauseTimeTextField = new TTextField("00:30", 40, true,valueMustBeTime); + this.noteTextField = new TTextField("", 100); this.departureTextField = new TTextField(); this.elapsedTextField = new TTextField("", 100); @@ -338,10 +350,6 @@ public class MainWindow extends TWindow { noteTextField.setBoundsFromLeft(noteTextFieldLabel); timeOffCheckBox.setBoundsFromLeft(noteTextField); // - arrivalTextField.setEditable(false); - overtimeTextField.setEditable(false); - workingTimeTextField.setEditable(false); - pauseTimeTextField.setEditable(false); add(arrivalTextFieldLabel); add(arrivalTextField); @@ -670,43 +678,84 @@ public class MainWindow extends TWindow { forgetOvertimeProperty.setValue(wd.getForgetOvertime()); } else { Calendar cal = time.asCalendar(); + wd = new WorkingDay(); + { + Calendar cal2 = Calendar.getInstance(); + cal2.setTime(cal.getTime()); + List arrivals = new ArrayList<>(); + for(int i = 1; i <= 90; i++) { + cal2.add(Calendar.DAY_OF_MONTH, -1); + WorkingDay wd_ = workingDayRepository.read(cal2); + if(wd_ == null || wd_.isThisDayTimeOff()) { + continue; + } + arrivals.add(wd_); + if(arrivals.size() == 20) { + break; + } + } + + if(!arrivals.isEmpty()) { +// double averageArrival = arrivals.size() == 1 ? arrivals.get(0) : arrivals.stream().mapToDouble(Double::doubleValue).sorted().average().getAsDouble(); + double medianArrival = arrivals.stream().map(a->a.getArrivalAsDouble()) + .sorted() + .collect(Collectors.collectingAndThen( + Collectors.toList(), + a -> (a.size() % 2 == 0) ? ((a.get(a.size() / 2 - 1) + a.get(a.size() / 2)) / 2) : (a.get(a.size() / 2)))); + + TTime arrivalTTime = TTime.ofMilliseconds((int)(medianArrival * 60 * 60 * 1000)); + while(arrivalTTime.getMinute() % 5 != 0) { + arrivalTTime = arrivalTTime.add(new TTime(0,1)); + } + arrivalTextField.valueProperty.setValue(arrivalTTime.toString().substring(0, 5)); + wd.setArrivalHour(arrivalTTime.getHour()); + wd.setArrivalMinute(arrivalTTime.getMinute()); + + } else { + wd.setArrivalHour(7); + wd.setArrivalMinute(0); + } + + } int year = cal.get(Calendar.YEAR); int month = cal.get(Calendar.MONTH) + 1; int day = cal.get(Calendar.DAY_OF_MONTH); - wd = new WorkingDay(); - wd.setId(WorkingDay.createId(year, month, day)); - wd.setYear(year); - wd.setMonth(month); - wd.setDay(day); - wd.setArrivalHour(7); - wd.setArrivalMinute(0); - wd.setOvertimeHour(0); - wd.setOvertimeMinute(0); - wd.setWorkingTimeInMinutes(480); - wd.setPauseTimeInMinutes(30); - wd.setNote(""); - wd.setTimeOff(false); + + wd.setId(WorkingDay.createId(year, month, day)); + wd.setYear(year); + wd.setMonth(month); + wd.setDay(day); + wd.setOvertimeHour(0); + wd.setOvertimeMinute(0); + wd.setWorkingTimeInMinutes(480); + wd.setPauseTimeInMinutes(30); + wd.setNote(""); + wd.setTimeOff(false); } - - workingDayRepository.update(wd); - System.out.println(wd); - - File dbFile = new File(FileConstants.TC_DIRECTORY.getAbsolutePath() + "/" + "time-calc.sqlite3"); + workingDayRepository.update(wd); while (true) { - if(Math.random() > 0.999) { - File dbFileBackup = new File(dbFile.getAbsolutePath() + ".backup." + DateFormats.DATE_TIME_FORMATTER_SHORT.format(new Date()).substring(0, 10) + ".sqlite3"); - if (dbFile.exists() && !dbFileBackup.exists()) { + if(Math.random() > 0.99) { + File dbFileBackup = new File( + FileConstants.DB_FILE.getAbsolutePath() + ".backup." + + DateFormats.DATE_TIME_FORMATTER_SHORT + .format(new Date()).substring(0, 10) + + ".sqlite3"); + if (FileConstants.DB_FILE.exists() && !dbFileBackup.exists()) { try { - Files.copy(dbFile.toPath(), dbFileBackup.toPath(), StandardCopyOption.REPLACE_EXISTING); + Files.copy(FileConstants.DB_FILE.toPath(), + dbFileBackup.toPath(), + StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { e.printStackTrace(); } } + } + if(Math.random() > 0.9999) { for(File file: FileConstants.TC_DIRECTORY.listFiles()) { - if(file.getName().startsWith(dbFile.getName() + ".backup")) { + if(file.getName().startsWith(FileConstants.DB_FILE.getName() + ".backup")) { try { long now = System.currentTimeMillis(); long diff = now - Files.getLastModifiedTime(file.toPath()).toMillis(); diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/utils/common/FileConstants.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/utils/common/FileConstants.java index 7b4ae9e..0bccaa9 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/utils/common/FileConstants.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/utils/common/FileConstants.java @@ -17,6 +17,7 @@ public class FileConstants { public static final File FILE_WITHOUT_ANY_PROFILE = new File(TC_DIRECTORY, "timecalc.conf"); public static final File JOKES_TXT = new File(TC_DIRECTORY, "time-calc-jokes.txt"); + public static final File DB_FILE = new File(FileConstants.TC_DIRECTORY.getAbsolutePath() + "/" + "time-calc.sqlite3"); private FileConstants() { //Not meant to be instantiated. diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/utils/common/TTime.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/utils/common/TTime.java index 3fef585..6c86790 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/utils/common/TTime.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/utils/common/TTime.java @@ -2,6 +2,7 @@ package org.nanoboot.utils.timecalc.utils.common; import lombok.Getter; import lombok.Setter; +import org.nanoboot.utils.timecalc.app.TimeCalcException; import java.time.Duration; import java.time.temporal.ChronoUnit; @@ -20,6 +21,7 @@ public class TTime implements Comparable { public static final TTime T_TIME_ONE_MINUTE = new TTime(0, 1); public static final TTime T_TIME_ONE_HOUR = new TTime(1,0); + public static final TTime T_TIME_FIVE_MINUTES = new TTime(0,5); @Getter @Setter private boolean negative; @@ -100,6 +102,9 @@ public class TTime implements Comparable { string = string.replace("-", ""); } String[] array = string.split(":"); + if(array.length < 2) { + throw new TimeCalcException("Wrong format of time: " + string); + } this.hour = (negative ? (1) : 1) * Integer.valueOf(array[0]); this.minute = (negative ? (1) : 1) * Integer.valueOf(array[1]); this.second = array.length >= 3 ? ((negative ? (1) : 1) * Integer.valueOf(array[2])) : 0; @@ -167,7 +172,7 @@ public class TTime implements Comparable { public static int countDiffInMinutes(TTime startTime, TTime endTime) { return (endTime.getHour() * TTime.MINUTES_PER_HOUR + endTime .getMinute()) - (startTime.getHour() * TTime.MINUTES_PER_HOUR - + startTime.getMinute()); + + startTime.getMinute()); } public TTime cloneInstance() { 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 38eeaba..7a18d25 100644 --- a/modules/time-calc-app/src/main/resources/help/Readme.md +++ b/modules/time-calc-app/src/main/resources/help/Readme.md @@ -199,7 +199,7 @@ Smileys can be colored or white-black (can be set in configuration) * CTRL + W - Decrease worknig time * SHIFT + P - Increase pause * CTRL + P - Decrease pause -* SHIFT + C - Increase or decrease of time is change by 1 hour +* SHIFT + C - Increase or decrease of time is change by 5 minutes * CTRL + C - Increase or decrease of time is change by 1 minute * CTRL + E - Save arrival, overtime, working time, pause time and note