Add test for state updates in YouTrackRepository. Also it correctly releases connecti...
[idea/community.git] / plugins / tasks / tasks-core / src / com / intellij / tasks / actions / OpenTaskDialog.java
1 /*
2  * Copyright 2000-2009 JetBrains s.r.o.
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *  http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  */
16
17 package com.intellij.tasks.actions;
18
19 import com.intellij.ide.util.PropertiesComponent;
20 import com.intellij.openapi.diagnostic.Logger;
21 import com.intellij.openapi.options.binding.BindControl;
22 import com.intellij.openapi.options.binding.ControlBinder;
23 import com.intellij.openapi.progress.ProgressIndicator;
24 import com.intellij.openapi.project.Project;
25 import com.intellij.openapi.ui.ComboBox;
26 import com.intellij.openapi.ui.DialogWrapper;
27 import com.intellij.openapi.ui.Messages;
28 import com.intellij.openapi.ui.ValidationInfo;
29 import com.intellij.openapi.util.Condition;
30 import com.intellij.openapi.vcs.AbstractVcs;
31 import com.intellij.openapi.vcs.VcsTaskHandler;
32 import com.intellij.tasks.*;
33 import com.intellij.tasks.impl.TaskManagerImpl;
34 import com.intellij.tasks.impl.TaskUiUtil.ComboBoxUpdater;
35 import com.intellij.tasks.impl.TaskUtil;
36 import com.intellij.ui.ColoredListCellRenderer;
37 import com.intellij.ui.ListCellRendererWrapper;
38 import com.intellij.ui.components.JBCheckBox;
39 import com.intellij.ui.components.JBLabel;
40 import com.intellij.util.containers.ContainerUtil;
41 import org.jetbrains.annotations.NonNls;
42 import org.jetbrains.annotations.NotNull;
43 import org.jetbrains.annotations.Nullable;
44
45 import javax.swing.*;
46 import java.awt.event.ActionEvent;
47 import java.awt.event.ActionListener;
48 import java.util.Set;
49
50 /**
51  * @author Dmitry Avdeev
52  */
53 public class OpenTaskDialog extends DialogWrapper {
54   private final static Logger LOG = Logger.getInstance("#com.intellij.tasks.actions.SimpleOpenTaskDialog");
55   public static final String START_FROM_BRANCH = "start.from.branch";
56
57   private static final CustomTaskState DO_NOT_UPDATE_STATE = new CustomTaskState("", "-- do not update --");
58
59   private JPanel myPanel;
60   @BindControl(value = "clearContext", instant = true)
61   private JCheckBox myClearContext;
62   private JLabel myTaskNameLabel;
63   private JPanel myVcsPanel;
64   private JTextField myBranchName;
65   private JTextField myChangelistName;
66   private JBCheckBox myCreateBranch;
67   private JBCheckBox myCreateChangelist;
68   private JBLabel myFromLabel;
69   private ComboBox myBranchFrom;
70   private ComboBox myStateComboBox;
71   private JLabel myStateComboBoxLabel;
72
73   private final Project myProject;
74   private final Task myTask;
75   private VcsTaskHandler myVcsTaskHandler;
76
77   public OpenTaskDialog(@NotNull final Project project, @NotNull final Task task) {
78     super(project, false);
79     myProject = project;
80     myTask = task;
81     TaskManagerImpl taskManager = (TaskManagerImpl)TaskManager.getManager(myProject);
82     setTitle("Open Task");
83     myTaskNameLabel.setText(TaskUtil.getTrimmedSummary(task));
84     myTaskNameLabel.setIcon(task.getIcon());
85
86     TaskManagerImpl manager = (TaskManagerImpl)TaskManager.getManager(project);
87     ControlBinder binder = new ControlBinder(manager.getState());
88     binder.bindAnnotations(this);
89     binder.reset();
90
91     myStateComboBox.setRenderer(new ListCellRendererWrapper<CustomTaskState>() {
92       @Override
93       public void customize(JList list, CustomTaskState value, int index, boolean selected, boolean hasFocus) {
94         if (value != null) {
95           setText(value.getPresentableName());
96         }
97         else {
98           setText("-- no states available --");
99         }
100       }
101     });
102
103     // Capture correct modality state
104     final TaskRepository repository = myTask.getRepository();
105     if (myTask.isIssue() && repository != null && repository.isSupported(TaskRepository.STATE_UPDATING)) {
106       // Find out proper way to determine modality state here
107       new ComboBoxUpdater<CustomTaskState>(myProject, "Fetching available task states...", myStateComboBox) {
108         @NotNull
109         @Override
110         protected Set<CustomTaskState> fetch(@NotNull ProgressIndicator indicator) throws Exception {
111           return repository.getAvailableTaskStates(myTask);
112         }
113
114         @Nullable
115         @Override
116         public CustomTaskState getSelectedItem() {
117           return repository.getPreferredOpenTaskState();
118         }
119
120         @Nullable
121         @Override
122         public CustomTaskState getExtraItem() {
123           return DO_NOT_UPDATE_STATE;
124         }
125       }.queue();
126     }
127     else {
128       myStateComboBoxLabel.setVisible(false);
129       myStateComboBox.setVisible(false);
130     }
131
132     TaskManagerImpl.Config state = taskManager.getState();
133     myClearContext.setSelected(state.clearContext);
134
135     AbstractVcs vcs = manager.getActiveVcs();
136     if (vcs == null) {
137       myVcsPanel.setVisible(false);
138     }
139     else {
140       ActionListener listener = new ActionListener() {
141         @Override
142         public void actionPerformed(ActionEvent e) {
143           updateFields(false);
144         }
145       };
146       myCreateChangelist.addActionListener(listener);
147       myCreateBranch.addActionListener(listener);
148       myCreateChangelist.setSelected(manager.getState().createChangelist);
149
150       VcsTaskHandler[] handlers = VcsTaskHandler.getAllHandlers(project);
151       if (handlers.length == 0) {
152         myCreateBranch.setSelected(false);
153         myCreateBranch.setVisible(false);
154         myBranchName.setVisible(false);
155         myFromLabel.setVisible(false);
156         myBranchFrom.setVisible(false);
157       }
158       else {
159         for (VcsTaskHandler handler : handlers) {
160           VcsTaskHandler.TaskInfo[] tasks = handler.getCurrentTasks();
161           if (tasks.length > 0) {
162             myVcsTaskHandler = handler;
163             //noinspection unchecked
164             myBranchFrom.setModel(new DefaultComboBoxModel(tasks));
165             myBranchFrom.setEnabled(true);
166             final String startFrom = PropertiesComponent.getInstance(project).getValue(START_FROM_BRANCH);
167             VcsTaskHandler.TaskInfo info = null;
168             if (startFrom != null) {
169               info = ContainerUtil.find(tasks, new Condition<VcsTaskHandler.TaskInfo>() {
170                 @Override
171                 public boolean value(VcsTaskHandler.TaskInfo taskInfo) {
172                   return startFrom.equals(taskInfo.getName());
173                 }
174               });
175             }
176             if (info == null) {
177               info = handler.getActiveTask();
178             }
179             myBranchFrom.setSelectedItem(info);
180             myBranchFrom.addActionListener(new ActionListener() {
181               @Override
182               public void actionPerformed(ActionEvent e) {
183                 VcsTaskHandler.TaskInfo item = (VcsTaskHandler.TaskInfo)myBranchFrom.getSelectedItem();
184                 if (item != null) {
185                   PropertiesComponent.getInstance(project).setValue(START_FROM_BRANCH, item.getName());
186                 }
187               }
188             });
189             break;
190           }
191         }
192         myCreateBranch.setSelected(manager.getState().createBranch && myBranchFrom.getItemCount() > 0);
193         myBranchFrom.setRenderer(new ColoredListCellRenderer<VcsTaskHandler.TaskInfo>() {
194           @Override
195           protected void customizeCellRenderer(JList list, VcsTaskHandler.TaskInfo value, int index, boolean selected, boolean hasFocus) {
196             if (value != null) {
197               append(value.getName());
198             }
199           }
200         });
201       }
202
203       myBranchName.setText(taskManager.suggestBranchName(task));
204       myChangelistName.setText(taskManager.getChangelistName(task));
205       updateFields(true);
206     }
207     init();
208   }
209
210   private void updateFields(boolean initial) {
211     if (!initial && myBranchFrom.getItemCount() == 0 && myCreateBranch.isSelected()) {
212       Messages.showWarningDialog(myPanel, "Can't create branch if no commit exists.\nCreate a commit first.", "Cannot Create Branch");
213       myCreateBranch.setSelected(false);
214     }
215     myBranchName.setEnabled(myCreateBranch.isSelected());
216     myFromLabel.setEnabled(myCreateBranch.isSelected());
217     myBranchFrom.setEnabled(myCreateBranch.isSelected());
218     myChangelistName.setEnabled(myCreateChangelist.isSelected());
219   }
220
221
222   @Override
223   protected void doOKAction() {
224     createTask();
225     super.doOKAction();
226   }
227
228   public void createTask() {
229     final TaskManagerImpl taskManager = (TaskManagerImpl)TaskManager.getManager(myProject);
230
231     taskManager.getState().createChangelist = myCreateChangelist.isSelected();
232     taskManager.getState().createBranch = myCreateBranch.isSelected();
233
234     final TaskRepository repository = myTask.getRepository();
235     final CustomTaskState taskState = (CustomTaskState)myStateComboBox.getSelectedItem();
236     if (repository != null && taskState != null && taskState != DO_NOT_UPDATE_STATE) {
237       try {
238         repository.setTaskState(myTask, taskState);
239         repository.setPreferredOpenTaskState(taskState);
240       }
241       catch (Exception ex) {
242         Messages.showErrorDialog(myProject, ex.getMessage(), "Cannot Set State For Issue");
243         LOG.warn(ex);
244       }
245     }
246     final LocalTask activeTask = taskManager.getActiveTask();
247     final LocalTask localTask = taskManager.activateTask(myTask, isClearContext());
248     if (myCreateChangelist.isSelected()) {
249       taskManager.createChangeList(localTask, myChangelistName.getText());
250     }
251     if (myCreateBranch.isSelected()) {
252       VcsTaskHandler.TaskInfo item = (VcsTaskHandler.TaskInfo)myBranchFrom.getSelectedItem();
253       Runnable createBranch = new Runnable() {
254         @Override
255         public void run() {
256           taskManager.createBranch(localTask, activeTask, myBranchName.getText());
257         }
258       };
259       if (item != null && !item.equals(myVcsTaskHandler.getActiveTask())) {
260         myVcsTaskHandler.switchToTask(item, createBranch);
261       }
262       else {
263         createBranch.run();
264       }
265     }
266     if (myTask.getType() == TaskType.EXCEPTION && AnalyzeTaskStacktraceAction.hasTexts(myTask)) {
267       AnalyzeTaskStacktraceAction.analyzeStacktrace(myTask, myProject);
268     }
269   }
270
271   @Nullable
272   @Override
273   protected ValidationInfo doValidate() {
274     if (myCreateBranch.isSelected()) {
275       String branchName = myBranchName.getText().trim();
276       if (branchName.isEmpty()) {
277         return new ValidationInfo("Branch name should not be empty", myBranchName);
278       }
279       else if (branchName.contains(" ")) {
280         return new ValidationInfo("Branch name should not contain spaces");
281       }
282       else {
283         return null;
284       }
285     }
286     if (myCreateChangelist.isSelected()) {
287       if (myChangelistName.getText().trim().isEmpty()) {
288         return new ValidationInfo("Changelist name should not be empty");
289       }
290     }
291     return null;
292   }
293
294   private boolean isClearContext() {
295     return myClearContext.isSelected();
296   }
297
298   @NonNls
299   protected String getDimensionServiceKey() {
300     return "SimpleOpenTaskDialog";
301   }
302
303   @Override
304   public JComponent getPreferredFocusedComponent() {
305     if (myCreateBranch.isSelected()) {
306       return myBranchName;
307     }
308     else if (myCreateChangelist.isSelected()) {
309       return myChangelistName;
310     }
311     else {
312       return null;
313     }
314   }
315
316   protected JComponent createCenterPanel() {
317     return myPanel;
318   }
319
320   private void createUIComponents() {
321     myStateComboBox = new ComboBox(300);
322   }
323 }