gt:             previousState = changed.getText();
context: /*
   * Copyright 2000-2009 JetBrains s.r.o.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.community.intellij.plugins.communitycase.ui;
  
  import com.intellij.ide.ui.ListCellRendererWrapper;
  import com.intellij.notification.Notification;
  import com.intellij.notification.NotificationType;
  import com.intellij.notification.Notifications;
  import com.intellij.openapi.project.Project;
  import com.intellij.openapi.ui.Messages;
  import com.intellij.openapi.vcs.AbstractVcsHelper;
  import com.intellij.openapi.vcs.VcsException;
  import com.intellij.openapi.vfs.VirtualFile;
  import org.community.intellij.plugins.communitycase.Branch;
  import org.community.intellij.plugins.communitycase.Remote;
  import org.community.intellij.plugins.communitycase.Vcs;
  import org.community.intellij.plugins.communitycase.config.ConfigUtil;
  import org.community.intellij.plugins.communitycase.i18n.Bundle;
  import org.jetbrains.annotations.NonNls;
  import org.jetbrains.annotations.NotNull;
  import org.jetbrains.annotations.Nullable;
  
  import javax.swing.*;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.List;
  
  /**
   * Utilities for plugin user interface
   */
  public class UiUtil {
    /**
     * Text containing in the label when there is no current branch
     */
    public static final String NO_CURRENT_BRANCH = Bundle.getString("common.no.active.branch");
  
    /**
     * A private constructor for utility class
     */
    private UiUtil() { }
  
    /**
     * Displays a "success"-notification.
     */
    public static void notifySuccess(Project project, String title, String description) {
      Notifications.Bus.notify(new Notification(Vcs.NOTIFICATION_GROUP_ID, title, description, NotificationType.INFORMATION), project);
    }
  
    /**
     * @return a list cell renderer for virtual files (it renders presentable URL)
     * @param listCellRenderer
     */
    public static ListCellRenderer getVirtualFileListCellRenderer(final ListCellRenderer listCellRenderer) {
      return new ListCellRendererWrapper<VirtualFile>(listCellRenderer) {
        @Override
        public void customize(final JList list, final VirtualFile file, final int index, final boolean selected, final boolean hasFocus) {
          setText(file == null || !file.isValid() ? "(invalid)" : file.getPresentableUrl());
        }
      };
    }
  
    /**
     * Get text field from combobox
     *
     * @param comboBox a combobox to examine
     * @return the text field reference
     */
    public static JTextField getTextField(JComboBox comboBox) {
      return (JTextField)comboBox.getEditor().getEditorComponent();
    }
  
    /**
     * Create list cell renderer for remotes. It shows both name and url and highlights the default
     * remote for the branch with bold.
     *
     *
     * @param defaultRemote a default remote
     * @param fetchUrl      if true, the fetch url is shown
     * @param listCellRenderer
     * @return a list cell renderer for virtual files (it renders presentable URL
     */
    public static ListCellRenderer getRemoteListCellRenderer(final String defaultRemote, final boolean fetchUrl,
                                                                final ListCellRenderer listCellRenderer) {
      return new ListCellRendererWrapper<Remote>(listCellRenderer) {
        @Override
        public void customize(final JList list, final Remote remote, final int index, final boolean selected, final boolean hasFocus) {
          final String text;
          if (remote == null) {
            text = Bundle.getString("util.remote.renderer.none");
          }
          else if (".".equals(remote.name())) {
            text = Bundle.getString("util.remote.renderer.self");
          }
          else {
            String key;
            if (defaultRemote != null && defaultRemote.equals(remote.name())) {
              key = "util.remote.renderer.default";
            }
            else {
              key = "util.remote.renderer.normal";
            }
            text = Bundle.message(key, remote.name(), fetchUrl ? remote.fetchUrl() : remote.pushUrl());
          }
          setText(text);
        }
      };
    }
  
    /**
     * Setup root chooser with specified elements and link selection to the current branch label.
     *
     * @param project            a context project
     * @param roots              roots for the project
     * @param defaultRoot        a default root
     * @param RootChooser     root selector
     * @param currentBranchLabel current branch label (might be null)
     */
    public static void setupRootChooser(@NotNull final Project project,
                                        @NotNull final List<VirtualFile> roots,
                                        @Nullable final VirtualFile defaultRoot,
                                        @NotNull final JComboBox RootChooser,
                                        @Nullable final JLabel currentBranchLabel) {
      for (VirtualFile root : roots) {
        RootChooser.addItem(root);
      }
      RootChooser.setRenderer(getVirtualFileListCellRenderer(RootChooser.getRenderer()));
      RootChooser.setSelectedItem(defaultRoot != null ? defaultRoot : roots.get(0));
      if (currentBranchLabel != null) {
        final ActionListener listener = new ActionListener() {
          public void actionPerformed(final ActionEvent e) {
            try {
              VirtualFile root = (VirtualFile)RootChooser.getSelectedItem();
              assert root != null : "The root must not be null";
              Branch current = Branch.current(project, root);
              if (current == null) {
                currentBranchLabel.setText(NO_CURRENT_BRANCH);
              }
              else {
                currentBranchLabel.setText(current.getName());
              }
            }
            catch (VcsException ex) {
              Vcs.getInstance(project).showErrors(Collections.singletonList(ex), Bundle.getString("merge.retrieving.branches"));
            }
          }
        };
        listener.actionPerformed(null);
        RootChooser.addActionListener(listener);
      }
    }
  
    /**
     * Get root from the chooser
     *
     * @param RootChooser the chooser constructed with {@link #setupRootChooser(Project, List, VirtualFile, JComboBox, JLabel)}.
     * @return the current selection
     */
    public static VirtualFile getRootFromRootChooser(JComboBox RootChooser) {
      return (VirtualFile)RootChooser.getSelectedItem();
    }
  
    /**
     * Show error associated with the specified operation
     *
     * @param project   the project
     * @param ex        the exception
     * @param operation the operation name
     */
    public static void showOperationError(final Project project, final VcsException ex, @NonNls @NotNull final String operation) {
      showOperationError(project, operation, ex.getMessage());
    }
  
    /**
     * Show errors associated with the specified operation
     *
     * @param project   the project
     * @param exs       the exceptions to show
     * @param operation the operation name
     */
    public static void showOperationErrors(final Project project,
                                           final Collection<VcsException> exs,
                                           @NonNls @NotNull final String operation) {
      if (exs.size() == 1) {
        //noinspection ThrowableResultOfMethodCallIgnored
        showOperationError(project, operation, exs.iterator().next().getMessage());
      }
      else if (exs.size() > 1) {
        // TODO use dialog in order to show big messages
        StringBuilder b = new StringBuilder();
        for (VcsException ex : exs) {
          b.append(Bundle.message("errors.message.item", ex.getMessage()));
        }
        showOperationError(project, operation, Bundle.message("errors.message", b.toString()));
      }
    }
  
    /**
     * Show error associated with the specified operation
     *
     * @param project   the project
     * @param message   the error description
     * @param operation the operation name
     */
    public static void showOperationError(final Project project, final String operation, final String message) {
      Messages.showErrorDialog(project, message, Bundle.message("error.occurred.during", operation));
    }
  
    /**
     * Show errors on the tab
     *
     * @param project the context project
     * @param title   the operation title
     * @param errors  the errors to display
     */
    public static void showTabErrors(Project project, String title, List<VcsException> errors) {
      AbstractVcsHelper.getInstance(project).showErrors(errors, title);
    }
  
    /**
     * Setup remotes combobox. The default remote for the current branch is selected by default.
     * This method gets current branch for the project.
     *
     * @param project        the project
     * @param root           the root
     * @param remoteCombobox the combobox to update
     * @param fetchUrl       if true, the fetch url is shown instead of push url
     */
    public static void setupRemotes(final Project project, final VirtualFile root, final JComboBox remoteCombobox, final boolean fetchUrl) {
      Branch Branch = null;
      try {
        Branch = Branch.current(project, root);
      }
      catch (VcsException ex) {
        // ignore error
      }
      final String branch = Branch != null ? Branch.getName() : null;
      setupRemotes(project, root, branch, remoteCombobox, fetchUrl);
  
    }
  
    /**
     * Setup remotes combobox. The default remote for the current branch is selected by default.
     *
     * @param project        the project
     * @param root           the root
     * @param currentBranch  the current branch
     * @param remoteCombobox the combobox to update
     * @param fetchUrl       if true, the fetch url is shown for remotes, push otherwise
     */
    public static void setupRemotes(final Project project,
                                    final VirtualFile root,
                                    final String currentBranch,
                                    final JComboBox remoteCombobox,
                                    final boolean fetchUrl) {
      try {
        List<Remote> remotes = Remote.list(project, root);
        String remote = null;
        if (currentBranch != null) {
          remote = ConfigUtil.getValue(project, root, "branch." + currentBranch + ".remote");
        }
        remoteCombobox.setRenderer(getRemoteListCellRenderer(remote, fetchUrl, remoteCombobox.getRenderer()));
        Remote toSelect = null;
        remoteCombobox.removeAllItems();
        for (Remote r : remotes) {
          remoteCombobox.addItem(r);
          if (r.name().equals(remote)) {
            toSelect = r;
          }
        }
        if (toSelect != null) {
          remoteCombobox.setSelectedItem(toSelect);
        }
      }
      catch (VcsException e) {
        Vcs.getInstance(project).showErrors(Collections.singletonList(e), Bundle.getString("pull.retrieving.remotes"));
      }
    }
  
    /**
     * Checks state of the {@code checked} checkbox and if state is {@code checkedState} than to disable {@code changed}
     * checkbox and change its state to {@code impliedState}. When the {@code checked} checkbox changes states to other state,
     * than enable {@code changed} and restore its state. Note that the each checkbox should be implied by only one other checkbox.
     *
     * @param checked      the checkbox to monitor
     * @param checkedState the state that triggers disabling changed state
     * @param changed      the checkbox to change
     * @param impliedState the implied state of checkbox
     */
    public static void imply(final JCheckBox checked, final boolean checkedState, final JCheckBox changed, final boolean impliedState) {
      ActionListener l = new ActionListener() {
        Boolean previousState;
  
        public void actionPerformed(ActionEvent e) {
          if (checked.isSelected() == checkedState) {
            if (previousState == null) {
              previousState = changed.isSelected();
            }
            changed.setEnabled(false);
            changed.setSelected(impliedState);
          }
          else {
            changed.setEnabled(true);
            if (previousState != null) {
              changed.setSelected(previousState);
              previousState = null;
            }
          }
        }
      };
      checked.addActionListener(l);
      l.actionPerformed(null);
    }
  
    /**
     * Declares states for two checkboxes to be mutually exclusive. When one of the checkboxes goes to the specified state, other is
     * disabled and forced into reverse of the state (to prevent very fast users from selecting incorrect state or incorrect
     * initial configuration).
     *
     * @param first       the first checkbox
     * @param firstState  the state of the first checkbox
     * @param second      the second checkbox
     * @param secondState the state of the second checkbox
     */
    public static void exclusive(final JCheckBox first, final boolean firstState, final JCheckBox second, final boolean secondState) {
      ActionListener l = new ActionListener() {
        /**
         * One way check for the condition
         * @param checked the first to check
         * @param checkedState the state to match
         * @param changed the changed control
         * @param impliedState the implied state
         */
        private void check(final JCheckBox checked, final boolean checkedState, final JCheckBox changed, final boolean impliedState) {
          if (checked.isSelected() == checkedState) {
            changed.setSelected(impliedState);
            changed.setEnabled(false);
          }
          else {
            changed.setEnabled(true);
          }
        }
  
        /**
         * {@inheritDoc}
         */
        public void actionPerformed(ActionEvent e) {
          check(first, firstState, second, !secondState);
          check(second, secondState, first, !firstState);
        }
      };
      first.addActionListener(l);
      second.addActionListener(l);
      l.actionPerformed(null);
    }
  
    /**
     * Checks state of the {@code checked} checkbox and if state is {@code checkedState} than to disable {@code changed}
     * text field and clean it. When the {@code checked} checkbox changes states to other state,
     * than enable {@code changed} and restore its state. Note that the each text field should be implied by
     * only one other checkbox.
     *
     * @param checked      the checkbox to monitor
     * @param checkedState the state that triggers disabling changed state
     * @param changed      the checkbox to change
     */
    public static void implyDisabled(final JCheckBox checked, final boolean checkedState, final JTextField changed) {
      ActionListener l = new ActionListener() {
        String previousState;
  
        public void actionPerformed(ActionEvent e) {
          if (checked.isSelected() == checkedState) {
            if (previousState == null) {
  