/* * Copyright 2000-2013 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 com.intellij.ide.ui.laf.darcula.ui; import com.intellij.ide.ui.laf.darcula.DarculaUIUtil; import com.intellij.openapi.ui.GraphicsConfig; import com.intellij.openapi.util.IconLoader; import com.intellij.ui.Gray; import com.intellij.util.ui.JBUI; import javax.swing.*; import javax.swing.border.Border; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicTextFieldUI; import javax.swing.text.JTextComponent; import java.awt.*; import java.awt.event.*; /** * @author Konstantin Bulenkov */ public class DarculaTextFieldUI extends BasicTextFieldUI { private static final Icon SEARCH_ICON = IconLoader.findIcon("/com/intellij/ide/ui/laf/icons/search.png"); private static final Icon SEARCH_WITH_HISTORY_ICON = IconLoader.findIcon("/com/intellij/ide/ui/laf/icons/searchWithHistory.png"); private static final Icon CLEAR_ICON = IconLoader.findIcon("/com/intellij/ide/ui/laf/icons/clear.png"); private enum SearchAction {POPUP, CLEAR} private final JTextField myTextField; protected JLabel myClearIcon; protected JLabel myRecentIcon; public DarculaTextFieldUI(JTextField textField) { myTextField = textField; } @SuppressWarnings("MethodOverridesStaticMethodOfSuperclass") public static ComponentUI createUI(final JComponent c) { final DarculaTextFieldUI ui = new DarculaTextFieldUI((JTextField)c); c.addFocusListener(new FocusAdapter() { @Override public void focusGained(FocusEvent e) { c.repaint(); } @Override public void focusLost(FocusEvent e) { c.repaint(); } }); c.addMouseMotionListener(new MouseMotionAdapter() { @Override public void mouseMoved(MouseEvent e) { if (ui.getComponent() != null && isSearchField(c)) { if (ui.getActionUnder(e) != null) { c.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); } else { c.setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); } } } }); c.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (isSearchField(c)) { final SearchAction action = ui.getActionUnder(e); if (action != null) { switch (action) { case POPUP: ui.showSearchPopup(); break; case CLEAR: ((JTextField)c).setText(""); break; } e.consume(); } } } }); return ui; } protected void showSearchPopup() { final Object value = getComponent().getClientProperty("JTextField.Search.FindPopup"); if (value instanceof JPopupMenu) { final JPopupMenu popup = (JPopupMenu)value; popup.show(getComponent(), getSearchIconCoord().x, getComponent().getHeight()); } } private SearchAction getActionUnder(MouseEvent e) { final Point cPoint = getClearIconCoord(); final Point sPoint = getSearchIconCoord(); cPoint.x += 8; cPoint.y += 8; sPoint.x += 8; sPoint.y += 8; final Point ePoint = e.getPoint(); return cPoint.distance(ePoint) <= 8 ? SearchAction.CLEAR : sPoint.distance(ePoint) <= 8 ? SearchAction.POPUP : null; } protected Rectangle getDrawingRect() { final JTextComponent c = myTextField; final Insets i = c.getInsets(); final int x = i.right - JBUI.scale(4) - JBUI.scale(16); final int y = i.top - JBUI.scale(3); final int w = c.getWidth() - (i.right + i.left) + JBUI.scale(16 * 2) + JBUI.scale(7 * 2) - JBUI.scale(5); int h = c.getBounds().height - (i.top + i.bottom) + JBUI.scale(4 * 2) - JBUI.scale(3); if (h % 2 == 1) h += JBUI.scale(1); return new Rectangle(x, y, w, h); } protected Point getSearchIconCoord() { final Rectangle r = getDrawingRect(); return new Point(r.x + JBUI.scale(3), r.y + (r.height - JBUI.scale(16)) / 2 + JBUI.scale(1)); } protected Point getClearIconCoord() { final Rectangle r = getDrawingRect(); return new Point(r.x + r.width - JBUI.scale(16 - 1), r.y + (r.height - JBUI.scale(16)) / 2); } @Override protected void paintBackground(Graphics graphics) { Graphics2D g = (Graphics2D)graphics; final JTextComponent c = getComponent(); final Container parent = c.getParent(); final Rectangle r = getDrawingRect(); if (c.isOpaque() && parent != null) { g.setColor(parent.getBackground()); g.fillRect(0, 0, c.getWidth(), c.getHeight()); } final GraphicsConfig config = new GraphicsConfig(g); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); final Border border = c.getBorder(); if (isSearchField(c)) { g.setColor(c.getBackground()); int radius = r.height - JBUI.scale(1); g.fillRoundRect(r.x, r.y, r.width, r.height - JBUI.scale(1), radius, radius); g.setColor(c.isEnabled() ? Gray._100 : new Color(0x535353)); if (c.hasFocus() && c.getClientProperty("JTextField.Search.noFocusRing") != Boolean.TRUE) { DarculaUIUtil.paintSearchFocusRing(g, r, c); } else { g.drawRoundRect(r.x, r.y, r.width, r.height - 1, radius, radius); } Point p = getSearchIconCoord(); Icon searchIcon = getComponent().getClientProperty("JTextField.Search.FindPopup") instanceof JPopupMenu ? SEARCH_WITH_HISTORY_ICON : SEARCH_ICON; searchIcon.paintIcon(null, g, p.x, p.y); if (getComponent().hasFocus() && getComponent().getText().length() > 0) { p = getClearIconCoord(); CLEAR_ICON.paintIcon(null, g, p.x, p.y); } } else if (border instanceof DarculaTextBorder) { if (c.isEnabled() && c.isEditable()) { g.setColor(c.getBackground()); } final int width = c.getWidth(); final int height = c.getHeight(); final Insets i = border.getBorderInsets(c); if (c.hasFocus()) { g.fillRoundRect(i.left - JBUI.scale(5), i.top - JBUI.scale(2), width - i.right - i.left + JBUI.scale(10), height - i.top - i.bottom + JBUI.scale(6), JBUI.scale(5), JBUI.scale(5)); } else { g.fillRect(i.left - JBUI.scale(5), i.top - JBUI.scale(2), width - i.right - i.left + JBUI.scale(12), height - i.top - i.bottom + 6); } } else { super.paintBackground(g); } config.restore(); } @Override protected void paintSafely(Graphics g) { paintBackground(g); super.paintSafely(g); } public static boolean isSearchField(Component c) { return c instanceof JTextField && "search".equals(((JTextField)c).getClientProperty("JTextField.variant")); } public static boolean isSearchFieldWithHistoryPopup(Component c) { return isSearchField(c) && ((JTextField)c).getClientProperty("JTextField.Search.FindPopup") instanceof JPopupMenu; } }