private static void fixGtkPopupStyle() {
    if (!UIUtil.isUnderGTKLookAndFeel()) return;

    final SynthStyleFactory original = SynthLookAndFeel.getStyleFactory();

    SynthLookAndFeel.setStyleFactory(
        new SynthStyleFactory() {
          @Override
          public SynthStyle getStyle(final JComponent c, final Region id) {
            final SynthStyle style = original.getStyle(c, id);
            if (id == Region.POPUP_MENU) {
              final Integer x =
                  ReflectionUtil.getField(style.getClass(), style, int.class, "xThickness");
              if (x != null && x == 0) {
                // workaround for Sun bug #6636964
                ReflectionUtil.setField(style.getClass(), style, int.class, "xThickness", 1);
                ReflectionUtil.setField(style.getClass(), style, int.class, "yThickness", 3);
              }
            }
            return style;
          }
        });

    new JBPopupMenu(); // invokes updateUI() -> updateStyle()

    SynthLookAndFeel.setStyleFactory(original);
  }
  private static void patchGtkDefaults(UIDefaults defaults) {
    if (!UIUtil.isUnderGTKLookAndFeel()) return;

    Map<String, Icon> map =
        ContainerUtil.newHashMap(
            Arrays.asList(
                "OptionPane.errorIcon",
                "OptionPane.informationIcon",
                "OptionPane.warningIcon",
                "OptionPane.questionIcon"),
            Arrays.asList(
                AllIcons.General.ErrorDialog,
                AllIcons.General.InformationDialog,
                AllIcons.General.WarningDialog,
                AllIcons.General.QuestionDialog));
    // GTK+ L&F keeps icons hidden in style
    SynthStyle style = SynthLookAndFeel.getStyle(new JOptionPane(""), Region.DESKTOP_ICON);
    for (String key : map.keySet()) {
      if (defaults.get(key) != null) continue;

      Object icon = style == null ? null : style.get(null, key);
      defaults.put(key, icon instanceof Icon ? icon : map.get(key));
    }

    Color fg = defaults.getColor("Label.foreground");
    Color bg = defaults.getColor("Label.background");
    if (fg != null && bg != null) {
      defaults.put("Label.disabledForeground", UIUtil.mix(fg, bg, 0.5));
    }
  }
    @Override
    protected void customizeCellRenderer(
        JList list, Object value, int index, boolean selected, boolean hasFocus) {
      setIcon(myListEntryIcon);
      if (myUseIdeaEditor) {
        int max = list.getModel().getSize();
        String indexString = String.valueOf(index + 1);
        int count = String.valueOf(max).length() - indexString.length();
        char[] spaces = new char[count];
        Arrays.fill(spaces, ' ');
        String prefix = indexString + new String(spaces) + "  ";
        append(prefix, SimpleTextAttributes.GRAYED_ATTRIBUTES);
      } else if (UIUtil.isUnderGTKLookAndFeel()) {
        // Fix GTK background
        Color background =
            selected ? UIUtil.getListSelectionBackground() : UIUtil.getListBackground();
        UIUtil.changeBackGround(this, background);
      }
      String text = ((Item) value).shortText;

      FontMetrics metrics = list.getFontMetrics(list.getFont());
      int charWidth = metrics.charWidth('m');
      int maxLength = list.getParent().getParent().getWidth() * 3 / charWidth / 2;
      text = StringUtil.first(text, maxLength, true); // do not paint long strings
      append(text, SimpleTextAttributes.REGULAR_ATTRIBUTES);
    }
  private static void fixGtkPopupStyle() {
    if (!UIUtil.isUnderGTKLookAndFeel()) return;

    final SynthStyleFactory original = SynthLookAndFeel.getStyleFactory();

    SynthLookAndFeel.setStyleFactory(
        new SynthStyleFactory() {
          @Override
          public SynthStyle getStyle(final JComponent c, final Region id) {
            final SynthStyle style = original.getStyle(c, id);
            if (id == Region.POPUP_MENU) {
              try {
                Field f = style.getClass().getDeclaredField("xThickness");
                f.setAccessible(true);
                final Object x = f.get(style);
                if (x instanceof Integer && (Integer) x == 0) {
                  // workaround for Sun bug #6636964
                  f.set(style, 1);
                  f = style.getClass().getDeclaredField("yThickness");
                  f.setAccessible(true);
                  f.set(style, 3);
                }
              } catch (Exception ignore) {
              }
            }
            return style;
          }
        });

    new JBPopupMenu(); // invokes updateUI() -> updateStyle()

    SynthLookAndFeel.setStyleFactory(original);
  }
 @Override
 public void setUI(final MenuItemUI ui) {
   final MenuItemUI newUi =
       UIUtil.isUnderGTKLookAndFeel() && GtkMenuItemUI.isUiAcceptable(ui)
           ? new GtkMenuItemUI(ui)
           : ui;
   super.setUI(newUi);
 }
Beispiel #6
0
 @Override
 public Insets getInsets() {
   Insets insets = super.getInsets();
   if (UIUtil.isUnderGTKLookAndFeel() || UIUtil.isUnderNimbusLookAndFeel()) {
     insets.top += 1;
     insets.bottom += 2;
   }
   return insets;
 }
 @Override
 public void updateUI() {
   super.updateUI();
   // putClientProperty(SwingUtilities2.AA_TEXT_PROPERTY_KEY, null);
   if (UIUtil.isMotifLookAndFeel()) {
     setBorder(BorderFactory.createEtchedBorder());
   } else if (!UIUtil.isUnderGTKLookAndFeel()) {
     setBorder(UIUtil.getButtonBorder());
   }
 }
 private static void patchOptionPaneIcons(final UIDefaults defaults) {
   if (UIUtil.isUnderGTKLookAndFeel() && defaults.get(ourOptionPaneIconKeys[0]) == null) {
     // GTK+ L&F keeps icons hidden in style
     final SynthStyle style = SynthLookAndFeel.getStyle(new JOptionPane(""), Region.DESKTOP_ICON);
     if (style != null) {
       for (final String key : ourOptionPaneIconKeys) {
         final Object icon = style.get(null, key);
         if (icon != null) defaults.put(key, icon);
       }
     }
   }
 }
  @Override
  public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
    final Component result = super.prepareRenderer(renderer, row, column);
    final boolean selected =
        myExpandableItemsHandler.getExpandedItems().contains(new TableCell(row, column));

    // Fix GTK background
    if (UIUtil.isUnderGTKLookAndFeel()) {
      UIUtil.changeBackGround(this, UIUtil.getTreeTextBackground());
    }

    if (isTableDecorationSupported() && isStriped() && result instanceof JComponent) {
      final Color bg = row % 2 == 1 ? getBackground() : DECORATED_ROW_BG_COLOR;
      final JComponent c = (JComponent) result;
      final boolean cellSelected = isCellSelected(row, column);
      if (!cellSelected || (!hasFocus() && !getSelectionBackground().equals(c.getBackground()))) {
        c.setOpaque(true);
        c.setBackground(bg);
        for (Component child : c.getComponents()) {
          child.setBackground(bg);
        }
      }
    }

    if (!selected) return result;

    return new JComponent() {
      {
        add(result);
        setOpaque(false);
        setLayout(
            new AbstractLayoutManager() {
              @Override
              public Dimension preferredLayoutSize(Container parent) {
                return result.getPreferredSize();
              }

              @Override
              public void layoutContainer(Container parent) {
                Dimension size = parent.getSize();
                Insets i = parent.getInsets();
                Dimension pref = result.getPreferredSize();
                result.setBounds(
                    i.left,
                    i.top,
                    Math.max(pref.width, size.width - i.left - i.right),
                    size.height - i.top - i.bottom);
              }
            });
      }
    };
  }
 @Override
 public void setUI(ProgressBarUI ui) {
   boolean nativeLaf =
       UIUtil.isUnderWindowsLookAndFeel()
           || UIUtil.isUnderAquaLookAndFeel()
           || UIUtil.isUnderGTKLookAndFeel();
   if (nativeLaf) {
     ui = new DarculaProgressBarUI();
   }
   super.setUI(ui);
   if (nativeLaf) {
     setPreferredSize(new Dimension(getPreferredSize().width, JBUI.scale(NATIVE_LAF_HEIGHT)));
   }
 }
    @Override
    public Popup getPopup(final Component owner, final Component contents, final int x, final int y)
        throws IllegalArgumentException {
      final Point point = fixPopupLocation(contents, x, y);

      final int popupType =
          UIUtil.isUnderGTKLookAndFeel() ? WEIGHT_HEAVY : PopupUtil.getPopupType(this);
      if (popupType >= 0) {
        PopupUtil.setPopupType(myDelegate, popupType);
      }

      final Popup popup = myDelegate.getPopup(owner, contents, point.x, point.y);
      fixPopupSize(popup, contents);
      return popup;
    }
  public CustomizableComboBox() {
    super(new BorderLayout());

    myThemedCombo.setEditable(true);

    PopupMouseListener listener = new PopupMouseListener();
    // GTK always draws a border on the textbox.  It cannot be removed,
    // so to compensate, we remove our own border so we don't have a double border.
    if (UIUtil.isUnderGTKLookAndFeel()) {
      this.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
    } else {
      this.setBorder(
          BorderFactory.createCompoundBorder(
              BorderFactory.createEmptyBorder(2, 2, 2, 2),
              BorderFactory.createLineBorder(getBorderColor(), 1)));
    }

    // Try to turn off the border on the JTextField.
    myTextField =
        new JBTextField() {
          @Override
          public void setBorder(Border border) {
            super.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0));
          }
        };
    myTextField.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0));
    myTextField.addMouseListener(listener);
    myTextField.addFocusListener(
        new FocusListener() {
          @Override
          public void focusGained(FocusEvent e) {
            myTextField.selectAll();
          }

          @Override
          public void focusLost(FocusEvent e) {
            // no-op
          }
        });

    JButton popupButton = createArrowButton();
    popupButton.addMouseListener(listener);

    this.add(popupButton, BorderLayout.EAST);
    this.add(myTextField, BorderLayout.CENTER);
  }
    private static void fixPopupSize(final Popup popup, final Component contents) {
      if (!UIUtil.isUnderGTKLookAndFeel() || !(contents instanceof JPopupMenu)) return;

      for (Class<?> aClass = popup.getClass();
          aClass != null && Popup.class.isAssignableFrom(aClass);
          aClass = aClass.getSuperclass()) {
        try {
          final Method getComponent = aClass.getDeclaredMethod("getComponent");
          getComponent.setAccessible(true);
          final Object component = getComponent.invoke(popup);
          if (component instanceof JWindow) {
            ((JWindow) component).setSize(new Dimension(0, 0));
          }
          break;
        } catch (Exception ignored) {
        }
      }
    }
  public final Component getListCellRendererComponent(
      final JList list,
      final Object value,
      final int index,
      final boolean isSelected,
      final boolean cellHasFocus) {
    mySeparator = false;
    myIcon = null;
    myText = null;
    myForeground = null;
    myBackground = null;
    myFont = null;
    myToolTipText = null;

    @SuppressWarnings("unchecked")
    final T t = (T) value;
    customize(list, t, index, isSelected, cellHasFocus);

    if (mySeparator) {
      final TitledSeparator separator = new TitledSeparator(myText);
      separator.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0));
      if (!UIUtil.isUnderGTKLookAndFeel()) {
        separator.setOpaque(false);
        separator.setBackground(UIUtil.TRANSPARENT_COLOR);
        separator.getLabel().setOpaque(false);
        separator.getLabel().setBackground(UIUtil.TRANSPARENT_COLOR);
      }
      return separator;
    }

    final Component component =
        myOriginalRenderer.getListCellRendererComponent(
            list, value, index, isSelected, cellHasFocus);
    if (component instanceof JLabel) {
      final JLabel label = (JLabel) component;
      label.setIcon(myIcon);
      if (myText != null) label.setText(myText);
      if (myForeground != null) label.setForeground(myForeground);
      if (myBackground != null && !isSelected) label.setBackground(myBackground);
      if (myFont != null) label.setFont(myFont);
      label.setToolTipText(myToolTipText);
    }
    return component;
  }
Beispiel #15
0
 private static boolean hasIconsOutsideOfTextField() {
   return UIUtil.isUnderGTKLookAndFeel() || UIUtil.isUnderNimbusLookAndFeel();
 }
    public ComboBoxButton(Presentation presentation) {
      myPresentation = presentation;
      setModel(new MyButtonModel());
      setHorizontalAlignment(LEFT);
      setFocusable(false);
      Insets margins = getMargin();
      setMargin(new Insets(margins.top, 2, margins.bottom, 2));
      if (isSmallVariant()) {
        setBorder(IdeBorderFactory.createEmptyBorder(0, 2, 0, 2));
        if (!UIUtil.isUnderGTKLookAndFeel()) {
          setFont(UIUtil.getLabelFont().deriveFont(11.0f));
        }
      }
      addActionListener(
          new ActionListener() {
            public void actionPerformed(ActionEvent e) {
              if (!myForcePressed) {
                IdeFocusManager.getGlobalInstance()
                    .doWhenFocusSettlesDown(
                        new Runnable() {
                          public void run() {
                            showPopup();
                          }
                        });
              }
            }
          });

      //noinspection HardCodedStringLiteral
      putClientProperty("Quaqua.Button.style", "placard");
      addMouseListener(
          new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
              myMouseInside = true;
              repaint();
            }

            @Override
            public void mouseExited(MouseEvent e) {
              myMouseInside = false;
              repaint();
            }

            @Override
            public void mousePressed(final MouseEvent e) {
              if (SwingUtilities.isLeftMouseButton(e)) {
                e.consume();
                doClick();
              }
            }

            @Override
            public void mouseReleased(MouseEvent e) {
              dispatchEventToPopup(e);
            }
          });
      addMouseMotionListener(
          new MouseMotionListener() {
            @Override
            public void mouseDragged(MouseEvent e) {
              mouseMoved(
                  new MouseEvent(
                      e.getComponent(),
                      MouseEvent.MOUSE_MOVED,
                      e.getWhen(),
                      e.getModifiers(),
                      e.getX(),
                      e.getY(),
                      e.getClickCount(),
                      e.isPopupTrigger(),
                      e.getButton()));
            }

            @Override
            public void mouseMoved(MouseEvent e) {
              dispatchEventToPopup(e);
            }
          });
    }
  public HectorComponent(@NotNull PsiFile file) {
    super(new GridBagLayout());
    setBorder(BorderFactory.createEmptyBorder(0, 0, 7, 0));
    myFile = file;
    mySliders = new HashMap<Language, JSlider>();

    final Project project = myFile.getProject();
    final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
    final VirtualFile virtualFile = myFile.getContainingFile().getVirtualFile();
    LOG.assertTrue(virtualFile != null);
    final boolean notInLibrary =
        !fileIndex.isInLibrarySource(virtualFile) && !fileIndex.isInLibraryClasses(virtualFile)
            || fileIndex.isInContent(virtualFile);
    final FileViewProvider viewProvider = myFile.getViewProvider();
    List<Language> languages = new ArrayList<Language>(viewProvider.getLanguages());
    Collections.sort(languages, PsiUtilBase.LANGUAGE_COMPARATOR);
    for (Language language : languages) {
      @SuppressWarnings("UseOfObsoleteCollectionType")
      final Hashtable<Integer, JLabel> sliderLabels = new Hashtable<Integer, JLabel>();
      sliderLabels.put(1, new JLabel(EditorBundle.message("hector.none.slider.label")));
      sliderLabels.put(2, new JLabel(EditorBundle.message("hector.syntax.slider.label")));
      if (notInLibrary) {
        sliderLabels.put(3, new JLabel(EditorBundle.message("hector.inspections.slider.label")));
      }

      final JSlider slider = new JSlider(SwingConstants.VERTICAL, 1, notInLibrary ? 3 : 2, 1);
      if (UIUtil.isUnderGTKLookAndFeel()) {
        // default GTK+ slider UI is way too ugly
        slider.putClientProperty("Slider.paintThumbArrowShape", true);
        slider.setUI(new BasicSliderUI(slider));
      }
      slider.setLabelTable(sliderLabels);
      UIUtil.setSliderIsFilled(slider, true);
      slider.setPaintLabels(true);
      slider.setSnapToTicks(true);
      slider.addChangeListener(
          new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
              int value = slider.getValue();
              for (Enumeration<Integer> enumeration = sliderLabels.keys();
                  enumeration.hasMoreElements(); ) {
                Integer key = enumeration.nextElement();
                sliderLabels
                    .get(key)
                    .setForeground(
                        key.intValue() <= value
                            ? UIUtil.getLabelForeground()
                            : UIUtil.getLabelDisabledForeground());
              }
            }
          });

      final PsiFile psiRoot = viewProvider.getPsi(language);
      assert psiRoot != null : "No root in " + viewProvider + " for " + language;
      slider.setValue(
          getValue(
              HighlightLevelUtil.shouldHighlight(psiRoot),
              HighlightLevelUtil.shouldInspect(psiRoot)));
      mySliders.put(language, slider);
    }

    GridBagConstraints gc =
        new GridBagConstraints(
            0,
            GridBagConstraints.RELATIVE,
            1,
            1,
            0,
            0,
            GridBagConstraints.NORTHWEST,
            GridBagConstraints.NONE,
            new Insets(0, 5, 0, 0),
            0,
            0);

    JPanel panel = new JPanel(new GridBagLayout());
    panel.setBorder(IdeBorderFactory.createTitledBorder(myTitle, false));
    final boolean addLabel = mySliders.size() > 1;
    if (addLabel) {
      layoutVertical(panel);
    } else {
      layoutHorizontal(panel);
    }
    gc.gridx = 0;
    gc.gridy = 0;
    gc.weighty = 1.0;
    gc.fill = GridBagConstraints.BOTH;
    add(panel, gc);

    gc.gridy = GridBagConstraints.RELATIVE;
    gc.weighty = 0;

    final HyperlinkLabel configurator = new HyperlinkLabel("Configure inspections");
    gc.insets.right = 5;
    gc.insets.bottom = 10;
    gc.weightx = 0;
    gc.fill = GridBagConstraints.NONE;
    gc.anchor = GridBagConstraints.EAST;
    add(configurator, gc);
    configurator.addHyperlinkListener(
        new HyperlinkListener() {
          @Override
          public void hyperlinkUpdate(HyperlinkEvent e) {
            final JBPopup hector = getOldHector();
            if (hector != null) {
              hector.cancel();
            }
            if (!DaemonCodeAnalyzer.getInstance(myFile.getProject())
                .isHighlightingAvailable(myFile)) return;
            final Project project = myFile.getProject();
            final ErrorsConfigurable errorsConfigurable =
                ErrorsConfigurable.SERVICE.createConfigurable(project);
            assert errorsConfigurable != null;
            ShowSettingsUtil.getInstance().editConfigurable(project, errorsConfigurable);
          }
        });

    gc.anchor = GridBagConstraints.WEST;
    gc.weightx = 1.0;
    gc.insets.right = 0;
    gc.fill = GridBagConstraints.HORIZONTAL;
    myAdditionalPanels = new ArrayList<HectorComponentPanel>();
    for (HectorComponentPanelsProvider provider :
        Extensions.getExtensions(HectorComponentPanelsProvider.EP_NAME, project)) {
      final HectorComponentPanel componentPanel = provider.createConfigurable(file);
      if (componentPanel != null) {
        myAdditionalPanels.add(componentPanel);
        add(componentPanel.createComponent(), gc);
        componentPanel.reset();
      }
    }
  }
  @Override
  public final Component getTreeCellRendererComponent(
      JTree tree,
      Object value,
      boolean selected,
      boolean expanded,
      boolean leaf,
      int row,
      boolean hasFocus) {
    myTree = tree;

    clear();

    mySelected = selected;
    myFocusedCalculated = false;

    // We paint background if and only if tree path is selected and tree has focus.
    // If path is selected and tree is not focused then we just paint focused border.
    if (UIUtil.isFullRowSelectionLAF()) {
      setBackground(selected ? UIUtil.getTreeSelectionBackground() : null);
    } else if (WideSelectionTreeUI.isWideSelection(tree)) {
      setPaintFocusBorder(false);
      if (selected) {
        setBackground(
            hasFocus
                ? UIUtil.getTreeSelectionBackground()
                : UIUtil.getTreeUnfocusedSelectionBackground());
      }
    } else if (selected) {
      setPaintFocusBorder(true);
      if (isFocused()) {
        setBackground(UIUtil.getTreeSelectionBackground());
      } else {
        setBackground(null);
      }
    } else {
      setBackground(null);
    }

    if (value instanceof LoadingNode) {
      setForeground(JBColor.GRAY);
      setIcon(LOADING_NODE_ICON);
    } else {
      setForeground(tree.getForeground());
      setIcon(null);
    }

    if (UIUtil.isUnderGTKLookAndFeel()) {
      super.setOpaque(false); // avoid nasty background
      super.setIconOpaque(false);
    } else if (UIUtil.isUnderNimbusLookAndFeel() && selected && hasFocus) {
      super.setOpaque(false); // avoid erasing Nimbus focus frame
      super.setIconOpaque(false);
    } else if (WideSelectionTreeUI.isWideSelection(tree)) {
      super.setOpaque(false); // avoid erasing Nimbus focus frame
      super.setIconOpaque(false);
    } else {
      super.setOpaque(
          myOpaque
              || selected && hasFocus
              || selected && isFocused()); // draw selection background even for non-opaque tree
    }

    if (tree.getUI() instanceof WideSelectionTreeUI && UIUtil.isUnderAquaBasedLookAndFeel()) {
      setMyBorder(null);
      setIpad(new Insets(0, 2, 0, 2));
    }

    customizeCellRenderer(tree, value, selected, expanded, leaf, row, hasFocus);

    return this;
  }
Beispiel #19
0
  private boolean updateTextComponent(final boolean search) {
    JTextComponent oldComponent = search ? mySearchTextComponent : myReplaceTextComponent;
    Color oldBackground = oldComponent != null ? oldComponent.getBackground() : null;
    Wrapper wrapper = search ? mySearchFieldWrapper : myReplaceFieldWrapper;
    boolean multiline = myFindModel.isMultiline();
    if (multiline && oldComponent instanceof JTextArea) return false;
    if (!multiline && oldComponent instanceof JTextField) return false;

    final JTextComponent textComponent;
    if (multiline) {
      textComponent = new JTextArea();
      ((JTextArea) textComponent).setColumns(25);
      ((JTextArea) textComponent).setRows(2);
      wrapper.setContent(
          new SearchWrapper(textComponent, new ShowHistoryAction(textComponent, this)));
    } else {
      SearchTextField searchTextField = new SearchTextField(true);
      searchTextField.setOpaque(false);
      textComponent = searchTextField.getTextEditor();
      searchTextField.getTextEditor().setColumns(25);
      if (UIUtil.isUnderGTKLookAndFeel()) {
        textComponent.setOpaque(false);
      }
      setupHistoryToSearchField(
          searchTextField,
          search
              ? FindSettings.getInstance().getRecentFindStrings()
              : FindSettings.getInstance().getRecentReplaceStrings());
      textComponent.registerKeyboardAction(
          new ActionListener() {
            @Override
            public void actionPerformed(final ActionEvent e) {
              final String text = textComponent.getText();
              myFindModel.setMultiline(true);
              ApplicationManager.getApplication()
                  .invokeLater(
                      new Runnable() {
                        @Override
                        public void run() {
                          if (search) {
                            mySearchTextComponent.setText(text + "\n");
                          } else {
                            myReplaceTextComponent.setText(text + "\n");
                          }
                        }
                      });
            }
          },
          KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.ALT_DOWN_MASK),
          JComponent.WHEN_FOCUSED);
      wrapper.setContent(searchTextField);
    }

    if (search) {
      mySearchTextComponent = textComponent;
    } else {
      myReplaceTextComponent = textComponent;
    }

    UIUtil.addUndoRedoActions(textComponent);
    Utils.setSmallerFont(textComponent);

    textComponent.putClientProperty("AuxEditorComponent", Boolean.TRUE);
    if (oldBackground != null) {
      textComponent.setBackground(oldBackground);
    }
    textComponent.addFocusListener(
        new FocusListener() {
          @Override
          public void focusGained(final FocusEvent e) {
            textComponent.repaint();
          }

          @Override
          public void focusLost(final FocusEvent e) {
            textComponent.repaint();
          }
        });
    new CloseOnESCAction(this, textComponent);
    return true;
  }
  protected JComponent createSouthPanel() {
    JPanel panel = new JPanel(new BorderLayout());
    panel.setBorder(BorderFactory.createEmptyBorder(8, 0, 0, 0));

    JPanel buttonPanel = new JPanel();

    if (SystemInfo.isMac) {
      panel.add(buttonPanel, BorderLayout.EAST);
      buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));

      if (!UIUtil.isUnderDarcula()) {
        myHelpButton.putClientProperty("JButton.buttonType", "help");
      }
      if (UIUtil.isUnderAquaLookAndFeel()) {
        myHelpButton.setText("");
      }

      JPanel leftPanel = new JPanel();
      if (ApplicationInfo.contextHelpAvailable()) {
        leftPanel.add(myHelpButton);
      }
      leftPanel.add(myCancelButton);
      panel.add(leftPanel, BorderLayout.WEST);

      if (mySteps.size() > 1) {
        buttonPanel.add(Box.createHorizontalStrut(5));
        buttonPanel.add(myPreviousButton);
      }
      buttonPanel.add(Box.createHorizontalStrut(5));
      buttonPanel.add(myNextButton);
    } else {
      panel.add(buttonPanel, BorderLayout.CENTER);
      GroupLayout layout = new GroupLayout(buttonPanel);
      buttonPanel.setLayout(layout);
      layout.setAutoCreateGaps(true);

      final GroupLayout.SequentialGroup hGroup = layout.createSequentialGroup();
      final GroupLayout.ParallelGroup vGroup = layout.createParallelGroup();
      final Collection<Component> buttons = ContainerUtil.newArrayListWithExpectedSize(5);
      final boolean helpAvailable = ApplicationInfo.contextHelpAvailable();

      if (helpAvailable && UIUtil.isUnderGTKLookAndFeel()) {
        add(hGroup, vGroup, buttons, myHelpButton);
      }
      add(hGroup, vGroup, null, Box.createHorizontalGlue());
      if (mySteps.size() > 1) {
        add(hGroup, vGroup, buttons, myPreviousButton);
      }
      add(hGroup, vGroup, buttons, myNextButton, myCancelButton);
      if (helpAvailable && !UIUtil.isUnderGTKLookAndFeel()) {
        add(hGroup, vGroup, buttons, myHelpButton);
      }

      layout.setHorizontalGroup(hGroup);
      layout.setVerticalGroup(vGroup);
      layout.linkSize(buttons.toArray(new Component[buttons.size()]));
    }

    myPreviousButton.setEnabled(false);
    myPreviousButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(final ActionEvent e) {
            doPreviousAction();
          }
        });
    myNextButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(final ActionEvent e) {
            if (isLastStep()) {
              // Commit data of current step and perform OK action
              final Step currentStep = mySteps.get(myCurrentStep);
              LOG.assertTrue(currentStep != null);
              try {
                currentStep._commit(true);
                doOKAction();
              } catch (final CommitStepException exc) {
                String message = exc.getMessage();
                if (message != null) {
                  Messages.showErrorDialog(myContentPanel, message);
                }
              }
            } else {
              doNextAction();
            }
          }
        });

    myCancelButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(final ActionEvent e) {
            doCancelAction();
          }
        });
    myHelpButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(final ActionEvent e) {
            helpAction();
          }
        });

    return panel;
  }