blob: 6174054be32f355f9cebf739cbbd13e0e8f7db83 [file] [log] [blame]
package com.intellij.tasks.actions;
import com.intellij.codeInsight.documentation.DocumentationManager;
import com.intellij.ide.actions.GotoActionBase;
import com.intellij.ide.util.gotoByName.*;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Ref;
import com.intellij.tasks.LocalTask;
import com.intellij.tasks.Task;
import com.intellij.tasks.TaskManager;
import com.intellij.tasks.doc.TaskPsiElement;
import com.intellij.tasks.impl.TaskManagerImpl;
import com.intellij.tasks.impl.TaskUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IconUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.event.ActionEvent;
/**
* @author Evgeny Zakrevsky
*/
public class GotoTaskAction extends GotoActionBase implements DumbAware {
public static final CreateNewTaskAction CREATE_NEW_TASK_ACTION = new CreateNewTaskAction();
public static final String ID = "tasks.goto";
private static final Logger LOG = Logger.getInstance(GotoTaskAction.class);
public static final int PAGE_SIZE = 20;
public GotoTaskAction() {
getTemplatePresentation().setText("Open Task...");
getTemplatePresentation().setIcon(IconUtil.getAddIcon());
}
@Override
protected void gotoActionPerformed(final AnActionEvent e) {
final Project project = e.getProject();
if (project == null) return;
perform(project);
}
void perform(final Project project) {
final Ref<Boolean> shiftPressed = Ref.create(false);
final ChooseByNamePopup popup = createPopup(project, new GotoTaskPopupModel(project), new TaskItemProvider(project));
popup.setShowListForEmptyPattern(true);
popup.setSearchInAnyPlace(true);
popup.setFixLostTyping(false);
popup.setAlwaysHasMore(true);
popup.setAdText("<html>Press SHIFT to merge with current context<br/>" +
"Pressing " +
KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction(IdeActions.ACTION_QUICK_JAVADOC)) +
" would show task description and comments</html>");
popup.registerAction("shiftPressed", KeyStroke.getKeyStroke("shift pressed SHIFT"), new AbstractAction() {
public void actionPerformed(ActionEvent e) {
shiftPressed.set(true);
}
});
popup.registerAction("shiftReleased", KeyStroke.getKeyStroke("released SHIFT"), new AbstractAction() {
public void actionPerformed(ActionEvent e) {
shiftPressed.set(false);
}
});
final DefaultActionGroup group = new DefaultActionGroup(new ConfigureServersAction() {
@Override
protected void serversChanged() {
popup.rebuildList(true);
}
});
final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true);
actionToolbar.setLayoutPolicy(ActionToolbar.NOWRAP_LAYOUT_POLICY);
actionToolbar.updateActionsImmediately();
actionToolbar.getComponent().setFocusable(false);
actionToolbar.getComponent().setBorder(null);
popup.setToolArea(actionToolbar.getComponent());
popup.setMaximumListSizeLimit(PAGE_SIZE);
popup.setListSizeIncreasing(PAGE_SIZE);
showNavigationPopup(new GotoActionCallback<Object>() {
@Override
public void elementChosen(ChooseByNamePopup popup, Object element) {
TaskManager taskManager = TaskManager.getManager(project);
if (element instanceof TaskPsiElement) {
Task task = ((TaskPsiElement)element).getTask();
LocalTask localTask = taskManager.findTask(task.getId());
if (localTask != null) {
taskManager.activateTask(localTask, !shiftPressed.get());
}
else {
showOpenTaskDialog(project, task);
}
}
else if (element == CREATE_NEW_TASK_ACTION) {
LocalTask localTask = taskManager.createLocalTask(CREATE_NEW_TASK_ACTION.getTaskName());
showOpenTaskDialog(project, localTask);
}
}
}, null, popup);
}
private static void showOpenTaskDialog(final Project project, final Task task) {
JBPopup hint = DocumentationManager.getInstance(project).getDocInfoHint();
if (hint != null) hint.cancel();
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
new OpenTaskDialog(project, task).show();
}
});
}
private static class GotoTaskPopupModel extends SimpleChooseByNameModel {
private ListCellRenderer myListCellRenderer;
protected GotoTaskPopupModel(@NotNull Project project) {
super(project, "Enter task name:", null);
myListCellRenderer = new TaskCellRenderer(project);
}
@Override
public String[] getNames() {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
@Override
protected Object[] getElementsByName(String name, String pattern) {
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
@Override
public ListCellRenderer getListCellRenderer() {
return myListCellRenderer;
}
@Override
public String getElementName(Object element) {
if (element instanceof TaskPsiElement) {
return TaskUtil.getTrimmedSummary(((TaskPsiElement)element).getTask());
}
else if (element == CREATE_NEW_TASK_ACTION) {
return CREATE_NEW_TASK_ACTION.getActionText();
}
return null;
}
@Override
public String getCheckBoxName() {
return "Include closed tasks";
}
@Override
public void saveInitialCheckBoxState(final boolean state) {
((TaskManagerImpl)TaskManager.getManager(getProject())).getState().searchClosedTasks = state;
}
@Override
public boolean loadInitialCheckBoxState() {
return ((TaskManagerImpl)TaskManager.getManager(getProject())).getState().searchClosedTasks;
}
}
/**
* {@link ChooseByNameBase} and {@link ChooseByNamePopup} are not disposable (why?). So to correctly dispose alarm used in
* {@link TaskItemProvider} and don't touch existing UI classes We have to extend popup and override {@link ChooseByNamePopup#close(boolean)}.
*/
private static class MyChooseByNamePopup extends ChooseByNamePopup {
private MyChooseByNamePopup(@Nullable Project project,
@NotNull ChooseByNameModel model,
@NotNull ChooseByNameItemProvider provider,
@Nullable ChooseByNamePopup oldPopup,
@Nullable String predefinedText,
boolean mayRequestOpenInCurrentWindow, int initialIndex) {
super(project, model, provider, oldPopup, predefinedText, mayRequestOpenInCurrentWindow, initialIndex);
}
@Override
public void close(boolean isOk) {
super.close(isOk);
Disposer.dispose((TaskItemProvider)myProvider);
}
}
/**
* Mostly copied from {@link ChooseByNamePopup#createPopup(Project, ChooseByNameModel, ChooseByNameItemProvider, String, boolean, int)}.
*/
private static MyChooseByNamePopup createPopup(Project project, ChooseByNameModel model, ChooseByNameItemProvider provider) {
final ChooseByNamePopup oldPopup = project == null ? null : project.getUserData(ChooseByNamePopup.CHOOSE_BY_NAME_POPUP_IN_PROJECT_KEY);
if (oldPopup != null) {
oldPopup.close(false);
}
MyChooseByNamePopup newPopup = new MyChooseByNamePopup(project, model, provider, oldPopup, null, false, 0);
if (project != null) {
project.putUserData(ChooseByNamePopup.CHOOSE_BY_NAME_POPUP_IN_PROJECT_KEY, newPopup);
}
return newPopup;
}
public static class CreateNewTaskAction {
private String taskName;
public String getActionText() {
return "Create New Task \'" + taskName + "\'";
}
public void setTaskName(final String taskName) {
this.taskName = taskName;
}
public String getTaskName() {
return taskName;
}
}
}