diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/entity/Activity.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/entity/Activity.java index f0aed06..ac545f5 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/entity/Activity.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/entity/Activity.java @@ -8,6 +8,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; import lombok.ToString; +import org.nanoboot.utils.timecalc.utils.common.NumberFormats; /** * @author Robert Vokac @@ -31,7 +32,7 @@ public class Activity implements Comparable { private int spentHours; private int spentMinutes; private String flags; - private String nextActivityId; + private int sortkey; public String createSubject() { return ticket + SUBJECT_FIELD_SEPARATOR + name; @@ -39,13 +40,18 @@ public class Activity implements Comparable { public String createTotalComment() { return ticket + SUBJECT_FIELD_SEPARATOR + year + "-" + month + "-" + day - + SUBJECT_FIELD_SEPARATOR + ((spentHours + spentMinutes / 60d) - + "h") + SUBJECT_FIELD_SEPARATOR + + SUBJECT_FIELD_SEPARATOR + ( + NumberFormats.FORMATTER_TWO_DECIMAL_PLACES.format(spentHours + spentMinutes / 60d) + + "h") + SUBJECT_FIELD_SEPARATOR + comment; } public Set flagsAsSet() { Set set = new HashSet<>(); for(String flag:flags.split(":")) { + if(flag.isEmpty()) { + //nothing to do + continue; + } set.add(flag); } return set; @@ -64,24 +70,10 @@ public class Activity implements Comparable { @Override public int compareTo(Activity o) { - int result = Integer.valueOf(year).compareTo(Integer.valueOf(o.year)); - if(result != 0) { - return result; - } - result = Integer.valueOf(month).compareTo(Integer.valueOf(o.month)); - if(result != 0) { - return result; - } - result = Integer.valueOf(day).compareTo(Integer.valueOf(o.day)); - if(result != 0) { - return result; - } - if(this.nextActivityId != null && this.nextActivityId.equals(o.getId())) { - return -1; - } - if(o.nextActivityId != null && o.nextActivityId.equals(o.getId())) { - return 1; - } - return 0; + return Integer.valueOf(sortkey).compareTo(Integer.valueOf(o.sortkey)); + } + + public String getSpentTimeAsString() { + return (getSpentHours() < 10 ? "0" : "") + getSpentHours() + ":" + (getSpentMinutes() < 10 ? "0" : "") + getSpentMinutes(); } } diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/entity/ActivityForStats.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/entity/ActivityForStats.java index edad733..bfc13e2 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/entity/ActivityForStats.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/entity/ActivityForStats.java @@ -17,14 +17,14 @@ public class ActivityForStats extends Activity { public ActivityForStats(String id, int year, int month, int day, String name, String comment, String ticket, int spentHours, int spentMinutes, - String flags, String nextActivityId, + String flags, int sortkey, int todaySpentHours, int todaySpentMinutes, int todayRemainsHours, int todayRemainsMinutes) { super(id, year, month, day, name, comment, ticket, spentHours, spentMinutes, - flags, nextActivityId); + flags, sortkey); this.todaySpentHours = todaySpentHours; this.todaySpentMinutes = todaySpentMinutes; this.todayRemainsHours = todayRemainsHours; diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/persistence/api/ActivityRepositoryApi.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/persistence/api/ActivityRepositoryApi.java index 3ab3d0d..c49fd85 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/persistence/api/ActivityRepositoryApi.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/persistence/api/ActivityRepositoryApi.java @@ -12,10 +12,6 @@ public interface ActivityRepositoryApi { void create(Activity activity); - Activity getLastActivityForDay(int year, int month, int day); - - Activity getPreviousActivity(String id); - List list(int year, int month, int day); List list(String ticket); @@ -28,4 +24,10 @@ public interface ActivityRepositoryApi { public List getYears(); + public void putToClipboard(Activity activity); + + public Activity getFromClipboard(); + + public int getLargestSortkey(int year, int month, int day); + } diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/persistence/impl/sqlite/ActivityRepositorySQLiteImpl.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/persistence/impl/sqlite/ActivityRepositorySQLiteImpl.java index ee0992d..0d17ba9 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/persistence/impl/sqlite/ActivityRepositorySQLiteImpl.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/persistence/impl/sqlite/ActivityRepositorySQLiteImpl.java @@ -1,17 +1,18 @@ package org.nanoboot.utils.timecalc.persistence.impl.sqlite; +import org.nanoboot.utils.timecalc.app.TimeCalcException; +import org.nanoboot.utils.timecalc.entity.Activity; +import org.nanoboot.utils.timecalc.persistence.api.ActivityRepositoryApi; +import org.nanoboot.utils.timecalc.utils.common.Utils; + import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.ArrayList; -import org.nanoboot.utils.timecalc.persistence.api.ActivityRepositoryApi; - import java.util.List; -import org.nanoboot.utils.timecalc.app.TimeCalcException; -import org.nanoboot.utils.timecalc.entity.Activity; -import org.nanoboot.utils.timecalc.utils.common.Utils; +import java.util.OptionalInt; /** * @author Robert Vokac @@ -25,9 +26,10 @@ public class ActivityRepositorySQLiteImpl implements ActivityRepositoryApi { this.sqliteConnectionFactory = sqliteConnectionFactory; } + private Activity activityInClipboard = null; @Override public void create(Activity activity) { - Activity lastActivityForDay = getLastActivityForDay(activity.getYear(), activity.getMonth(), activity.getDay()); + StringBuilder sb = new StringBuilder(); sb .append("INSERT INTO ") @@ -51,7 +53,7 @@ public class ActivityRepositorySQLiteImpl implements ActivityRepositoryApi { stmt.setInt(++i, activity.getSpentHours()); stmt.setInt(++i, activity.getSpentMinutes()); stmt.setString(++i, activity.getFlags()); - stmt.setNull(++i, Types.VARCHAR); + stmt.setInt(++i, activity.getSortkey()); // stmt.execute(); @@ -64,11 +66,6 @@ public class ActivityRepositorySQLiteImpl implements ActivityRepositoryApi { throw new TimeCalcException(ex); } - if(lastActivityForDay != null) { - lastActivityForDay.setNextActivityId(activity.getId()); - update(lastActivityForDay); - } - } @Override @@ -103,12 +100,7 @@ public class ActivityRepositorySQLiteImpl implements ActivityRepositoryApi { ex.printStackTrace(); throw new TimeCalcException(ex); } - Activity previousActivity = getPreviousActivity(id); - Activity nextActivity = read(activityToBeDeleted.getNextActivityId()); - if(previousActivity != null) { - previousActivity.setNextActivityId(nextActivity == null ? null : nextActivity.getId()); - update(previousActivity); - } + } @@ -210,7 +202,7 @@ public class ActivityRepositorySQLiteImpl implements ActivityRepositoryApi { .append(ActivityTable.SPENT_HOURS).append("=?, ") .append(ActivityTable.SPENT_MINUTES).append("=?, ") .append(ActivityTable.FLAGS).append("=?, ") - .append(ActivityTable.NEXT_ACTIVITY_ID).append("=? ") + .append(ActivityTable.SORTKEY).append("=? ") .append(" WHERE ").append( ActivityTable.ID).append("=?"); @@ -225,7 +217,7 @@ public class ActivityRepositorySQLiteImpl implements ActivityRepositoryApi { stmt.setInt(++i, activity.getSpentHours()); stmt.setInt(++i, activity.getSpentMinutes()); stmt.setString(++i, activity.getFlags()); - stmt.setString(++i, activity.getNextActivityId()); + stmt.setInt(++i, activity.getSortkey()); stmt.setString(++i, activity.getId()); @@ -293,7 +285,7 @@ public class ActivityRepositorySQLiteImpl implements ActivityRepositoryApi { rs.getInt(ActivityTable.SPENT_HOURS), rs.getInt(ActivityTable.SPENT_MINUTES), rs.getString(ActivityTable.FLAGS), - rs.getString(ActivityTable.NEXT_ACTIVITY_ID) + rs.getInt(ActivityTable.SORTKEY) ); } @@ -336,101 +328,37 @@ public class ActivityRepositorySQLiteImpl implements ActivityRepositoryApi { return result; } - @Override - public Activity getLastActivityForDay(int year, int month, int day) { - - List result = new ArrayList<>(); - StringBuilder sb = new StringBuilder(); - sb - .append("SELECT * FROM ") - .append(ActivityTable.TABLE_NAME) - .append(" WHERE ") - .append(ActivityTable.YEAR).append("=? AND ") - .append(ActivityTable.MONTH).append("=? AND ") - .append(ActivityTable.DAY).append("=? AND ") - .append(ActivityTable.NEXT_ACTIVITY_ID) - .append(" IS NULL "); - - String sql = sb.toString(); - int i = 0; - ResultSet rs = null; - try ( - Connection connection = sqliteConnectionFactory.createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) { - - stmt.setInt(++i, year); - stmt.setInt(++i, month); - stmt.setInt(++i, day); - rs = stmt.executeQuery(); - - while (rs.next()) { - result.add(extractActivityFromResultSet(rs)); - } - } catch (SQLException | ClassNotFoundException e) { - System.out.println(e.getMessage()); - throw new RuntimeException(e); - } finally { - try { - if (rs != null) { - rs.close(); - } - } catch (SQLException ex) { - System.out.println(ex.getMessage()); - throw new RuntimeException(ex); - } - } - if(result.isEmpty()) { - return null; - } - if(result.size() == 1) { - return result.get(0); - } - throw new TimeCalcException("Fatal error: More (" + result.size() + ") than one activity per one day with next activity id set to null: " + year + ", " + month + ", " + day); + public void putToClipboard(Activity activity) { + this.activityInClipboard = activity; } @Override - public Activity getPreviousActivity(String id) { - - List result = new ArrayList<>(); - StringBuilder sb = new StringBuilder(); - sb - .append("SELECT * FROM ") - .append(ActivityTable.TABLE_NAME) - .append(" WHERE ") - .append(ActivityTable.NEXT_ACTIVITY_ID).append("=? "); - - String sql = sb.toString(); - int i = 0; - ResultSet rs = null; - try ( - Connection connection = sqliteConnectionFactory.createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) { - - stmt.setString(++i, id); - rs = stmt.executeQuery(); - - while (rs.next()) { - result.add(extractActivityFromResultSet(rs)); - } - } catch (SQLException | ClassNotFoundException e) { - System.out.println(e.getMessage()); - throw new RuntimeException(e); - } finally { - try { - if (rs != null) { - rs.close(); - } - } catch (SQLException ex) { - System.out.println(ex.getMessage()); - throw new RuntimeException(ex); - } - } - if(result.isEmpty()) { + public Activity getFromClipboard() { + if(this.activityInClipboard == null) { return null; } - if(result.size() == 1) { - result.get(0); + Activity a = new Activity( + null, + 2000, 1,1, + activityInClipboard.getName(), + activityInClipboard.getComment(), + activityInClipboard.getTicket(), + 0,0, "", 1); + return activityInClipboard; + } + + @Override + public int getLargestSortkey(int year, int month, int day) { + OptionalInt optional = + list(year, month, day).stream().map(Activity::getSortkey) + .mapToInt(e -> e).max(); + if (optional.isPresent()) { + System.out.println("getLargestSortkey=" +optional.getAsInt()); + return optional.getAsInt(); + } else { + return 1; } - throw new TimeCalcException("Fatal error: More than one activity, which is previous for this activity id:" + id); } } diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/persistence/impl/sqlite/ActivityTable.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/persistence/impl/sqlite/ActivityTable.java index 736ea71..cffeb61 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/persistence/impl/sqlite/ActivityTable.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/persistence/impl/sqlite/ActivityTable.java @@ -37,7 +37,7 @@ class ActivityTable { public static final String SPENT_HOURS = "SPENT_HOURS"; public static final String SPENT_MINUTES = "SPENT_MINUTES"; public static final String FLAGS = "FLAGS"; - public static final String NEXT_ACTIVITY_ID = "NEXT_ACTIVITY_ID"; + public static final String SORTKEY = "SORTKEY"; private ActivityTable() { //Not meant to be instantiated. diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/ActivitiesWindow.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/ActivitiesWindow.java index 65a94b1..9c3bc91 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/ActivitiesWindow.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/ActivitiesWindow.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Map; import javax.swing.JButton; import javax.swing.JOptionPane; +import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -41,7 +42,6 @@ public class ActivitiesWindow extends TWindow { List yearsList = activityRepository.getYears(); TTabbedPane tp = new TTabbedPane(); - JButton addYearButton = new JButton("Add year"); addYearButton.setBounds(SwingUtils.MARGIN, SwingUtils.MARGIN, 150, 30); add(addYearButton); diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/ActivityHeader.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/ActivityHeader.java index 71f570d..7a435e6 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/ActivityHeader.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/ActivityHeader.java @@ -1,17 +1,11 @@ package org.nanoboot.utils.timecalc.swing.common; -import org.nanoboot.utils.timecalc.entity.Activity; -import org.nanoboot.utils.timecalc.persistence.api.ActivityRepositoryApi; - import javax.swing.BorderFactory; -import javax.swing.JOptionPane; import javax.swing.JPanel; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; /** * @author Robert @@ -19,6 +13,14 @@ import java.awt.event.MouseListener; */ public class ActivityHeader extends JPanel { private static final Font FONT = new Font("sans", Font.BOLD, 12); + + public static final Dimension PREFERRED_SIZE = new Dimension(200, 40); + public static final Dimension PREFERRED_SIZE1 = new Dimension(80, 40); + public static final Dimension PREFERRED_SIZE3 = new Dimension(60, 40); + public static final Dimension PREFERRED_SIZE4 = new Dimension(40, 40); + public static final Dimension PREFERRED_SIZE2 = new Dimension(100, 40); + + private TTextField sortkey = new TTextField("Sortkey"); private TTextField name = new TTextField("Name"); private TTextField comment = new TTextField("Comment"); private TTextField ticket = new TTextField("Ticket"); @@ -27,12 +29,13 @@ public class ActivityHeader extends JPanel { private TTextField flags = new TTextField("Flags"); private TTextField subject = new TTextField("Subject"); private TTextField totalComment = new TTextField("Total comment"); - private TTextField today = new TTextField("Today"); - private TTextField remains = new TTextField("Remains"); + private TTextField done = new TTextField("Done"); + private TTextField todo = new TTextField("Todo"); public ActivityHeader() { this.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + add(sortkey); add(name); add(comment); add(ticket); @@ -41,20 +44,22 @@ public class ActivityHeader extends JPanel { add(flags); add(subject); add(totalComment); - add(today); - add(remains); + add(done); + add(todo); - name.setPreferredSize(new Dimension(200, 40)); - comment.setPreferredSize(new Dimension(200, 40)); - ticket.setPreferredSize(new Dimension(80, 40)); - spentTime.setPreferredSize(new Dimension(80, 40)); + sortkey.setPreferredSize(PREFERRED_SIZE1); + name.setPreferredSize(PREFERRED_SIZE); + comment.setPreferredSize(PREFERRED_SIZE); + ticket.setPreferredSize(PREFERRED_SIZE1); + spentTime.setPreferredSize(PREFERRED_SIZE1); - flags.setPreferredSize(new Dimension(100, 40)); - subject.setPreferredSize(new Dimension(100, 40)); - totalComment.setPreferredSize(new Dimension(100, 40)); - today.setPreferredSize(new Dimension(80, 40)); - remains.setPreferredSize(new Dimension(80, 40)); + flags.setPreferredSize(PREFERRED_SIZE2); + subject.setPreferredSize(PREFERRED_SIZE2); + totalComment.setPreferredSize(PREFERRED_SIZE2); + done.setPreferredSize(PREFERRED_SIZE3); + todo.setPreferredSize(PREFERRED_SIZE3); + sortkey.setEditable(false); name.setEditable(false); comment.setEditable(false); ticket.setEditable(false); @@ -63,9 +68,10 @@ public class ActivityHeader extends JPanel { flags.setEditable(false); subject.setEditable(false); totalComment.setEditable(false); - today.setEditable(false); - remains.setEditable(false); + done.setEditable(false); + todo.setEditable(false); + sortkey.setFont(FONT); name.setFont(FONT); comment.setFont(FONT); ticket.setFont(FONT); @@ -74,9 +80,10 @@ public class ActivityHeader extends JPanel { flags.setFont(FONT); subject.setFont(FONT); totalComment.setFont(FONT); - today.setFont(FONT); - remains.setFont(FONT); + done.setFont(FONT); + todo.setFont(FONT); + sortkey.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); name.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); comment.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); ticket.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); @@ -85,8 +92,8 @@ public class ActivityHeader extends JPanel { flags.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); subject.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); totalComment.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); - today.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); - remains.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); + done.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); + todo.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); //this.setBorder(BorderFactory.createLineBorder(Color.ORANGE, 1)); setAlignmentX(LEFT_ALIGNMENT); diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/ActivityPanel.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/ActivityPanel.java index 0671e9d..0a182a3 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/ActivityPanel.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/ActivityPanel.java @@ -1,25 +1,37 @@ package org.nanoboot.utils.timecalc.swing.common; +import lombok.Getter; import org.nanoboot.utils.timecalc.entity.Activity; import org.nanoboot.utils.timecalc.persistence.api.ActivityRepositoryApi; +import org.nanoboot.utils.timecalc.utils.common.TTime; import javax.swing.BorderFactory; +import javax.swing.JButton; import javax.swing.JOptionPane; import javax.swing.JPanel; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; /** * @author Robert * @since 13.03.2024 */ -public class ActivityPanel extends JPanel { +public class ActivityPanel extends JPanel implements Comparable { + public static final Dimension PREFERRED_SIZE = new Dimension(200, 40); + public static final Dimension PREFERRED_SIZE1 = new Dimension(80, 40); + public static final Dimension PREFERRED_SIZE3 = new Dimension(60, 40); + public static final Dimension PREFERRED_SIZE4 = new Dimension(40, 40); + public static final Dimension PREFERRED_SIZE2 = new Dimension(100, 40); private final ActivityRepositoryApi activityRepository; + @Getter private final Activity activity; + + private TTextField sortkey = new TTextField("1"); private TTextField name = new TTextField(""); private TTextField comment = new TTextField(""); private TTextField ticket = new TTextField(""); @@ -28,14 +40,17 @@ public class ActivityPanel extends JPanel { private TTextField flags = new TTextField("Flags"); private TTextField subject = new TTextField(""); private TTextField totalComment = new TTextField(""); - private TTextField today = new TTextField("00:00"); - private TTextField remains = new TTextField("00:00"); + public TTextField today = new TTextField("00:00"); + public TTextField remains = new TTextField("00:00"); + @Getter + private boolean deleted; public ActivityPanel(ActivityRepositoryApi activityRepository, - Activity activity) { + Activity activity, DayPanel dayPanel) { this.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); this.activity = activity; + add(sortkey); add(name); add(comment); add(ticket); @@ -47,19 +62,46 @@ public class ActivityPanel extends JPanel { add(today); add(remains); - name.setPreferredSize(new Dimension(200, 40)); - comment.setPreferredSize(new Dimension(200, 40)); - ticket.setPreferredSize(new Dimension(80, 40)); - spentTime.setPreferredSize(new Dimension(80, 40)); +// JButton moveThisButton = new SmallTButton("Move "); +// JButton moveBeforeButton = new SmallTButton("Here"); + JButton copyButton = new SmallTButton("Copy"); + JButton deleteButton = new SmallTButton("Delete"); + JButton subjectButton = new SmallTButton("Sub"); + JButton totalCommentButton = new SmallTButton("TotCom"); +// add(moveThisButton); +// add(moveBeforeButton); + add(copyButton); + add(deleteButton); + add(subjectButton); + add(totalCommentButton); +// moveThisButton.setFont(SwingUtils.SMALL_FONT); +// moveBeforeButton.setFont(SwingUtils.SMALL_FONT); + copyButton.setFont(SwingUtils.SMALL_FONT); + deleteButton.setFont(SwingUtils.SMALL_FONT); + subjectButton.setFont(SwingUtils.SMALL_FONT); + totalCommentButton.setFont(SwingUtils.SMALL_FONT); - flags.setPreferredSize(new Dimension(100, 40)); - subject.setPreferredSize(new Dimension(100, 40)); - totalComment.setPreferredSize(new Dimension(100, 40)); - today.setPreferredSize(new Dimension(80, 40)); - remains.setPreferredSize(new Dimension(80, 40)); + sortkey.setPreferredSize(PREFERRED_SIZE1); + name.setPreferredSize(PREFERRED_SIZE); + comment.setPreferredSize(PREFERRED_SIZE); + ticket.setPreferredSize(PREFERRED_SIZE1); + spentTime.setPreferredSize(PREFERRED_SIZE1); + flags.setPreferredSize(PREFERRED_SIZE2); + subject.setPreferredSize(PREFERRED_SIZE2); + totalComment.setPreferredSize(PREFERRED_SIZE2); + today.setPreferredSize(PREFERRED_SIZE3); + remains.setPreferredSize(PREFERRED_SIZE3); + +// moveThisButton.setPreferredSize(PREFERRED_SIZE4); +// moveBeforeButton.setPreferredSize(PREFERRED_SIZE4); + copyButton.setPreferredSize(PREFERRED_SIZE4); + deleteButton.setPreferredSize(PREFERRED_SIZE4); + subjectButton.setPreferredSize(PREFERRED_SIZE4); + totalCommentButton.setPreferredSize(PREFERRED_SIZE3); this.setPreferredSize(new Dimension(getWidth(), 40)); + sortkey.setEditable(false); name.setEditable(false); comment.setEditable(false); ticket.setEditable(false); @@ -71,6 +113,7 @@ public class ActivityPanel extends JPanel { today.setEditable(false); remains.setEditable(false); + sortkey.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); name.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); comment.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); ticket.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); @@ -82,55 +125,153 @@ public class ActivityPanel extends JPanel { today.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); remains.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); - name.addMouseListener(new MouseListener() { - @Override - public void mouseClicked(MouseEvent e) { - String result = (String) JOptionPane.showInputDialog( - null, - "Select new name", - "New name", - JOptionPane.PLAIN_MESSAGE, - null, - null, - name.getText() - ); - if (result != null) { - activity.setName(result); - activityRepository.update(activity); - name.setText(result); - } + sortkey.addMouseListener((MouseClickedListener) e -> { + String result = (String) JOptionPane.showInputDialog( + null, + "Select new sortkey", + "New sortkey", + JOptionPane.PLAIN_MESSAGE, + null, + null, + sortkey.getText() + ); + if (result != null) { + activity.setSortkey(Integer.valueOf(result)); + activityRepository.update(activity); + sortkey.setText(result); + dayPanel.sortActivityPanels(); } + }); - @Override - public void mousePressed(MouseEvent e) { - + name.addMouseListener((MouseClickedListener) e -> { + String result = (String) JOptionPane.showInputDialog( + null, + "Select new name", + "New name", + JOptionPane.PLAIN_MESSAGE, + null, + null, + name.getText() + ); + if (result != null) { + activity.setName(result); + activityRepository.update(activity); + name.setText(result); + subject.setText(activity.createSubject()); } - - @Override - public void mouseReleased(MouseEvent e) { - + }); + comment.addMouseListener((MouseClickedListener) e -> { + String result = (String) JOptionPane.showInputDialog( + null, + "Select new comment", + "New comment", + JOptionPane.PLAIN_MESSAGE, + null, + null, + comment.getText() + ); + if (result != null) { + activity.setComment(result); + activityRepository.update(activity); + comment.setText(result); + totalComment.setText(activity.createTotalComment()); } - - @Override - public void mouseEntered(MouseEvent e) { - + }); + ticket.addMouseListener((MouseClickedListener) e -> { + String result = (String) JOptionPane.showInputDialog( + null, + "Select new ticket", + "New ticket", + JOptionPane.PLAIN_MESSAGE, + null, + null, + ticket.getText() + ); + if (result != null) { + activity.setTicket(result); + activityRepository.update(activity); + ticket.setText(result); + subject.setText(activity.createSubject()); + totalComment.setText(activity.createTotalComment()); } + }); + spentTime.addMouseListener((MouseClickedListener) e -> { + String result = (String) JOptionPane.showInputDialog( + null, + "Select new spent time", + "New spent time", + JOptionPane.PLAIN_MESSAGE, + null, + null, + spentTime.getText() + ); + if (result != null) { + TTime spentTimeTTime = new TTime(result); + activity.setSpentHours(spentTimeTTime.getHour()); + activity.setSpentMinutes(spentTimeTTime.getMinute()); + activityRepository.update(activity); + spentTime.setText(result); + totalComment.setText(activity.createTotalComment()); + dayPanel.sortActivityPanels(); + } + }); - @Override - public void mouseExited(MouseEvent e) { + flags.addMouseListener((MouseClickedListener) e -> { + String result = (String) JOptionPane.showInputDialog( + null, + "Select new flags", + "New flags", + JOptionPane.PLAIN_MESSAGE, + null, + null, + flags.getText() + ); + if (result != null) { + activity.setFlags(result); + activityRepository.update(activity); + flags.setText(result); } }); name.setText(activity.getName()); comment.setText(activity.getComment()); ticket.setText(activity.getTicket()); - spentTime.setText((activity.getSpentHours() < 10 ? "0" : "") + activity - .getSpentHours() + ":" + (activity.getSpentMinutes() < 10 ? "0" : - "") + activity.getSpentMinutes()); + spentTime.setText(activity.getSpentTimeAsString()); flags.setText(activity.getFlags()); + subject.setText(activity.createSubject()); + totalComment.setText(activity.createTotalComment()); + sortkey.setText(String.valueOf(activity.getSortkey())); this.activityRepository = activityRepository; //this.setBorder(BorderFactory.createLineBorder(Color.ORANGE, 1)); setAlignmentX(LEFT_ALIGNMENT); +// moveThisButton.addActionListener(e-> { +// //dayPanel.switchPositionsForThisActivityAndThePreviousActivity(getActivity()); +// //dayPanel.markActivityAsToBeMoved(getActivity()); +// }); +// +// moveBeforeButton.addActionListener(e-> { +// //dayPanel.moveMarkedActivityBeforeThisActivity(getActivity()); +// }); + deleteButton.addActionListener(e -> { + activityRepository.delete(this.activity.getId()); + deleted = true; + }); + copyButton.addActionListener(e -> { + activityRepository.putToClipboard(this.activity); + }); + subjectButton.addActionListener(e-> { + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + clipboard.setContents(new StringSelection(subject.getText()), null); + }); + totalCommentButton.addActionListener(e-> { + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + clipboard.setContents(new StringSelection(totalComment.getText()), null); + }); + dayPanel.sortActivityPanels(); + } + @Override + public int compareTo(ActivityPanel o) { + return this.getActivity().compareTo(o.getActivity()); } } diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/DayPanel.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/DayPanel.java index 090d3b5..142bb39 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/DayPanel.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/DayPanel.java @@ -2,15 +2,30 @@ package org.nanoboot.utils.timecalc.swing.common; import org.nanoboot.utils.timecalc.entity.Activity; import org.nanoboot.utils.timecalc.persistence.api.ActivityRepositoryApi; +import org.nanoboot.utils.timecalc.utils.common.NumberFormats; +import org.nanoboot.utils.timecalc.utils.common.TTime; +import org.nanoboot.utils.timecalc.utils.common.Utils; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.Timer; +import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.UUID; +import java.util.stream.Collectors; /** * @author robertvokac @@ -24,6 +39,8 @@ public class DayPanel extends JPanel { private final Map map = new HashMap<>(); private final ActivityRepositoryApi activityRepository; private JButton loadButton; + private JScrollPane scrollPane; + private JPanel panelInsideScrollPane; public DayPanel(String yearIn, String monthIn, String dayIn, ActivityRepositoryApi activityRepository) { @@ -33,7 +50,7 @@ public class DayPanel extends JPanel { this.month = monthIn; this.day = dayIn; this.activityRepository = activityRepository; - setSize(1350, 600); + setSize(1450, 600); this.setLayout(null); this.loadButton = new JButton("Load"); @@ -67,12 +84,25 @@ public class DayPanel extends JPanel { buttons.setAlignmentX(LEFT_ALIGNMENT); JButton newButton = new JButton("New"); JButton pasteButton = new JButton("Paste"); + + JButton reviewButton = new JButton("Review");; buttons.add(newButton); buttons.add(pasteButton); + buttons.add(reviewButton); add(buttons); + + this.scrollPane + = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, + JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + add(scrollPane); + this.panelInsideScrollPane = new JPanel(); + panelInsideScrollPane.setLayout(new BoxLayout(panelInsideScrollPane, BoxLayout.Y_AXIS)); + scrollPane.setViewportView(panelInsideScrollPane); ActivityHeader activityHeader = new ActivityHeader(); - add(activityHeader); + panelInsideScrollPane.add(activityHeader); activityHeader.setMaximumSize(new Dimension(1200, 40)); + + buttons.setMaximumSize(new Dimension(1000, 40)); for (Activity a : activityRepository.list( Integer.valueOf(year), @@ -80,26 +110,118 @@ public class DayPanel extends JPanel { Integer.valueOf(day))) { ActivityPanel comp = - new ActivityPanel(activityRepository, a); - comp.setMaximumSize(new Dimension(1200, 40)); - add(comp); + new ActivityPanel(activityRepository, a, this); + comp.setMaximumSize(new Dimension(1300, 40)); + panelInsideScrollPane.add(comp); } + new Timer(100, e -> { + List + list = Arrays.stream(panelInsideScrollPane.getComponents()).filter(c-> c instanceof ActivityPanel).filter(c-> ((ActivityPanel)c).isDeleted()).collect( + Collectors.toList()); + + if(!list.isEmpty()) { + list.forEach(c->panelInsideScrollPane.remove(c)); + } + revalidate(); + }).start(); revalidate(); newButton.addActionListener(e-> { - Activity newActivity = new Activity(UUID.randomUUID().toString(), Integer.valueOf(year), Integer.valueOf(month), Integer.valueOf(day), "", "", "", 0, 0, "", null); + Activity newActivity = new Activity(UUID.randomUUID().toString(), Integer.valueOf(year), Integer.valueOf(month), Integer.valueOf(day), "", "", "", 0, 0, "", 1 + activityRepository.getLargestSortkey(Integer.valueOf(year), Integer.valueOf(month), Integer.valueOf(day))); ActivityPanel comp = - new ActivityPanel(activityRepository, newActivity); + new ActivityPanel(activityRepository, newActivity, this); comp.setMaximumSize(new Dimension(1200, 40)); add(comp); activityRepository.create(newActivity); + + panelInsideScrollPane.add(comp); + revalidate(); }); -// for (int i = 0; i < 10; i++) { -// add(new ActivityPanel(activityRepository, -// new Activity("id", 2000, 7, 7, "name", "comment", "ticket", 2, 30, -// "a b c", null))); -// } + pasteButton.addActionListener(e-> { + Activity afc = activityRepository.getFromClipboard(); + if(afc == null) { + Utils.showNotification("There is no activity in clipboard. Nothing to do."); + return; + } + Activity newActivity = new Activity(UUID.randomUUID().toString(), Integer.valueOf(year), Integer.valueOf(month), Integer.valueOf(day), + afc.getName(), afc.getComment(), afc.getTicket(), 0, 0, "", 1 + activityRepository.getLargestSortkey(Integer.valueOf(year), Integer.valueOf(month), Integer.valueOf(day))); + ActivityPanel comp = + new ActivityPanel(activityRepository, newActivity, this); + comp.setMaximumSize(new Dimension(1200, 40)); + add(comp); + activityRepository.create(newActivity); + + panelInsideScrollPane.add(comp); + + revalidate(); + }); + reviewButton.addActionListener(e->{ + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + clipboard.setContents(new StringSelection(Arrays + .stream(panelInsideScrollPane.getComponents()) + .filter(c-> c instanceof ActivityPanel) + .map(ap->((ActivityPanel) ap).getActivity()) + .map(a->a.createTotalComment()) + .collect( + Collectors.joining("\n"))), null); + }); + // for (int i = 0; i < 10; i++) { + // add(new ActivityPanel(activityRepository, + // new Activity("id", 2000, 7, 7, "name", "comment", "ticket", 2, 30, + // "a b c", null))); + // } + } + public List getActivities() { + return Arrays + .stream(panelInsideScrollPane.getComponents()) + .filter(c-> c instanceof ActivityPanel) + .map(ap->((ActivityPanel) ap).getActivity()).collect(Collectors.toList()); + } + + public int getIndexForActivityPanel(Activity a) { + for(int i = 0;i optional = Arrays + .stream(panelInsideScrollPane.getComponents()) + .filter(c-> c instanceof ActivityPanel) + .filter(c-> ((ActivityPanel) c).getActivity().equals(a)) + .findFirst(); + if(optional.isPresent()) { + return (ActivityPanel) optional.get(); + } else { + return null; + } + } + public void sortActivityPanels() { + List list = new ArrayList<>(); + Arrays + .stream(panelInsideScrollPane.getComponents()) + .filter(c-> c instanceof ActivityPanel).forEach(e-> list.add((ActivityPanel) e)); + Collections.sort(list); + for(ActivityPanel ap:list) { + panelInsideScrollPane.remove(ap); + } + double done = 0d; + double todo = 8d; + for(ActivityPanel ap:list) { + panelInsideScrollPane.add(ap); + double now = ap.getActivity().getSpentHours() + ap.getActivity().getSpentMinutes() / 60d; + done = done + now; + todo = todo - now; + ap.today.setText(TTime.ofMilliseconds((int)(done * 60d * 60d * 1000d)).toString().substring(0,5)); + ap.remains.setText(TTime.ofMilliseconds((int)(todo * 60d * 60d * 1000d)).toString().substring(0,5)); + } + revalidate(); } } diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/MonthPanel.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/MonthPanel.java index 1822e6c..cb4dfb1 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/MonthPanel.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/MonthPanel.java @@ -32,7 +32,7 @@ public class MonthPanel extends JPanel { setLayout(null); this.tp = new TTabbedPane(); add(tp); - tp.setBounds(0, 0, 1350, 650); + tp.setBounds(0, 0, 1450, 650); ChangeListener changeListener = new ChangeListener() { private boolean secondOrLaterChange = false; diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/MouseClickedListener.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/MouseClickedListener.java new file mode 100644 index 0000000..5abdb80 --- /dev/null +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/MouseClickedListener.java @@ -0,0 +1,31 @@ +package org.nanoboot.utils.timecalc.swing.common; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +/** + * @author Robert + * @since 14.03.2024 + */ +public interface MouseClickedListener extends MouseListener { + + @Override + default void mousePressed(MouseEvent e) { + + } + + @Override + default void mouseReleased(MouseEvent e) { + + } + + @Override + default void mouseEntered(MouseEvent e) { + + } + + @Override + default void mouseExited(MouseEvent e) { + + } +} diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/SmallTButton.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/SmallTButton.java index 19d762f..46825e7 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/SmallTButton.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/SmallTButton.java @@ -10,9 +10,13 @@ public class SmallTButton extends TButton { private static final Insets INSETS = new Insets(1, 1, 1, 1); - public SmallTButton(char character) { - super(String.valueOf(character), 15, 15); + public SmallTButton(String s) { + super(s, 15, 15); //setFont(SwingUtils.SMALL_FONT); setMargin(INSETS); } + + public SmallTButton(char character) { + this(String.valueOf(character)); + } } diff --git a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/YearPanel.java b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/YearPanel.java index 58bb60e..0349418 100644 --- a/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/YearPanel.java +++ b/modules/time-calc-app/src/main/java/org/nanoboot/utils/timecalc/swing/common/YearPanel.java @@ -26,7 +26,7 @@ public class YearPanel extends JPanel { setLayout(null); this.tp = new TTabbedPane(); add(tp); - tp.setBounds(0, 0, 1350, 700); + tp.setBounds(0, 0, 1450, 700); ChangeListener changeListener = new ChangeListener() { private boolean secondOrLaterChange = false; diff --git a/modules/time-calc-app/src/main/resources/db_migrations/sqlite/timecalc/V000006__alter_table_activity_drop_column_next_activity_id.sql b/modules/time-calc-app/src/main/resources/db_migrations/sqlite/timecalc/V000006__alter_table_activity_drop_column_next_activity_id.sql new file mode 100644 index 0000000..dbf7cca --- /dev/null +++ b/modules/time-calc-app/src/main/resources/db_migrations/sqlite/timecalc/V000006__alter_table_activity_drop_column_next_activity_id.sql @@ -0,0 +1 @@ +ALTER TABLE "ACTIVITY" DROP COLUMN "NEXT_ACTIVITY_ID"; diff --git a/modules/time-calc-app/src/main/resources/db_migrations/sqlite/timecalc/V000007__alter_table_activity_add_column_sortkey.sql b/modules/time-calc-app/src/main/resources/db_migrations/sqlite/timecalc/V000007__alter_table_activity_add_column_sortkey.sql new file mode 100644 index 0000000..542e620 --- /dev/null +++ b/modules/time-calc-app/src/main/resources/db_migrations/sqlite/timecalc/V000007__alter_table_activity_add_column_sortkey.sql @@ -0,0 +1 @@ +ALTER TABLE "ACTIVITY" ADD COLUMN "SORTKEY" NUMBER DEFAULT 1;