01/01: fixes #143: On idle dialog, add an option to create a new task to assign idle time to
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository jtimer. See https://gitlab.nuiton.org/chorem/jtimer.git commit 304b94d6d14fd5d8925727a3314c9b3b3ddb8929 Author: Eric Chatellier <chatellier@codelutin.com> Date: Tue Jun 5 16:11:37 2018 +0200 fixes #143: On idle dialog, add an option to create a new task to assign idle time to --- src/main/java/org/chorem/jtimer/JTimer.java | 8 ++- .../java/org/chorem/jtimer/ui/NewTaskView.java | 34 ++++++++--- .../org/chorem/jtimer/ui/tasks/IdleDialog.java | 68 ++++++++++++++++++---- .../org/chorem/jtimer/ui/tree/TaskTreeModel.java | 10 +++- .../jtimer/ui/treetable/ProjectsAndTasksModel.java | 10 +++- .../org/chorem/jtimer/ui/widget/DialogView.java | 8 +-- .../ui/tasks/resources/IdleDialog.properties | 1 + .../ui/tasks/resources/IdleDialog_fr.properties | 2 + 8 files changed, 108 insertions(+), 33 deletions(-) diff --git a/src/main/java/org/chorem/jtimer/JTimer.java b/src/main/java/org/chorem/jtimer/JTimer.java index ab54d3e..c02b8b9 100644 --- a/src/main/java/org/chorem/jtimer/JTimer.java +++ b/src/main/java/org/chorem/jtimer/JTimer.java @@ -23,7 +23,6 @@ package org.chorem.jtimer; import org.apache.commons.io.FileUtils; -import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -634,8 +633,13 @@ public class JTimer extends SingleFrameApplication implements // select task to add new task TimerTask selectedTask = projectsAndTasksTable.getSelectedElements().get(0); - NewTaskView newTaskPanel = new NewTaskView(this, core, selectedTask); + NewTaskView newTaskPanel = new NewTaskView(this.getMainFrame(), this, core, selectedTask); show(newTaskPanel); + + TimerTask newTask = newTaskPanel.getTask(); + if (newTask != null) { + selectTask(newTask); + } } /** diff --git a/src/main/java/org/chorem/jtimer/ui/NewTaskView.java b/src/main/java/org/chorem/jtimer/ui/NewTaskView.java index d8e4e12..e34aa9b 100644 --- a/src/main/java/org/chorem/jtimer/ui/NewTaskView.java +++ b/src/main/java/org/chorem/jtimer/ui/NewTaskView.java @@ -2,7 +2,7 @@ * #%L * jTimer * %% - * Copyright (C) 2016 CodeLutin + * Copyright (C) 2016 - 2018 CodeLutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as @@ -22,6 +22,8 @@ package org.chorem.jtimer.ui; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.chorem.jtimer.JTimer; import org.chorem.jtimer.data.DataViolationException; import org.chorem.jtimer.data.TimerCore; @@ -43,6 +45,7 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.GridLayout; import java.awt.Insets; +import java.awt.Window; import java.util.Date; import java.util.Map; import java.util.Set; @@ -58,16 +61,20 @@ import java.util.Set; */ public class NewTaskView extends DialogView { + /** log */ + private static Log log = LogFactory.getLog(NewTaskView.class); + protected JTimer parent; protected TimerCore core; protected ActionMap actionMap; protected TimerTask selectedTask; + protected TimerTask newTask; protected JTextField newTaskField; protected JComboBox<String> newTaskTemplateBox; - public NewTaskView(JTimer parent, TimerCore core, TimerTask selectedTask) { - super(parent.getMainFrame(), parent); + public NewTaskView(Window owner, JTimer parent, TimerCore core, TimerTask selectedTask) { + super(owner, parent); this.parent = parent; this.core = core; this.selectedTask = selectedTask; @@ -146,26 +153,35 @@ public class NewTaskView extends DialogView { String taskName = newTaskField.getText(); String taskTemplate = (String) newTaskTemplateBox.getSelectedItem(); - getApplication().hide(this); - // remove unneeded spaces taskName = taskName.trim(); - TimerTask t = new TimerTask(taskName); + newTask = new TimerTask(taskName); // Fix creation date - t.setCreationDate(new Date()); + newTask.setCreationDate(new Date()); try { - core.getData().addTask(selectedTask, t, taskTemplate); - parent.selectTask(t); + core.getData().addTask(selectedTask, newTask, taskTemplate); } catch (DataViolationException e) { parent.displayErrorMessage(e.getExceptionKey()); + newTask = null; } + + getApplication().hide(this); } @Action public void cancel() { getApplication().hide(this); } + + /** + * Returning new task after creation. + * + * @return new task + */ + public TimerTask getTask() { + return newTask; + } } diff --git a/src/main/java/org/chorem/jtimer/ui/tasks/IdleDialog.java b/src/main/java/org/chorem/jtimer/ui/tasks/IdleDialog.java index 82624ea..1c3e6f5 100644 --- a/src/main/java/org/chorem/jtimer/ui/tasks/IdleDialog.java +++ b/src/main/java/org/chorem/jtimer/ui/tasks/IdleDialog.java @@ -2,7 +2,7 @@ * #%L * jTimer * %% - * Copyright (C) 2009 - 2016 CodeLutin + * Copyright (C) 2009 - 2018 CodeLutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as @@ -28,6 +28,7 @@ import org.apache.commons.logging.LogFactory; import org.chorem.jtimer.JTimer; import org.chorem.jtimer.data.TimerCore; import org.chorem.jtimer.entities.TimerTask; +import org.chorem.jtimer.ui.NewTaskView; import org.chorem.jtimer.ui.tree.ProjectsAndTasksTree; import org.chorem.jtimer.ui.tree.TaskTreeModel; import org.chorem.jtimer.ui.treetable.ProjectsAndTasksCellRenderer; @@ -35,7 +36,6 @@ import org.jdesktop.application.Action; import org.jdesktop.application.ApplicationContext; import org.jdesktop.application.ResourceManager; import org.jdesktop.application.ResourceMap; -import org.jdesktop.application.SingleFrameApplication; import org.jdesktop.application.Task; import org.jdesktop.application.TaskMonitor; @@ -103,7 +103,7 @@ public class IdleDialog extends JDialog { protected static TimerTask assignSelectedTask; /** Parent application. */ - protected SingleFrameApplication application; + protected JTimer application; /** Timer core. */ protected TimerCore core; @@ -141,6 +141,9 @@ public class IdleDialog extends JDialog { /** Task selected in tree. */ protected boolean selectedTask; + /** Task selected in tree (other than current running task). */ + protected boolean selectedOtherTask; + /** * IdleDialog constructor. * @@ -149,7 +152,7 @@ public class IdleDialog extends JDialog { * @param application parent application * @param core timer core */ - protected IdleDialog(SingleFrameApplication application, TimerCore core) { + protected IdleDialog(JTimer application, TimerCore core) { // don't make reference on other parent // windows, cause idle to unlock some task // if parent window is hidden by systray @@ -271,13 +274,13 @@ public class IdleDialog extends JDialog { JPanel panel = new JPanel(new GridBagLayout()); // separator - panel.add(new JSeparator(), new GridBagConstraints(0, 0, 1, 1, 0, 0, + panel.add(new JSeparator(), new GridBagConstraints(0, 0, 2, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 5), 0, 0)); // label JLabel labelIdle = new JLabel(); labelIdle.setText(resourceMap.getString("assignIdleTimeTo")); - panel.add(labelIdle, new GridBagConstraints(0, 1, 1, 1, 0, 0, + panel.add(labelIdle, new GridBagConstraints(0, 1, 2, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(3, 0, 0, 5), 0, 0)); // Tree @@ -287,6 +290,7 @@ public class IdleDialog extends JDialog { projectsTree.setModel(new TaskTreeModel(core, null)); projectsTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); projectsTree.setCellRenderer(new ProjectsAndTasksCellRenderer()); + projectsTree.setScrollsOnExpand(true); projectsTree.addTreeSelectionListener(e -> { TreePath path = e.getPath(); if (path.getPathCount() > 2) { @@ -295,15 +299,23 @@ public class IdleDialog extends JDialog { assignSelectedTask = null; } // must select a task and a different one from one running - setSelectedTask(assignSelectedTask != null && !assignSelectedTask.equals(currentRunningTask)); + setSelectedTask(assignSelectedTask != null); + // must select a task and a different one from one running + setSelectedOtherTask(assignSelectedTask != null && !assignSelectedTask.equals(currentRunningTask)); }); - panel.add(new JScrollPane(projectsTree), new GridBagConstraints(0, 2, 1, 1, 1, 1, + panel.add(new JScrollPane(projectsTree), new GridBagConstraints(0, 2, 2, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 3, 5), 0, 0)); + // new task + JButton newTaskButton = new JButton(); + newTaskButton.setAction(application.getContext().getActionMap(this).get("newTaskOption")); + panel.add(newTaskButton, new GridBagConstraints(0, 3, 1, 1, 0, 0, + GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 5), 0, 0)); + // ok JButton assignValidButton = new JButton(); assignValidButton.setAction(application.getContext().getActionMap(this).get("validAssignOption")); - panel.add(assignValidButton, new GridBagConstraints(0, 3, 1, 1, 0, 0, + panel.add(assignValidButton, new GridBagConstraints(1, 3, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 5), 0, 0)); return panel; @@ -319,13 +331,23 @@ public class IdleDialog extends JDialog { firePropertyChange("selectedTask", oldValue, selectedTask); } + public boolean isSelectedOtherTask() { + return selectedOtherTask; + } + + public void setSelectedOtherTask(boolean selectedOtherTask) { + boolean oldValue = this.selectedOtherTask; + this.selectedOtherTask = selectedOtherTask; + firePropertyChange("selectedOtherTask", oldValue, selectedOtherTask); + } + /** * Init dialog idleDialog instance. * * @param parent parent reference * @param core core reference */ - public static void init(SingleFrameApplication parent, TimerCore core) { + public static void init(JTimer parent, TimerCore core) { idleDialog = new IdleDialog(parent, core); } @@ -370,9 +392,31 @@ public class IdleDialog extends JDialog { } /** - * Action when validating assign option. + * Action when creating a new sub task. */ @Action(enabledProperty = "selectedTask") + public void newTaskOption() { + // select task to add new task + TreePath selectionPath = projectsTree.getSelectionPath(); + TimerTask selectedTask = (TimerTask) selectionPath.getLastPathComponent(); + + NewTaskView newTaskPanel = new NewTaskView(this, application, core, selectedTask); + application.show(newTaskPanel); + + TimerTask newTask = newTaskPanel.getTask(); + if (newTask != null) { + TaskTreeModel model = (TaskTreeModel)projectsTree.getModel(); + int newIndex = model.getIndexOfChild(selectedTask, newTask); + model.getModelSupport().fireChildAdded(selectionPath, newIndex, newTask); + projectsTree.expandPath(selectionPath); + projectsTree.setSelectedTask(newTask); + } + } + + /** + * Action when validating assign option. + */ + @Action(enabledProperty = "selectedOtherTask") public void validAssignOption() { lastResumeOption = IdleOption.ASSIGN; idleEnded(); @@ -455,7 +499,7 @@ public class IdleDialog extends JDialog { mutex.wait(); } catch (InterruptedException e) { if (log.isErrorEnabled()) { - log.error("Thread inturrupted", e); + log.error("Thread interrupted", e); } } } diff --git a/src/main/java/org/chorem/jtimer/ui/tree/TaskTreeModel.java b/src/main/java/org/chorem/jtimer/ui/tree/TaskTreeModel.java index a74af61..51963f7 100644 --- a/src/main/java/org/chorem/jtimer/ui/tree/TaskTreeModel.java +++ b/src/main/java/org/chorem/jtimer/ui/tree/TaskTreeModel.java @@ -2,7 +2,7 @@ * #%L * jTimer * %% - * Copyright (C) 2009 - 2016 CodeLutin + * Copyright (C) 2009 - 2018 CodeLutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as @@ -73,6 +73,10 @@ public class TaskTreeModel implements TreeModel { modelSupport = new TreeModelSupport(this); } + public TreeModelSupport getModelSupport() { + return modelSupport; + } + @Override public Object getChild(Object parent, int index) { TimerTask child = getChildrenFor(parent).get(index); @@ -133,8 +137,8 @@ public class TaskTreeModel implements TreeModel { @Override public int getIndexOfChild(Object parent, Object child) { - int count = getChildrenFor(parent).indexOf(parent); - return count; + int index = getChildrenFor(parent).indexOf(child); + return index; } @Override diff --git a/src/main/java/org/chorem/jtimer/ui/treetable/ProjectsAndTasksModel.java b/src/main/java/org/chorem/jtimer/ui/treetable/ProjectsAndTasksModel.java index 4ba03a3..cbcb532 100644 --- a/src/main/java/org/chorem/jtimer/ui/treetable/ProjectsAndTasksModel.java +++ b/src/main/java/org/chorem/jtimer/ui/treetable/ProjectsAndTasksModel.java @@ -2,7 +2,7 @@ * #%L * jTimer * %% - * Copyright (C) 2007 - 2016 CodeLutin + * Copyright (C) 2007 - 2018 CodeLutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as @@ -288,8 +288,12 @@ public class ProjectsAndTasksModel extends AbstractTreeTableModel implements subTasksCache.remove(pathLastComponent); // force child recache int newIndex = getIndexOfChild(pathLastComponent, taskUO); modelSupport.fireChildAdded(path, newIndex, taskUO); - // expand path - projectsAndTaskTable.expandPath(path); + + // prevent side effect where tree branch is totally not visible + if (projectsAndTaskTable.isExpanded(path.getParentPath())) { + // expand path + projectsAndTaskTable.expandPath(path); + } break; } case OPERATION_DELETE: { diff --git a/src/main/java/org/chorem/jtimer/ui/widget/DialogView.java b/src/main/java/org/chorem/jtimer/ui/widget/DialogView.java index bdf5810..6773f8e 100644 --- a/src/main/java/org/chorem/jtimer/ui/widget/DialogView.java +++ b/src/main/java/org/chorem/jtimer/ui/widget/DialogView.java @@ -2,7 +2,7 @@ * #%L * jTimer * %% - * Copyright (C) 2016 CodeLutin + * Copyright (C) 2016 - 2018 CodeLutin * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as @@ -27,8 +27,8 @@ import org.jdesktop.application.View; import javax.swing.JDialog; import javax.swing.JRootPane; -import java.awt.Frame; import java.awt.Image; +import java.awt.Window; import static org.jdesktop.application.Application.KEY_APPLICATION_ICON; import static org.jdesktop.application.Application.KEY_APPLICATION_TITLE; @@ -40,10 +40,10 @@ import static org.jdesktop.application.Application.KEY_APPLICATION_TITLE; public class DialogView extends View { public static final String MAIN_DIALOG_NAME = "mainDialog"; - protected Frame owner; + protected Window owner; protected JDialog dialog; - public DialogView(Frame owner, Application application) { + public DialogView(Window owner, Application application) { super(application); this.owner = owner; } diff --git a/src/main/resources/org/chorem/jtimer/ui/tasks/resources/IdleDialog.properties b/src/main/resources/org/chorem/jtimer/ui/tasks/resources/IdleDialog.properties index df59e13..493e86c 100644 --- a/src/main/resources/org/chorem/jtimer/ui/tasks/resources/IdleDialog.properties +++ b/src/main/resources/org/chorem/jtimer/ui/tasks/resources/IdleDialog.properties @@ -44,5 +44,6 @@ chooseAssignOption.Action.text=&Assign\u2026 chooseAssignOption.Action.shortDescription=Assign idle time to another task chooseAssignOption.Action.icon=document-revert-3.png +newTaskOption.Action.text=New task... validAssignOption.Action.text=Assign and resume current task diff --git a/src/main/resources/org/chorem/jtimer/ui/tasks/resources/IdleDialog_fr.properties b/src/main/resources/org/chorem/jtimer/ui/tasks/resources/IdleDialog_fr.properties index 1f22e4c..5b83800 100644 --- a/src/main/resources/org/chorem/jtimer/ui/tasks/resources/IdleDialog_fr.properties +++ b/src/main/resources/org/chorem/jtimer/ui/tasks/resources/IdleDialog_fr.properties @@ -39,4 +39,6 @@ chooseResumeOption.Action.shortDescription=Reprendre la t\u00E2che en ne comptan chooseAssignOption.Action.text=&Assigner\u2026 chooseAssignOption.Action.shortDescription=Assigner le temps d'inactivit\u00E9 \u00E0 une autre t\u00E2che +newTaskOption.Action.text=Nouvelle t\u00E2che... validAssignOption.Action.text=Assigner et reprendre la t\u00E2che en cours + -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
participants (1)
-
chorem.org scm