SVN: new Show Working Copies view, with Configure Branches from there
[idea/community.git] / plugins / svn4idea / src / org / jetbrains / idea / svn / dialogs / CopiesPanel.java
1 /*
2  * Copyright 2000-2010 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 package org.jetbrains.idea.svn.dialogs;
17
18 import com.intellij.openapi.application.ApplicationManager;
19 import com.intellij.openapi.application.ModalityState;
20 import com.intellij.openapi.progress.ProgressManager;
21 import com.intellij.openapi.progress.Task;
22 import com.intellij.openapi.project.Project;
23 import com.intellij.openapi.vfs.LocalFileSystem;
24 import com.intellij.openapi.vfs.VirtualFile;
25 import com.intellij.openapi.wm.IdeFocusManager;
26 import com.intellij.ui.DottedBorder;
27 import com.intellij.ui.components.labels.LinkLabel;
28 import com.intellij.ui.components.labels.LinkListener;
29 import com.intellij.util.messages.MessageBusConnection;
30 import com.intellij.util.ui.UIUtil;
31 import org.jetbrains.idea.svn.NestedCopyType;
32 import org.jetbrains.idea.svn.SvnVcs;
33 import org.jetbrains.idea.svn.WorkingCopyFormat;
34
35 import javax.swing.*;
36 import javax.swing.border.Border;
37 import java.awt.*;
38 import java.awt.event.FocusAdapter;
39 import java.awt.event.FocusEvent;
40 import java.awt.event.KeyAdapter;
41 import java.awt.event.KeyEvent;
42 import java.io.File;
43 import java.util.List;
44
45 public class CopiesPanel {
46   private final Project myProject;
47   private MessageBusConnection myConnection;
48   private SvnVcs myVcs;
49   private JPanel myPanel;
50   private JComponent myHolder;
51   private LinkLabel myRefreshLabel;
52
53   public CopiesPanel(final Project project) {
54     myProject = project;
55     myConnection = myProject.getMessageBus().connect(myProject);
56     myVcs = SvnVcs.getInstance(myProject);
57
58     final Runnable focus = new Runnable() {
59       public void run() {
60         IdeFocusManager.getInstance(myProject).requestFocus(myRefreshLabel, true);
61       }
62     };
63     myConnection.subscribe(SvnVcs.ROOTS_RELOADED, new Runnable() {
64       public void run() {
65         ApplicationManager.getApplication().invokeLater(new Runnable() {
66           public void run() {
67             final List<WCInfo> infoList = myVcs.getAllWcInfos();
68             updateList(infoList);
69             myRefreshLabel.setEnabled(true);
70             SwingUtilities.invokeLater(focus);
71           }
72         }, ModalityState.NON_MODAL);
73       }
74     });
75
76     final JPanel holderPanel = new JPanel(new BorderLayout());
77     myPanel = new JPanel(new GridBagLayout());
78     final JPanel panel = new JPanel(new BorderLayout());
79     panel.add(myPanel, BorderLayout.NORTH);
80     holderPanel.add(panel, BorderLayout.WEST);
81     myRefreshLabel = new LinkLabel("Refresh", null, new LinkListener() {
82       public void linkSelected(LinkLabel aSource, Object aLinkData) {
83         if (myRefreshLabel.isEnabled()) {
84           myVcs.invokeRefreshSvnRoots(false);
85           myRefreshLabel.setEnabled(false);
86         }
87       }
88     });
89     myHolder = new JScrollPane(holderPanel);
90     setFocusableForLinks(myRefreshLabel);
91     initView();
92   }
93
94   public JComponent getPrefferedFocusComponent() {
95     return myRefreshLabel;
96   }
97
98   private JTextField createField(final String text) {
99     final JTextField field = new JTextField(text);
100     field.setBackground(UIUtil.getPanelBackgound());
101     field.setEditable(false);                               
102     field.setBorder(null);
103     field.setFocusable(false);
104     field.setHorizontalAlignment(JTextField.RIGHT);
105     field.setCaretPosition(0);
106     return field;
107   }
108
109   private void updateList(final List<WCInfo> infoList) {
110     myPanel.removeAll();
111     final Insets nullIndent = new Insets(1, 3, 1, 0);
112     final GridBagConstraints gb =
113       new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(2, 2, 0, 0), 0, 0);
114     gb.insets.left = 4;
115     myPanel.add(myRefreshLabel, gb);
116     gb.insets.left = 1;
117
118     final LocalFileSystem lfs = LocalFileSystem.getInstance();
119     final Insets topIndent = new Insets(10, 3, 0, 0);
120     for (final WCInfo wcInfo : infoList) {
121       final JPanel copyPanel = new JPanel(new GridBagLayout());
122
123       final GridBagConstraints gb1 =
124         new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, nullIndent, 0, 0);
125       gb1.insets.top = 1;
126       gb1.gridwidth = 3;
127
128       gb.insets = topIndent;
129       gb.fill = GridBagConstraints.HORIZONTAL;
130       ++ gb.gridy;
131
132       final JPanel contForCopy = new JPanel(new BorderLayout());
133       contForCopy.add(copyPanel, BorderLayout.WEST);
134       myPanel.add(contForCopy, gb);
135
136       final JTextField path = createField(wcInfo.getPath());
137       copyPanel.add(path, gb1);
138       path.setFont(path.getFont().deriveFont(Font.BOLD));
139
140       gb1.insets = nullIndent;
141       gb1.insets.top = 5;
142       ++ gb1.gridy;
143       final JTextField url = createField("URL: " + wcInfo.getRootUrl());
144       copyPanel.add(url, gb1);
145
146       ++ gb1.gridy;
147       gb1.insets.top = 1;
148       final JTextField format = createField("Format: " + wcInfo.getFormat().getName());
149       copyPanel.add(format, gb1);
150
151       final NestedCopyType type = wcInfo.getType();
152       if (NestedCopyType.external.equals(type) || NestedCopyType.switched.equals(type)) {
153         ++ gb1.gridy;
154         final JTextField whetherNested = createField(type.getName() + " copy");
155         copyPanel.add(whetherNested, gb1);
156         whetherNested.setFont(whetherNested.getFont().deriveFont(Font.ITALIC));
157       }
158       if (wcInfo.isIsWcRoot()) {
159         ++ gb1.gridy;
160         final JTextField whetherRoot = createField("Working copy root");
161         copyPanel.add(whetherRoot, gb1);
162         whetherRoot.setFont(whetherRoot.getFont().deriveFont(Font.ITALIC));
163       }
164
165       gb1.gridwidth = 1;
166       gb1.insets.top = 5;
167       ++ gb1.gridy;
168       final LinkLabel formatLabel = new LinkLabel("Change Format", null, new LinkListener() {
169         public void linkSelected(LinkLabel aSource, Object aLinkData) {
170           changeFormat(wcInfo);
171         }
172       });
173       copyPanel.add(formatLabel, gb1);
174       setFocusableForLinks(formatLabel);
175
176       final VirtualFile vf = lfs.refreshAndFindFileByIoFile(new File(wcInfo.getPath()));
177       final VirtualFile root = (vf == null) ? wcInfo.getVcsRoot() : vf;
178       ++ gb1.gridx;
179       final LinkLabel configureBranchesLabel = new LinkLabel("Configure Branches", null, new LinkListener() {
180         public void linkSelected(LinkLabel aSource, Object aLinkData) {
181           BranchConfigurationDialog.configureBranches(myProject, root, true);
182         }
183       });
184       if (root == null) {
185         configureBranchesLabel.setEnabled(false); //+-
186       }
187       copyPanel.add(configureBranchesLabel, gb1);
188       setFocusableForLinks(configureBranchesLabel);
189     }
190
191     myPanel.revalidate();
192     myPanel.repaint();
193   }
194
195   private void setFocusableForLinks(final LinkLabel label) {
196     final Border border = new DottedBorder(new Insets(1,2,1,1), Color.black);
197     label.setFocusable(true);
198     label.addFocusListener(new FocusAdapter() {
199       @Override
200       public void focusGained(FocusEvent e) {
201         super.focusGained(e);
202         label.setBorder(border);
203       }
204
205       @Override
206       public void focusLost(FocusEvent e) {
207         super.focusLost(e);
208         label.setBorder(null);
209       }
210     });
211     label.addKeyListener(new KeyAdapter() {
212       @Override
213       public void keyPressed(KeyEvent e) {
214         if (KeyEvent.VK_ENTER == e.getKeyCode()) {
215           label.doClick();
216         }
217       }
218     });
219   }
220
221   private void changeFormat(final WCInfo wcInfo) {
222     ChangeFormatDialog dialog = new ChangeFormatDialog(myProject, new File(wcInfo.getPath()), false, ! wcInfo.isIsWcRoot());
223     dialog.setData(true, wcInfo.getFormat().getOption());
224     dialog.show();
225     if (! dialog.isOK()) {
226       return;
227     }
228     final String newMode = dialog.getUpgradeMode();
229     if (! wcInfo.getFormat().getOption().equals(newMode)) {
230       final WorkingCopyFormat newFormat = WorkingCopyFormat.getInstance(newMode);
231       final Task.Backgroundable task = new SvnFormatWorker(myProject, newFormat, wcInfo) {
232         @Override
233         public void onSuccess() {
234           super.onSuccess();
235           myRefreshLabel.doClick();
236         }
237       };
238       ProgressManager.getInstance().run(task);
239     }
240   }
241
242   private void initView() {
243     myRefreshLabel.doClick();
244   }
245
246   public JComponent getComponent() {
247     return myHolder;
248   }
249 }