IDEA-74652 Time tracking features. As external plugin.

This commit is contained in:
Evgeny Zakrevsky
2012-11-22 14:05:36 +04:00
parent 2ed8698386
commit e7971d4d7a
16 changed files with 476 additions and 314 deletions
+1 -1
View File
@@ -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
@@ -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();
}
@@ -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);
}
@@ -1,9 +1,7 @@
<idea-plugin version="2">
<id>com.intellij.tasks</id>
<name>Task Management</name>
<description>Enables task and context management</description>
<version>1.0</version>
<vendor>JetBrains</vendor>
@@ -124,10 +122,6 @@
<tasks.repositoryType implementation="com.intellij.tasks.generic.assembla.AssemblaRepositoryType"/>
<checkinHandlerFactory implementation="com.intellij.tasks.impl.TaskCheckinHandlerFactory"/>
<toolWindow id="Time Tracking" anchor="right" secondary="false" icon="TasksIcons.Clock"
factoryClass="com.intellij.tasks.timetracking.TasksToolWindowFactory"
conditionClass="com.intellij.tasks.timetracking.TasksToolWindowFactory"/>
</extensions>
</idea-plugin>
@@ -92,7 +92,7 @@
<text value="milliseconds"/>
</properties>
</component>
<grid id="fa297" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="fa297" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="10" left="0" bottom="0" right="0"/>
<constraints>
<grid row="5" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -169,66 +169,6 @@
</component>
</children>
</grid>
<grid id="2da41" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="10" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="57d74" class="com.intellij.ui.components.JBCheckBox" binding="myEnableTimeTrackingCheckBox">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Enable Time Tracking"/>
</properties>
</component>
<grid id="4a3c" binding="myTimeTrackingSettings" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<clientProperties>
<BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
</clientProperties>
<border type="none" title="Time Tracking settings"/>
<children>
<component id="b4e9f" class="com.intellij.ui.components.JBLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Suspend delay:"/>
</properties>
</component>
<hspacer id="f3dab">
<constraints>
<grid row="0" column="3" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
<component id="4d525" class="javax.swing.JTextField" binding="myTimeTrackingSuspendDelay">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="50" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="cb93c" class="com.intellij.ui.components.JBLabel">
<constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="seconds"/>
</properties>
</component>
</children>
</grid>
</children>
</grid>
</children>
</grid>
<hspacer id="87f9">
@@ -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<ControlBinder> myControlBinder = new NotNullLazyValue<ControlBinder>() {
@@ -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());
}
@@ -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<TaskRepository> myRepositories = new ArrayList<TaskRepository>();
private final EventDispatcher<TaskListener> myDispatcher = EventDispatcher.create(TaskListener.class);
private Set<TaskRepository> myBadRepositories = new ConcurrentHashSet<TaskRepository>();
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 {
@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module relativePaths="true" type="PLUGIN_MODULE" version="4">
<component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/src/META-INF/plugin.xml" />
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
-1
View File
@@ -4,7 +4,6 @@
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
@@ -0,0 +1,24 @@
<idea-plugin version="2">
<id>com.intellij.tasks.timeTracking</id>
<name>Time Tracking</name>
<description>Enables time tracking for "Task Management" plugin</description>
<vendor>JetBrains</vendor>
<version>1.0</version>
<depends>com.intellij.tasks</depends>
<project-components>
<component>
<implementation-class>com.intellij.tasks.timeTracking.TimeTrackingManager</implementation-class>
</component>
</project-components>
<extensions defaultExtensionNs="com.intellij">
<projectConfigurable instance="com.intellij.tasks.timeTracking.TimeTrackingConfigurable" displayName="Time Tracking" id="tasks.timeTracking"
parentId="tasks"/>
<toolWindow id="Time Tracking" anchor="right" secondary="false" icon="TasksIcons.Clock"
factoryClass="com.intellij.tasks.timeTracking.TasksToolWindowFactory"
conditionClass="com.intellij.tasks.timeTracking.TasksToolWindowFactory"/>
</extensions>
</idea-plugin>
@@ -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<Proj
@Override
public boolean value(final Project project) {
return TaskManager.getManager(project).isTimeTrackingToolWindowAvailable();
return TimeTrackingManager.getInstance(project).isTimeTrackingToolWindowAvailable();
}
@Override
@@ -1,4 +1,4 @@
package com.intellij.tasks.timetracking;
package com.intellij.tasks.timeTracking;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.Disposable;
@@ -13,7 +13,6 @@ import com.intellij.tasks.TaskListenerAdapter;
import com.intellij.tasks.TaskManager;
import com.intellij.tasks.actions.GotoTaskAction;
import com.intellij.tasks.actions.SwitchTaskAction;
import com.intellij.tasks.impl.TaskManagerImpl;
import com.intellij.ui.LayeredIcon;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.SimpleColoredComponent;
@@ -42,14 +41,16 @@ import java.util.Comparator;
public class TasksToolWindowPanel extends SimpleToolWindowPanel implements Disposable {
private final ListTableModel<LocalTask> myTableModel;
private final TaskManager myTaskManager;
private final TimeTrackingManager myTimeTrackingManager;
private final Project myProject;
private Timer myTimer;
private final TableView<LocalTask> 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<LocalTask>(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<LocalTask>() {
@Override
public boolean value(final LocalTask task) {
return task.isActive() || task.getTimeSpent() != 0;
}
}));
myTableModel
.setItems(ContainerUtil.filter(myTaskManager.getLocalTasks(myTimeTrackingManager.isHideClosedTasks()), new Condition<LocalTask>() {
@Override
public boolean value(final LocalTask task) {
return task.isActive() || task.getTimeSpent() != 0;
}
}));
}
private ListTableModel<LocalTask> 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);
@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.tasks.timeTracking.TimeTrackingConfigurable">
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<vspacer id="9d80d">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<grid id="f42" binding="myTimeTrackingSettings" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<clientProperties>
<BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
</clientProperties>
<border type="none" title="Time Tracking settings"/>
<children>
<component id="e1b59" class="com.intellij.ui.components.JBLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Suspend delay:"/>
</properties>
</component>
<component id="463e7" class="javax.swing.JTextField" binding="myTimeTrackingSuspendDelay">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="50" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="5584b" class="com.intellij.ui.components.JBLabel">
<constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="seconds"/>
</properties>
</component>
</children>
</grid>
<component id="c5b5" class="javax.swing.JCheckBox" binding="myEnableTimeTrackingCheckBox" default-binding="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;Enable Time Tracking"/>
</properties>
</component>
<hspacer id="e6e8e">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
</children>
</grid>
</form>
@@ -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<ControlBinder> myControlBinder = new NotNullLazyValue<ControlBinder>() {
@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;
}
}
@@ -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<TimeTrackingManager.Config> {
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;
}
}
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="DevKit.ModuleBuildProperties" />
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="jdk" jdkName="IDEA jdk" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="tasks-api" exported="" />
<orderEntry type="module" module-name="tasks-core" exported="" />
<orderEntry type="module" module-name="util" />
<orderEntry type="module" module-name="core-api" />
<orderEntry type="module" module-name="platform-api" />
<orderEntry type="module" module-name="platform-impl" />
<orderEntry type="module" module-name="lang-impl" />
</component>
</module>