From e7971d4d7acca4179548eabf547c67cb7d94d232 Mon Sep 17 00:00:00 2001 From: Evgeny Zakrevsky Date: Thu, 22 Nov 2012 06:18:42 +0400 Subject: [PATCH] IDEA-74652 Time tracking features. As external plugin. --- build/scripts/layouts.gant | 2 +- .../impl/UpdateSettingsConfigurable.java | 2 + .../src/com/intellij/tasks/TaskManager.java | 12 -- .../tasks/tasks-core/src/META-INF/plugin.xml | 6 - .../tasks/config/TaskConfigurable.form | 62 +----- .../tasks/config/TaskConfigurable.java | 22 +- .../intellij/tasks/impl/TaskManagerImpl.java | 152 ------------- .../tasks/tasks-core/tasks-core-plugin.iml | 13 -- plugins/tasks/tasks-core/tasks-core.iml | 1 - .../src/META-INF/plugin.xml | 24 +++ .../timeTracking}/TasksToolWindowFactory.java | 5 +- .../timeTracking}/TasksToolWindowPanel.java | 90 ++++---- .../TimeTrackingConfigurable.form | 68 ++++++ .../TimeTrackingConfigurable.java | 111 ++++++++++ .../timeTracking/TimeTrackingManager.java | 200 ++++++++++++++++++ .../tasks-time-tracking.iml | 20 ++ 16 files changed, 476 insertions(+), 314 deletions(-) delete mode 100644 plugins/tasks/tasks-core/tasks-core-plugin.iml create mode 100644 plugins/tasks/tasks-time-tracking/src/META-INF/plugin.xml rename plugins/tasks/{tasks-core/src/com/intellij/tasks/timetracking => tasks-time-tracking/src/com/intellij/tasks/timeTracking}/TasksToolWindowFactory.java (87%) rename plugins/tasks/{tasks-core/src/com/intellij/tasks/timetracking => tasks-time-tracking/src/com/intellij/tasks/timeTracking}/TasksToolWindowPanel.java (81%) create mode 100644 plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TimeTrackingConfigurable.form create mode 100644 plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TimeTrackingConfigurable.java create mode 100644 plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TimeTrackingManager.java create mode 100644 plugins/tasks/tasks-time-tracking/tasks-time-tracking.iml diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index 6256972f52d5..abb2947d5efa 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -203,7 +203,7 @@ def layoutFull(String home, String targetDirectory, String patchedDescriptorDir public def layoutCommunityPlugins(String home) { dir("plugins") { - def simplePlugins = ["commander", "copyright", "properties", "java-i18n", "hg4idea", "github", "ui-designer-new"] + def simplePlugins = ["commander", "copyright", "properties", "java-i18n", "hg4idea", "github", "ui-designer-new", "tasks-time-tracking"] simplePlugins.each { layoutPlugin it diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java index ffb449e33c32..d5262cfb6e8c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java @@ -25,6 +25,7 @@ import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.project.Project; import com.intellij.ui.CollectionComboBoxModel; import com.intellij.util.text.DateFormatUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -142,6 +143,7 @@ public class UpdateSettingsConfigurable extends BaseConfigurable implements Sear } } + @NotNull public String getId() { return getHelpTopic(); } diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskManager.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskManager.java index f1ffb5153225..9d2d410f307e 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskManager.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskManager.java @@ -106,16 +106,4 @@ public abstract class TaskManager { public abstract boolean testConnection(TaskRepository repository); public final static TaskRepositoryType[] ourRepositoryTypes = Extensions.getExtensions(TaskRepositoryType.EP_NAME); - - public abstract void updateTimeTrackingToolWindow(); - - public abstract boolean isTimeTrackingToolWindowAvailable(); - - public abstract boolean isTimeTrackingAutoMode(); - - public abstract void setTimeTrackingAutoMode(final boolean state); - - public abstract boolean isHideClosedTasks(); - - public abstract void setHideClosedTasks(final boolean state); } diff --git a/plugins/tasks/tasks-core/src/META-INF/plugin.xml b/plugins/tasks/tasks-core/src/META-INF/plugin.xml index 3236b50ff0d9..185fcab01288 100644 --- a/plugins/tasks/tasks-core/src/META-INF/plugin.xml +++ b/plugins/tasks/tasks-core/src/META-INF/plugin.xml @@ -1,9 +1,7 @@ com.intellij.tasks Task Management - Enables task and context management - 1.0 JetBrains @@ -124,10 +122,6 @@ - - diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.form b/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.form index 55c006b710a2..595bc4f4a2d0 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.form +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.form @@ -92,7 +92,7 @@ - + @@ -169,66 +169,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.java index a60a6dc9d509..c08cdc44b8f7 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.java @@ -25,7 +25,7 @@ import java.awt.event.ActionListener; */ @SuppressWarnings({"UnusedDeclaration"}) public class TaskConfigurable extends BindableConfigurable implements SearchableConfigurable.Parent, - NonDefaultProjectConfigurable { + NonDefaultProjectConfigurable, Configurable.NoScroll { private JPanel myPanel; @@ -50,12 +50,6 @@ public class TaskConfigurable extends BindableConfigurable implements Searchable private JBCheckBox myAlwaysDisplayTaskCombo; private JTextField myConnectionTimeout; - @BindControl("enableTimeTracking") - private JBCheckBox myEnableTimeTrackingCheckBox; - @BindControl("timeTrackingSuspendDelayInSeconds") - private JTextField myTimeTrackingSuspendDelay; - private JPanel myTimeTrackingSettings; - private final Project myProject; private Configurable[] myConfigurables; private final NotNullLazyValue myControlBinder = new NotNullLazyValue() { @@ -74,11 +68,6 @@ public class TaskConfigurable extends BindableConfigurable implements Searchable enableCachePanel(); } }); - myEnableTimeTrackingCheckBox.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - enableTimeTrackingPanel(); - } - }); } private TaskManagerImpl.Config getConfig() { @@ -94,15 +83,10 @@ public class TaskConfigurable extends BindableConfigurable implements Searchable GuiUtils.enableChildren(myCacheSettings, myUpdateCheckBox.isSelected()); } - private void enableTimeTrackingPanel() { - GuiUtils.enableChildren(myTimeTrackingSettings, myEnableTimeTrackingCheckBox.isSelected()); - } - @Override public void reset() { super.reset(); enableCachePanel(); - enableTimeTrackingPanel(); myAlwaysDisplayTaskCombo.setSelected(TaskSettings.getInstance().ALWAYS_DISPLAY_COMBO); myConnectionTimeout.setText(Integer.toString(TaskSettings.getInstance().CONNECTION_TIMEOUT)); } @@ -110,14 +94,10 @@ public class TaskConfigurable extends BindableConfigurable implements Searchable @Override public void apply() throws ConfigurationException { boolean oldUpdateEnabled = getConfig().updateEnabled; - boolean oldTimeTrackingEnabled = getConfig().enableTimeTracking; super.apply(); if (getConfig().updateEnabled && !oldUpdateEnabled) { TaskManager.getManager(myProject).updateIssues(null); } - if (getConfig().enableTimeTracking != oldTimeTrackingEnabled) { - TaskManager.getManager(myProject).updateTimeTrackingToolWindow(); - } TaskSettings.getInstance().ALWAYS_DISPLAY_COMBO = myAlwaysDisplayTaskCombo.isSelected(); TaskSettings.getInstance().CONNECTION_TIMEOUT = Integer.valueOf(myConnectionTimeout.getText()); } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java index c8cfcc1d4f46..f7ff1b11a4fc 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java @@ -15,7 +15,6 @@ */ package com.intellij.tasks.impl; -import com.intellij.ide.IdeEventQueue; import com.intellij.notification.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.*; @@ -33,13 +32,10 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.changes.*; -import com.intellij.openapi.wm.*; import com.intellij.tasks.*; import com.intellij.tasks.config.TaskRepositoriesConfigurable; import com.intellij.tasks.context.WorkingContextManager; -import com.intellij.tasks.timetracking.TasksToolWindowFactory; import com.intellij.ui.ColoredTreeCellRenderer; -import com.intellij.util.Alarm; import com.intellij.util.ArrayUtil; import com.intellij.util.EventDispatcher; import com.intellij.util.Function; @@ -98,7 +94,6 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe } }; static final String TASKS_NOTIFICATION_GROUP = "Task Group"; - public static final int TIME_TRACKING_TIME_UNIT = 1000; private final Project myProject; @@ -136,8 +131,6 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe private final List myRepositories = new ArrayList(); private final EventDispatcher myDispatcher = EventDispatcher.create(TaskListener.class); private Set myBadRepositories = new ConcurrentHashSet(); - private Timer myTimeTrackingTimer; - private Alarm myIdleAlarm; public TaskManagerImpl(Project project, WorkingContextManager contextManager, @@ -580,46 +573,6 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe myCacheRefreshTimer.start(); } }); - - myTimeTrackingTimer = UIUtil.createNamedTimer("TaskManager time tracking", TIME_TRACKING_TIME_UNIT, new ActionListener() { - @Override - public void actionPerformed(final ActionEvent e) { - final LocalTask activeTask = getActiveTask(); - if (isTimeTrackingAutoMode()) { - activeTask.setTimeSpent(activeTask.getTimeSpent() + TIME_TRACKING_TIME_UNIT); - getState().myTotallyTimeSpent += TIME_TRACKING_TIME_UNIT; - } - else { - if (activeTask.isRunning()) { - activeTask.setTimeSpent(activeTask.getTimeSpent() + TIME_TRACKING_TIME_UNIT); - getState().myTotallyTimeSpent += TIME_TRACKING_TIME_UNIT; - } - } - } - }); - StartupManager.getInstance(myProject).registerStartupActivity(new Runnable() { - public void run() { - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - startTimeTrackingTimer(); - } - }); - } - }); - - myIdleAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, myProject); - - IdeEventQueue.getInstance().addActivityListener(new Runnable() { - @Override - public void run() { - final IdeFrame frame = IdeFocusManager.getGlobalInstance().getLastFocusedFrame(); - if (frame == null) return; - final Project project = frame.getProject(); - if (project == null || !myProject.equals(project)) return; - startTimeTrackingTimer(); - } - }, myProject); } LocalTask defaultTask = myTasks.get(LocalTaskImpl.DEFAULT_TASK_ID); @@ -666,101 +619,6 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe myDispatcher.getMulticaster().taskActivated(myActiveTask); myChangeListManager.addChangeListListener(myChangeListListener); - - addTaskListener(new TaskListener() { - @Override - public void taskDeactivated(final LocalTask task) { - updateTimeTrackingToolWindow(); - } - - @Override - public void taskActivated(final LocalTask task) { - updateTimeTrackingToolWindow(); - } - - @Override - public void taskAdded(final LocalTask task) { - updateTimeTrackingToolWindow(); - } - - @Override - public void taskRemoved(final LocalTask task) { - updateTimeTrackingToolWindow(); - } - }); - } - - private void startTimeTrackingTimer() { - if (!myTimeTrackingTimer.isRunning()) { - myTimeTrackingTimer.start(); - } - - myIdleAlarm.cancelAllRequests(); - myIdleAlarm.addRequest(new Runnable() { - @Override - public void run() { - if (myTimeTrackingTimer.isRunning()) { - myTimeTrackingTimer.stop(); - } - } - }, getState().timeTrackingSuspendDelayInSeconds * 1000); - } - - public void updateTimeTrackingToolWindow() { - ToolWindow toolWindow = ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.TASKS); - if (isTimeTrackingToolWindowAvailable()) { - if (toolWindow == null) { - toolWindow = - ToolWindowManager.getInstance(myProject).registerToolWindow(ToolWindowId.TASKS, true, ToolWindowAnchor.RIGHT, myProject, true); - new TasksToolWindowFactory().createToolWindowContent(myProject, toolWindow); - final ToolWindow finalToolWindow = toolWindow; - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - finalToolWindow.setAvailable(true, null); - finalToolWindow.show(null); - finalToolWindow.activate(null); - } - }); - } - } - else { - if (toolWindow != null) { - final ToolWindow finalToolWindow = toolWindow; - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - finalToolWindow.setAvailable(false, null); - } - }); - } - } - } - - public boolean isTimeTrackingToolWindowAvailable() { - final LocalTask activeTask = getActiveTask(); - final boolean isNotUsed = activeTask.isDefault() && Comparing.equal(activeTask.getCreated(), activeTask.getUpdated()); - return !isNotUsed && ApplicationManager.getApplication().isInternal() && getState().enableTimeTracking; - } - - @Override - public boolean isTimeTrackingAutoMode() { - return getState().isTimeTrackingAutoMode; - } - - @Override - public void setTimeTrackingAutoMode(final boolean state) { - getState().isTimeTrackingAutoMode = state; - } - - @Override - public boolean isHideClosedTasks() { - return getState().hideClosedTasks; - } - - @Override - public void setHideClosedTasks(final boolean state) { - getState().hideClosedTasks = state; } private static LocalTaskImpl createDefaultTask() { @@ -771,9 +629,6 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe if (myCacheRefreshTimer != null) { myCacheRefreshTimer.stop(); } - if (myTimeTrackingTimer != null) { - myTimeTrackingTimer.stop(); - } myChangeListManager.removeChangeListListener(myChangeListListener); } @@ -997,15 +852,8 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe public boolean searchClosedTasks = false; - public long myTotallyTimeSpent = 0; - @Tag("servers") public Element servers = new Element("servers"); - - public boolean enableTimeTracking = true; - public int timeTrackingSuspendDelayInSeconds = 600; - public boolean isTimeTrackingAutoMode = true; - public boolean hideClosedTasks = true; } private abstract class TestConnectionTask extends com.intellij.openapi.progress.Task.Modal { diff --git a/plugins/tasks/tasks-core/tasks-core-plugin.iml b/plugins/tasks/tasks-core/tasks-core-plugin.iml deleted file mode 100644 index 4155fc0458fb..000000000000 --- a/plugins/tasks/tasks-core/tasks-core-plugin.iml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/plugins/tasks/tasks-core/tasks-core.iml b/plugins/tasks/tasks-core/tasks-core.iml index 71a3186e8557..e9a954fc69cf 100644 --- a/plugins/tasks/tasks-core/tasks-core.iml +++ b/plugins/tasks/tasks-core/tasks-core.iml @@ -4,7 +4,6 @@ - diff --git a/plugins/tasks/tasks-time-tracking/src/META-INF/plugin.xml b/plugins/tasks/tasks-time-tracking/src/META-INF/plugin.xml new file mode 100644 index 000000000000..7b75e5c1c332 --- /dev/null +++ b/plugins/tasks/tasks-time-tracking/src/META-INF/plugin.xml @@ -0,0 +1,24 @@ + + com.intellij.tasks.timeTracking + Time Tracking + Enables time tracking for "Task Management" plugin + JetBrains + 1.0 + + com.intellij.tasks + + + + com.intellij.tasks.timeTracking.TimeTrackingManager + + + + + + + + + diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/timetracking/TasksToolWindowFactory.java b/plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TasksToolWindowFactory.java similarity index 87% rename from plugins/tasks/tasks-core/src/com/intellij/tasks/timetracking/TasksToolWindowFactory.java rename to plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TasksToolWindowFactory.java index 1d9dd09dc3d0..fd1593fc94b2 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/timetracking/TasksToolWindowFactory.java +++ b/plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TasksToolWindowFactory.java @@ -1,4 +1,4 @@ -package com.intellij.tasks.timetracking; +package com.intellij.tasks.timeTracking; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; @@ -6,7 +6,6 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowAnchor; import com.intellij.openapi.wm.ToolWindowFactory; -import com.intellij.tasks.TaskManager; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentFactory; import com.intellij.ui.content.ContentManager; @@ -19,7 +18,7 @@ public class TasksToolWindowFactory implements ToolWindowFactory, Condition myTableModel; - private final TaskManager myTaskManager; + private final TimeTrackingManager myTimeTrackingManager; private final Project myProject; private Timer myTimer; private final TableView myTable; + private final TaskManager myTaskManager; public TasksToolWindowPanel(final Project project, final boolean vertical) { super(vertical); myProject = project; + myTimeTrackingManager = TimeTrackingManager.getInstance(project); myTaskManager = TaskManager.getManager(project); myTable = new TableView(createListModel()); @@ -81,7 +82,7 @@ public class TasksToolWindowPanel extends SimpleToolWindowPanel implements Dispo } }); - myTimer = new Timer(TaskManagerImpl.TIME_TRACKING_TIME_UNIT, new ActionListener() { + myTimer = new Timer(TimeTrackingManager.TIME_TRACKING_TIME_UNIT, new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { myTable.repaint(); @@ -123,69 +124,70 @@ public class TasksToolWindowPanel extends SimpleToolWindowPanel implements Dispo group.add(new ToggleAction("Hide closed tasks", "Hide closed tasks", AllIcons.Actions.Checked) { @Override public boolean isSelected(final AnActionEvent e) { - return myTaskManager.isHideClosedTasks(); + return myTimeTrackingManager.isHideClosedTasks(); } @Override public void setSelected(final AnActionEvent e, final boolean state) { - myTaskManager.setHideClosedTasks(state); + myTimeTrackingManager.setHideClosedTasks(state); } }); group.add(new ToggleAction("Auto mode", "Automatic starting and stopping of timer", TasksIcons.AutoMode) { @Override public boolean isSelected(final AnActionEvent e) { - return myTaskManager.isTimeTrackingAutoMode(); + return myTimeTrackingManager.isTimeTrackingAutoMode(); } @Override public void setSelected(final AnActionEvent e, final boolean state) { - myTaskManager.setTimeTrackingAutoMode(state); + myTimeTrackingManager.setTimeTrackingAutoMode(state); updateTable(); } }); group.add(new AnAction() { @Override - public void update(final AnActionEvent e) { - if (myTaskManager.isTimeTrackingAutoMode()) { - e.getPresentation().setEnabled(false); - e.getPresentation().setIcon(TasksIcons.StartTimer); - e.getPresentation().setText("Start timer for active task"); - } - else { - e.getPresentation().setEnabled(true); - if (myTaskManager.getActiveTask().isRunning()) { - e.getPresentation().setIcon(TasksIcons.StopTimer); - e.getPresentation().setText("Stop timer for active task"); - } - else { - e.getPresentation().setIcon(TasksIcons.StartTimer); - e.getPresentation().setText("Start timer for active task"); - } - } + public void update(final AnActionEvent e) { + if (myTimeTrackingManager.isTimeTrackingAutoMode()) { + e.getPresentation().setEnabled(false); + e.getPresentation().setIcon(TasksIcons.StartTimer); + e.getPresentation().setText("Start timer for active task"); + } + else { + e.getPresentation().setEnabled(true); + if (myTaskManager.getActiveTask().isRunning()) { + e.getPresentation().setIcon(TasksIcons.StopTimer); + e.getPresentation().setText("Stop timer for active task"); } + else { + e.getPresentation().setIcon(TasksIcons.StartTimer); + e.getPresentation().setText("Start timer for active task"); + } + } + } - @Override - public void actionPerformed(final AnActionEvent e) { - final LocalTask activeTask = myTaskManager.getActiveTask(); - if (activeTask.isRunning()) { - activeTask.setRunning(false); - } - else { - activeTask.setRunning(true); - } - } - }); + @Override + public void actionPerformed(final AnActionEvent e) { + final LocalTask activeTask = myTaskManager.getActiveTask(); + if (activeTask.isRunning()) { + activeTask.setRunning(false); + } + else { + activeTask.setRunning(true); + } + } + }); final ActionToolbar actionToolBar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, myVertical); return actionToolBar.getComponent(); } private void updateTable() { - myTableModel.setItems(ContainerUtil.filter(myTaskManager.getLocalTasks(myTaskManager.isHideClosedTasks()), new Condition() { - @Override - public boolean value(final LocalTask task) { - return task.isActive() || task.getTimeSpent() != 0; - } - })); + myTableModel + .setItems(ContainerUtil.filter(myTaskManager.getLocalTasks(myTimeTrackingManager.isHideClosedTasks()), new Condition() { + @Override + public boolean value(final LocalTask task) { + return task.isActive() || task.getTimeSpent() != 0; + } + })); } private ListTableModel createListModel() { @@ -213,7 +215,7 @@ public class TasksToolWindowPanel extends SimpleToolWindowPanel implements Dispo final SimpleColoredComponent component = new SimpleColoredComponent(); final boolean isClosed = task.isClosed() || myTaskManager.isLocallyClosed(task); final boolean isActive = task.isActive(); - final boolean isRunning = myTaskManager.isTimeTrackingAutoMode() ? isActive : isActive && task.isRunning(); + final boolean isRunning = myTimeTrackingManager.isTimeTrackingAutoMode() ? isActive : isActive && task.isRunning(); component.append((String)value, getAttributes(isClosed, isActive, isSelected)); component.setIcon(isRunning ? LayeredIcon.create(task.getIcon(), AllIcons.General.Run) @@ -243,7 +245,7 @@ public class TasksToolWindowPanel extends SimpleToolWindowPanel implements Dispo @Override public String valueOf(final LocalTask task) { long timeSpent = task.getTimeSpent(); - if (myTaskManager.isTimeTrackingAutoMode() ? task.isActive() : task.isRunning()) { + if (myTimeTrackingManager.isTimeTrackingAutoMode() ? task.isActive() : task.isRunning()) { return formatDuration(timeSpent); } return DateFormatUtil.formatDuration(timeSpent); diff --git a/plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TimeTrackingConfigurable.form b/plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TimeTrackingConfigurable.form new file mode 100644 index 000000000000..26dfc39e8f7c --- /dev/null +++ b/plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TimeTrackingConfigurable.form @@ -0,0 +1,68 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TimeTrackingConfigurable.java b/plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TimeTrackingConfigurable.java new file mode 100644 index 000000000000..733a40b0c0b3 --- /dev/null +++ b/plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TimeTrackingConfigurable.java @@ -0,0 +1,111 @@ +package com.intellij.tasks.timeTracking; + +import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.options.NonDefaultProjectConfigurable; +import com.intellij.openapi.options.SearchableConfigurable; +import com.intellij.openapi.options.binding.BindControl; +import com.intellij.openapi.options.binding.BindableConfigurable; +import com.intellij.openapi.options.binding.ControlBinder; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.NotNullLazyValue; +import com.intellij.ui.GuiUtils; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * User: Evgeny.Zakrevsky + * Date: 11/19/12 + */ +public class TimeTrackingConfigurable extends BindableConfigurable implements SearchableConfigurable, + NonDefaultProjectConfigurable, Configurable.NoScroll { + @BindControl("enabled") + private JCheckBox myEnableTimeTrackingCheckBox; + @BindControl("suspendDelayInSeconds") + private JTextField myTimeTrackingSuspendDelay; + private JPanel myTimeTrackingSettings; + private JPanel myPanel; + private Project myProject; + private final NotNullLazyValue myControlBinder = new NotNullLazyValue() { + @NotNull + @Override + protected ControlBinder compute() { + return new ControlBinder(getConfig()); + } + }; + + + public TimeTrackingConfigurable(Project project) { + myProject = project; + myEnableTimeTrackingCheckBox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + enableTimeTrackingPanel(); + } + }); + } + + private void enableTimeTrackingPanel() { + GuiUtils.enableChildren(myTimeTrackingSettings, myEnableTimeTrackingCheckBox.isSelected()); + } + + private TimeTrackingManager.Config getConfig() { + return TimeTrackingManager.getInstance(myProject).getState(); + } + + @Override + protected ControlBinder getBinder() { + return myControlBinder.getValue(); + } + + @Override + public void reset() { + super.reset(); + enableTimeTrackingPanel(); + } + + @Override + public void apply() throws ConfigurationException { + boolean oldTimeTrackingEnabled = getConfig().enabled; + super.apply(); + if (getConfig().enabled != oldTimeTrackingEnabled) { + TimeTrackingManager.getInstance(myProject).updateTimeTrackingToolWindow(); + } + } + + @NotNull + @Override + public String getId() { + return "tasks.timeTracking"; + } + + @Nullable + @Override + public Runnable enableSearch(final String option) { + return null; + } + + @Nls + @Override + public String getDisplayName() { + return "Time Tracking"; + } + + @Nullable + @Override + public String getHelpTopic() { + return null; + //return "reference.settings.project.tasks.timeTracking"; + } + + @Nullable + @Override + public JComponent createComponent() { + bindAnnotations(); + return myPanel; + } +} diff --git a/plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TimeTrackingManager.java b/plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TimeTrackingManager.java new file mode 100644 index 000000000000..1cc6f79fead5 --- /dev/null +++ b/plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TimeTrackingManager.java @@ -0,0 +1,200 @@ +package com.intellij.tasks.timeTracking; + +import com.intellij.ide.IdeEventQueue; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.*; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.startup.StartupManager; +import com.intellij.openapi.wm.*; +import com.intellij.tasks.LocalTask; +import com.intellij.tasks.TaskManager; +import com.intellij.util.Alarm; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * User: Evgeny.Zakrevsky + * Date: 11/19/12 + */ + +@State( + name = "TimeTrackingManager", + storages = { + @Storage(file = StoragePathMacros.WORKSPACE_FILE) + } +) +public class TimeTrackingManager implements ProjectComponent, PersistentStateComponent { + + public static final int TIME_TRACKING_TIME_UNIT = 1000; + + private final Project myProject; + private final TaskManager myTaskManager; + private final Config myConfig = new Config(); + private Timer myTimeTrackingTimer; + private Alarm myIdleAlarm; + + public TimeTrackingManager(Project project, + TaskManager taskManager) { + myProject = project; + myTaskManager = taskManager; + } + + public static TimeTrackingManager getInstance(Project project) { + return project.getComponent(TimeTrackingManager.class); + } + + private void startTimeTrackingTimer() { + if (!myTimeTrackingTimer.isRunning()) { + myTimeTrackingTimer.start(); + } + + myIdleAlarm.cancelAllRequests(); + myIdleAlarm.addRequest(new Runnable() { + @Override + public void run() { + if (myTimeTrackingTimer.isRunning()) { + myTimeTrackingTimer.stop(); + } + } + }, getState().suspendDelayInSeconds * 1000); + } + + public void updateTimeTrackingToolWindow() { + ToolWindow toolWindow = ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.TASKS); + if (isTimeTrackingToolWindowAvailable()) { + if (toolWindow == null) { + toolWindow = + ToolWindowManager.getInstance(myProject).registerToolWindow(ToolWindowId.TASKS, true, ToolWindowAnchor.RIGHT, myProject, true); + new TasksToolWindowFactory().createToolWindowContent(myProject, toolWindow); + final ToolWindow finalToolWindow = toolWindow; + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + finalToolWindow.setAvailable(true, null); + finalToolWindow.show(null); + finalToolWindow.activate(null); + } + }); + } + } + else { + if (toolWindow != null) { + final ToolWindow finalToolWindow = toolWindow; + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + finalToolWindow.setAvailable(false, null); + } + }); + } + } + } + + public boolean isTimeTrackingToolWindowAvailable() { + return getState().enabled; + } + + public boolean isTimeTrackingAutoMode() { + return getState().autoMode; + } + + public void setTimeTrackingAutoMode(final boolean state) { + getState().autoMode = state; + } + + public boolean isHideClosedTasks() { + return getState().hideClosedTasks; + } + + public void setHideClosedTasks(final boolean state) { + getState().hideClosedTasks = state; + } + + @Override + public void initComponent() { + if (!ApplicationManager.getApplication().isUnitTestMode()) { + myTimeTrackingTimer = UIUtil.createNamedTimer("TaskManager time tracking", TIME_TRACKING_TIME_UNIT, new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + final LocalTask activeTask = myTaskManager.getActiveTask(); + if (isTimeTrackingAutoMode()) { + activeTask.setTimeSpent(activeTask.getTimeSpent() + TIME_TRACKING_TIME_UNIT); + getState().totallyTimeSpent += TIME_TRACKING_TIME_UNIT; + } + else { + if (activeTask.isRunning()) { + activeTask.setTimeSpent(activeTask.getTimeSpent() + TIME_TRACKING_TIME_UNIT); + getState().totallyTimeSpent += TIME_TRACKING_TIME_UNIT; + } + } + } + }); + StartupManager.getInstance(myProject).registerStartupActivity(new Runnable() { + public void run() { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + startTimeTrackingTimer(); + } + }); + } + }); + + myIdleAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, myProject); + + IdeEventQueue.getInstance().addActivityListener(new Runnable() { + @Override + public void run() { + final IdeFrame frame = IdeFocusManager.getGlobalInstance().getLastFocusedFrame(); + if (frame == null) return; + final Project project = frame.getProject(); + if (project == null || !myProject.equals(project)) return; + startTimeTrackingTimer(); + } + }, myProject); + } + } + + @Override + public void disposeComponent() { + if (myTimeTrackingTimer != null) { + myTimeTrackingTimer.stop(); + } + } + + @NotNull + @Override + public String getComponentName() { + return "Time Tracking Manager"; + } + + @NotNull + @Override + public TimeTrackingManager.Config getState() { + return myConfig; + } + + @Override + public void loadState(final TimeTrackingManager.Config state) { + } + + @Override + public void projectOpened() { + } + + @Override + public void projectClosed() { + } + + public static class Config { + public boolean enabled = true; + public long totallyTimeSpent = 0; + public int suspendDelayInSeconds = 600; + public boolean autoMode = true; + public boolean hideClosedTasks = true; + } +} diff --git a/plugins/tasks/tasks-time-tracking/tasks-time-tracking.iml b/plugins/tasks/tasks-time-tracking/tasks-time-tracking.iml new file mode 100644 index 000000000000..24c5efd433f3 --- /dev/null +++ b/plugins/tasks/tasks-time-tracking/tasks-time-tracking.iml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + +