Skip to content

Commit

Permalink
Added entry optimizations + Bugfixes related to automatically selecte…
Browse files Browse the repository at this point in the history
…d year and default file names (#203)

* Made Timefields accept . as :
- Auto-replace on confirm

* Revert Changes in parseTime

* Enabled Tab Switch for Activity
- Changed Type of Activity from TextArea to TextField to enable switching fields with tabs
- Removed containing ScrollPane
- Increased Max Activity Length from 27 to 30

* Solved Dialog Closing Issue
- When discarding the edit dialog, the entry is now unchanged (added back)

* minor fixes in sidebar

* Spotless apply

---------

Co-authored-by: Dominik Fuchß <[email protected]>
  • Loading branch information
Just1Developer and dfuchss authored Jan 28, 2025
1 parent bab7521 commit 0055199
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 33 deletions.
60 changes: 35 additions & 25 deletions src/main/java/ui/DialogHelper.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Licensed under MIT 2024. */
/* Licensed under MIT 2024-2025. */
package ui;

import javax.swing.*;
Expand All @@ -8,6 +8,8 @@
import java.awt.*;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.time.Duration;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
Expand All @@ -29,7 +31,7 @@ private DialogHelper() {
static final Pattern TIME_PATTERN_SMALL = Pattern.compile("^(\\d{1,2})$");
static final Pattern TIME_PATTERN_SEMI_SMALL = Pattern.compile("^(\\d{1,2}):(\\d)$");

private static final int MAX_TEXT_LENGTH_ACTIVITY = 27;
private static final int MAX_TEXT_LENGTH_ACTIVITY = 30;
private static final int MIN_BREAK_SIX_HOURS = 30;
private static final int MIN_BREAK_NINE_HOURS = 45;

Expand Down Expand Up @@ -74,23 +76,20 @@ public static void showEntryDialog(UserInterface parentUi, String title, Timeshe
gbc.anchor = GridBagConstraints.NORTHWEST;
panel.add(actionLabel, gbc);

JTextArea actionTextArea = new JTextArea(1, MAX_TEXT_LENGTH_ACTIVITY);
JScrollPane scrollPane = new JScrollPane(actionTextArea);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
JTextField actionTextField = new JTextField("", MAX_TEXT_LENGTH_ACTIVITY);

addPlaceholderText(actionTextArea, "Describe the activity", entry.getActivity());
addPlaceholderText(actionTextField, "Describe the activity", entry.getActivity());
if (!entry.getActivity().isEmpty()) {
actionTextArea.setText(entry.getActivity());
actionTextField.setText(entry.getActivity());
taskSummaryValue.setText(entry.getActivity());
}
((AbstractDocument) actionTextArea.getDocument()).setDocumentFilter(new DocumentSizeFilter(MAX_TEXT_LENGTH_ACTIVITY));
((AbstractDocument) actionTextField.getDocument()).setDocumentFilter(new DocumentSizeFilter(MAX_TEXT_LENGTH_ACTIVITY));

gbc.gridx = 1;
gbc.gridy = row;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.BOTH;
panel.add(scrollPane, gbc);
panel.add(actionTextField, gbc);

row++;

Expand Down Expand Up @@ -219,19 +218,23 @@ public void focusLost(FocusEvent e) {

// Action listeners for buttons
makeEntryButton.addActionListener(e -> {
if (makeEntryAction(parentUi, durationWarningLabel, actionTextArea, timeFields, vacationCheckBox))
if (makeEntryAction(parentUi, durationWarningLabel, actionTextField, timeFields, vacationCheckBox))
dialog.dispose();
});

cancelButton.addActionListener(e -> {
// Since the old entry will be deleted, we need to add it back
if (!entry.isEmpty())
parentUi.addEntry(entry);
dialog.dispose();
discardChanges(entry, parentUi, dialog);
});

dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
discardChanges(entry, parentUi, dialog);
}
});

// Update task summary when activity text changes
actionTextArea.getDocument().addDocumentListener(new DocumentListener() {
actionTextField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
update();
Expand All @@ -248,10 +251,10 @@ public void changedUpdate(DocumentEvent e) {
}

private void update() {
if (actionTextArea.getForeground() != Color.BLACK)
if (actionTextField.getForeground() != Color.BLACK)
return; // Not if placeholder text
taskSummaryValue.setText(actionTextArea.getText());
if (!actionTextArea.getText().isBlank() && durationWarningLabel.getText().equals(ACTIVITY_MESSAGE)) {
taskSummaryValue.setText(actionTextField.getText());
if (!actionTextField.getText().isBlank() && durationWarningLabel.getText().equals(ACTIVITY_MESSAGE)) {
durationWarningLabel.setText(" ");
updateDurationSummary(durationSummaryValue, timeFields[INDEX_START_TIME], timeFields[INDEX_END_TIME], timeFields[INDEX_BREAK_TIME],
durationWarningLabel, vacationCheckBox);
Expand All @@ -263,22 +266,29 @@ private void update() {
dialog.setVisible(true);
}

private static void discardChanges(TimesheetEntry entry, UserInterface parentUi, JDialog dialog) {
// Since the old entry will be deleted, we need to add it back
if (!entry.isEmpty())
parentUi.addEntry(entry);
dialog.dispose();
}

/**
* The Action for the "Make Entry" Button in the "Add/Edit Entry" Dialog.
* Returns if the dialog should be disposed (success) or if it should be kept
* open (failure).
*
*
* @param parentUI The parent UserInterface.
* @param durationWarningLabel The warning label for the work time message.
* @param actionTextArea The text area for the activity.
* @param actionTextField The text field for the activity.
* @param timeFields The array of fields for the times.
* @param vacationCheckBox The vacation checkbox.
* @return True if the dialog should be disposed, false if not.
*/
private static boolean makeEntryAction(UserInterface parentUI, JLabel durationWarningLabel, JTextArea actionTextArea, JTextField[] timeFields,
private static boolean makeEntryAction(UserInterface parentUI, JLabel durationWarningLabel, JTextField actionTextField, JTextField[] timeFields,
JCheckBox vacationCheckBox) {
if (durationWarningLabel.getText().isBlank()) {
if (actionTextArea.getText().isBlank()) {
if (actionTextField.getText().isBlank()) {
durationWarningLabel.setText(ACTIVITY_MESSAGE);
}
// warning label is updated automatically when fields are edited
Expand Down Expand Up @@ -315,7 +325,7 @@ private static boolean makeEntryAction(UserInterface parentUI, JLabel durationWa
timeFields[INDEX_BREAK_TIME].setText("00:00");
}

TimesheetEntry newEntry = TimesheetEntry.generateTimesheetEntry(actionTextArea.getText(), Integer.parseInt(timeFields[INDEX_DAY].getText()),
TimesheetEntry newEntry = TimesheetEntry.generateTimesheetEntry(actionTextField.getText(), Integer.parseInt(timeFields[INDEX_DAY].getText()),
timeFields[INDEX_START_TIME].getText(), timeFields[INDEX_END_TIME].getText(), timeFields[INDEX_BREAK_TIME].getText(),
vacationCheckBox.isSelected());
parentUI.addEntry(newEntry);
Expand Down Expand Up @@ -374,7 +384,7 @@ public void focusLost(FocusEvent e) {
}

private static void validateTimeField(JTextField timeField, JLabel errorLabel, boolean isBreak) {
String text = timeField.getText().trim();
String text = timeField.getText().trim().replace('.', ':');
if (text.equals(TIME_PLACEHOLDER) || text.equals(TIME_BREAK_PLACEHOLDER)) {
errorLabel.setText(" ");
return;
Expand Down
8 changes: 3 additions & 5 deletions src/main/java/ui/JTimeField.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Licensed under MIT 2024. */
/* Licensed under MIT 2024-2025. */
package ui;

import javax.swing.*;
Expand Down Expand Up @@ -34,19 +34,17 @@ public void focusLost(FocusEvent e) {
}

private void validateField() {
String text = this.getText();
String text = this.getText().trim().replace('.', ':');

if (DialogHelper.TIME_PATTERN_SMALL.matcher(text).matches()) {
text += ":00";
super.setText(text);
} else if (DialogHelper.TIME_PATTERN_SEMI_SMALL.matcher(text).matches()) {
text += "0";
super.setText(text);
}
if (TIME_PATTERN_SEMI_SMALL_2.matcher(text).matches()) {
text = "0" + text;
super.setText(text);
}
super.setText(text);

if (!text.isBlank() && !DialogHelper.TIME_PATTERN.matcher(text).matches()) {
setForeground(Color.RED);
Expand Down
15 changes: 12 additions & 3 deletions src/main/java/ui/MonthlySettingsBar.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Licensed under MIT 2024. */
/* Licensed under MIT 2024-2025. */
package ui;

import ui.json.Month;
Expand Down Expand Up @@ -125,9 +125,18 @@ public int getSelectedMonthNumber() {

public String getYear() {
if (semesterTextField.getForeground() == Color.BLACK && !semesterTextField.getText().isBlank()) {
return semesterTextField.getText();
// Winter semester
int year;
try {
year = Integer.parseInt(semesterTextField.getText());
} catch (NumberFormatException e) {
return DateTimeFormatter.ofPattern("yy").format(LocalDateTime.now());
}
if (getSelectedMonthNumber() < 6)
year++; // New year
return String.valueOf(year);
}
return DateTimeFormatter.ofPattern("yy").format(LocalDateTime.now());
return semesterTextField.getText();
}

public Time getPredTime() {
Expand Down

0 comments on commit 0055199

Please sign in to comment.