git4idea: Fixed some compatibility problem with Git 1.6.4
[fedora-idea.git] / plugins / git4idea / src / git4idea / ui / GitUIUtil.java
blob73576bbcdd7ddc53dcb639d1d0243304b64e0ec3
1 /*
2 * Copyright 2000-2008 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package git4idea.ui;
18 import com.intellij.openapi.project.Project;
19 import com.intellij.openapi.ui.Messages;
20 import com.intellij.openapi.vcs.VcsException;
21 import com.intellij.openapi.vfs.VirtualFile;
22 import git4idea.GitBranch;
23 import git4idea.GitRemote;
24 import git4idea.GitVcs;
25 import git4idea.config.GitConfigUtil;
26 import git4idea.i18n.GitBundle;
27 import org.jetbrains.annotations.NonNls;
28 import org.jetbrains.annotations.NotNull;
29 import org.jetbrains.annotations.Nullable;
31 import javax.swing.*;
32 import java.awt.*;
33 import java.awt.event.ActionEvent;
34 import java.awt.event.ActionListener;
35 import java.util.Collections;
36 import java.util.List;
38 /**
39 * Utilities for git plugin user interface
41 public class GitUIUtil {
42 /**
43 * Text containing in the label when there is no current branch
45 public static final String NO_CURRENT_BRANCH = GitBundle.getString("common.no.active.branch");
47 /**
48 * A private constructor for utility class
50 private GitUIUtil() {
53 /**
54 * @return a list cell renderer for virtual files (it renders presentable URL)
56 public static ListCellRenderer getVirtualFileListCellRenderer() {
57 return new DefaultListCellRenderer() {
58 public Component getListCellRendererComponent(final JList list,
59 final Object value,
60 final int index,
61 final boolean isSelected,
62 final boolean cellHasFocus) {
63 String text = ((VirtualFile)value).getPresentableUrl();
64 return super.getListCellRendererComponent(list, text, index, isSelected, cellHasFocus);
70 /**
71 * Get text field from combobox
73 * @param comboBox a combobox to examine
74 * @return the text field reference
76 public static JTextField getTextField(JComboBox comboBox) {
77 return (JTextField)comboBox.getEditor().getEditorComponent();
80 /**
81 * Create list cell renderer for remotes. It shows both name and url and highlights the default
82 * remote for the branch with bold.
84 * @param defaultRemote a default remote
85 * @param fetchUrl if true, the fetch url is shown
86 * @return a list cell renderer for virtual files (it renders presentable URL
88 public static ListCellRenderer getGitRemoteListCellRenderer(final String defaultRemote, final boolean fetchUrl) {
89 return new DefaultListCellRenderer() {
90 public Component getListCellRendererComponent(final JList list,
91 final Object value,
92 final int index,
93 final boolean isSelected,
94 final boolean cellHasFocus) {
95 final GitRemote remote = (GitRemote)value;
96 String text;
97 if (value == null) {
98 text = GitBundle.getString("util.remote.renderer.none");
100 else if (".".equals(remote.name())) {
101 text = GitBundle.getString("util.remote.renderer.self");
103 else {
104 String key;
105 if (defaultRemote != null && defaultRemote.equals(remote.name())) {
106 key = "util.remote.renderer.default";
108 else {
109 key = "util.remote.renderer.normal";
111 text = GitBundle.message(key, remote.name(), fetchUrl ? remote.fetchUrl() : remote.pushUrl());
113 return super.getListCellRendererComponent(list, text, index, isSelected, cellHasFocus);
121 * Setup root chooser with specified elements and link selection to the current branch label.
123 * @param project a context project
124 * @param roots git roots for the project
125 * @param defaultRoot a default root
126 * @param gitRootChooser git root selector
127 * @param currentBranchLabel current branch label (might be null)
129 public static void setupRootChooser(final Project project,
130 final List<VirtualFile> roots,
131 final VirtualFile defaultRoot,
132 final JComboBox gitRootChooser,
133 @Nullable final JLabel currentBranchLabel) {
134 for (VirtualFile root : roots) {
135 gitRootChooser.addItem(root);
137 gitRootChooser.setRenderer(getVirtualFileListCellRenderer());
138 gitRootChooser.setSelectedItem(defaultRoot);
139 if (currentBranchLabel != null) {
140 final ActionListener listener = new ActionListener() {
141 public void actionPerformed(final ActionEvent e) {
142 try {
143 VirtualFile root = (VirtualFile)gitRootChooser.getSelectedItem();
144 GitBranch current = GitBranch.current(project, root);
145 assert currentBranchLabel != null;
146 if (current == null) {
147 currentBranchLabel.setText(NO_CURRENT_BRANCH);
149 else {
150 currentBranchLabel.setText(current.getName());
153 catch (VcsException ex) {
154 GitVcs.getInstance(project).showErrors(Collections.singletonList(ex), GitBundle.getString("merge.retrieving.branches"));
158 listener.actionPerformed(null);
159 gitRootChooser.addActionListener(listener);
164 * Get root from the chooser
166 * @param gitRootChooser the chooser constructed with {@link #setupRootChooser(Project, List, VirtualFile, JComboBox, JLabel)}.
167 * @return the current selection
169 public static VirtualFile getRootFromRootChooser(JComboBox gitRootChooser) {
170 return (VirtualFile)gitRootChooser.getSelectedItem();
174 * Show error associated with the specified operation
176 * @param project the project
177 * @param ex the exception
178 * @param operation the operation name
180 public static void showOperationError(final Project project, final VcsException ex, @NonNls @NotNull final String operation) {
181 showOperationError(project, operation, ex.getMessage());
185 * Show error associated with the specified operation
187 * @param project the project
188 * @param message the error description
189 * @param operation the operation name
191 public static void showOperationError(final Project project, final String operation, final String message) {
192 Messages.showErrorDialog(project, message, GitBundle.message("error.occurred.during", operation));
196 * Setup remotes combobox. The default remote for the current branch is selected by default.
197 * This method gets current branch for the project.
199 * @param project the project
200 * @param root the git root
201 * @param remoteCombobox the combobox to update
202 * @param fetchUrl if true, the fetch url is shown instead of push url
204 public static void setupRemotes(final Project project, final VirtualFile root, final JComboBox remoteCombobox, final boolean fetchUrl) {
205 GitBranch gitBranch = null;
206 try {
207 gitBranch = GitBranch.current(project, root);
209 catch (VcsException ex) {
210 // ignore error
212 final String branch = gitBranch != null ? gitBranch.getName() : null;
213 setupRemotes(project, root, branch, remoteCombobox, fetchUrl);
219 * Setup remotes combobox. The default remote for the current branch is selected by default.
221 * @param project the project
222 * @param root the git root
223 * @param currentBranch the current branch
224 * @param remoteCombobox the combobox to update
225 * @param fetchUrl if true, the fetch url is shown for remotes, push otherwise
227 public static void setupRemotes(final Project project,
228 final VirtualFile root,
229 final String currentBranch,
230 final JComboBox remoteCombobox,
231 final boolean fetchUrl) {
232 try {
233 List<GitRemote> remotes = GitRemote.list(project, root);
234 String remote = null;
235 if (currentBranch != null) {
236 remote = GitConfigUtil.getValue(project, root, "branch." + currentBranch + ".remote");
238 remoteCombobox.setRenderer(getGitRemoteListCellRenderer(remote, fetchUrl));
239 GitRemote toSelect = null;
240 remoteCombobox.removeAllItems();
241 for (GitRemote r : remotes) {
242 remoteCombobox.addItem(r);
243 if (r.name().equals(remote)) {
244 toSelect = r;
247 if (toSelect != null) {
248 remoteCombobox.setSelectedItem(toSelect);
251 catch (VcsException e) {
252 GitVcs.getInstance(project).showErrors(Collections.singletonList(e), GitBundle.getString("pull.retrieving.remotes"));
257 * Checks state of the {@code checked} checkbox and if state is {@code checkedState} than to disable {@code changed}
258 * checkbox and change its state to {@code impliedState}. When the {@code checked} checkbox changes states to other state,
259 * than enable {@code changed} and restore its state. Note that the each checkbox should be implied by only one other checkbox.
261 * @param checked the checkbox to monitor
262 * @param checkedState the state that triggers disabling changed state
263 * @param changed the checkbox to change
264 * @param impliedState the implied state of checkbox
266 public static void imply(final JCheckBox checked, final boolean checkedState, final JCheckBox changed, final boolean impliedState) {
267 ActionListener l = new ActionListener() {
268 Boolean previousState;
270 public void actionPerformed(ActionEvent e) {
271 if (checked.isSelected() == checkedState) {
272 if (previousState == null) {
273 previousState = changed.isSelected();
275 changed.setEnabled(false);
276 changed.setSelected(impliedState);
278 else {
279 changed.setEnabled(true);
280 if (previousState != null) {
281 changed.setSelected(previousState);
282 previousState = null;
287 checked.addActionListener(l);
288 l.actionPerformed(null);
292 * Declares states for two checkboxes to be mutually exclusive. When one of the checkboxes goes to the specified state, other is
293 * disabled and forced into reverse of the state (to prevent very fast users from selecting incorrect state or incorrect
294 * initial configuration).
296 * @param first the first checkbox
297 * @param firstState the state of the first checkbox
298 * @param second the second checkbox
299 * @param secondState the state of the second checkbox
301 public static void exclusive(final JCheckBox first, final boolean firstState, final JCheckBox second, final boolean secondState) {
302 ActionListener l = new ActionListener() {
304 * One way check for the condition
305 * @param checked the first to check
306 * @param checkedState the state to match
307 * @param changed the changed control
308 * @param impliedState the implied state
310 private void check(final JCheckBox checked, final boolean checkedState, final JCheckBox changed, final boolean impliedState) {
311 if (checked.isSelected() == checkedState) {
312 changed.setSelected(impliedState);
313 changed.setEnabled(false);
315 else {
316 changed.setEnabled(true);
321 * {@inheritDoc}
323 public void actionPerformed(ActionEvent e) {
324 check(first, firstState, second, !secondState);
325 check(second, secondState, first, !firstState);
328 first.addActionListener(l);
329 second.addActionListener(l);
330 l.actionPerformed(null);
334 * Checks state of the {@code checked} checkbox and if state is {@code checkedState} than to disable {@code changed}
335 * text field and clean it. When the {@code checked} checkbox changes states to other state,
336 * than enable {@code changed} and restore its state. Note that the each text field should be implied by
337 * only one other checkbox.
339 * @param checked the checkbox to monitor
340 * @param checkedState the state that triggers disabling changed state
341 * @param changed the checkbox to change
343 public static void implyDisabled(final JCheckBox checked, final boolean checkedState, final JTextField changed) {
344 ActionListener l = new ActionListener() {
345 String previousState;
347 public void actionPerformed(ActionEvent e) {
348 if (checked.isSelected() == checkedState) {
349 if (previousState == null) {
350 previousState = changed.getText();
352 changed.setEnabled(false);
353 changed.setText("");
355 else {
356 changed.setEnabled(true);
357 if (previousState != null) {
358 changed.setText(previousState);
359 previousState = null;
364 checked.addActionListener(l);
365 l.actionPerformed(null);