/******************************************************************************* * Copyright (c) 2010 Stefan A. Tzeggai. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v2.1 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * * Contributors: * Stefan A. Tzeggai - initial API and implementation ******************************************************************************/ /* * $Id: BasicMapLayerLegendPaneUI.java 1133 2010-03-12 11:57:36Z alfonx $ * * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle, * Santa Clara, California 95054, U.S.A. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package org.geopublishing.atlasViewer.swing.plaf; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Insets; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.border.CompoundBorder; import javax.swing.event.MouseInputAdapter; import javax.swing.event.MouseInputListener; import javax.swing.plaf.ActionMapUIResource; import javax.swing.plaf.ColorUIResource; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.FontUIResource; import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicGraphicsUtils; import org.apache.log4j.Logger; import org.geopublishing.atlasViewer.GpCoreUtil; import org.geopublishing.atlasViewer.swing.AtlasMapLayerLegend; import org.geopublishing.atlasViewer.swing.Icons; import org.geopublishing.atlasViewer.swing.MapLayerLegend; import org.jdesktop.swingx.JXCollapsiblePane; import org.jdesktop.swingx.JXHyperlink; import org.jdesktop.swingx.JXTaskPane; import org.jdesktop.swingx.icon.EmptyIcon; import org.jdesktop.swingx.plaf.TaskPaneUI; /** * Base implementation of the <code>JXTaskPane</code> UI. * * @author Mostly <a href="mailto:fred@swingx.com">Frederic Lavigne</a> */ public class BasicMapLayerLegendPaneUI extends TaskPaneUI { private static final Color LAYER_HIDDEN_COLOR = Color.decode("#efefef"); static final Logger LOGGER = Logger .getLogger(BasicMapLayerLegendPaneUI.class); // TODO REDUCE STUPID CODE! public int controlEyeWidth; public int controlEyeX; public int controlEyeY; public int controlInfoWidth; public int controlInfoX; public int controlInfoY; public int controlToolWidth; public int controlToolX; public int controlToolY; public int controlExpandWidth; public int controlExpandX; public int controlExpandY; private static FocusListener focusListener = new RepaintOnFocus(); public static ComponentUI createUI(JComponent c) { return new BasicMapLayerLegendPaneUI(); } protected int titleHeight = 25; protected int roundHeight = 5; protected MapLayerLegend mapLayerLegend; protected boolean mouseOver; protected MouseInputListener mouseListener; protected PropertyChangeListener propertyListener; /** * {@inheritDoc} */ @Override public void installUI(JComponent c) { super.installUI(c); mapLayerLegend = (MapLayerLegend) c; installDefaults(); installListeners(); installKeyboardActions(); } /** * Installs default properties. Following properties are installed: * <ul> * <li>TaskPane.background</li> * <li>TaskPane.foreground</li> * <li>TaskPane.font</li> * <li>TaskPane.borderColor</li> * <li>TaskPane.titleForeground</li> * <li>TaskPane.titleBackgroundGradientStart</li> * <li>TaskPane.titleBackgroundGradientEnd</li> * <li>TaskPane.titleOver</li> * <li>TaskPane.specialTitleOver</li> * <li>TaskPane.specialTitleForeground</li> * <li>TaskPane.specialTitleBackground</li> * </ul> */ protected void installDefaults() { mapLayerLegend.setOpaque(true); mapLayerLegend.setBorder(createPaneBorder()); mapLayerLegend.setBorder(createPaneBorder()); ((JComponent) mapLayerLegend.getContentPane()) .setBorder(createContentPaneBorder()); LookAndFeel.installColorsAndFont(mapLayerLegend, "TaskPane.background", "TaskPane.foreground", "TaskPane.font"); LookAndFeel.installColorsAndFont( (JComponent) mapLayerLegend.getContentPane(), "TaskPane.background", "TaskPane.foreground", "TaskPane.font"); } /** * Installs listeners for UI delegate. */ protected void installListeners() { mouseListener = createMouseInputListener(); mapLayerLegend.addMouseMotionListener(mouseListener); mapLayerLegend.addMouseListener(mouseListener); mapLayerLegend.addFocusListener(focusListener); propertyListener = createPropertyListener(); mapLayerLegend.addPropertyChangeListener(propertyListener); } /** * Installs keyboard actions to allow task pane to react on hot keys. */ protected void installKeyboardActions() { InputMap inputMap = (InputMap) UIManager.get("TaskPane.focusInputMap"); if (inputMap != null) { SwingUtilities.replaceUIInputMap(mapLayerLegend, JComponent.WHEN_FOCUSED, inputMap); } ActionMap map = getActionMap(); if (map != null) { SwingUtilities.replaceUIActionMap(mapLayerLegend, map); } } ActionMap getActionMap() { ActionMap map = new ActionMapUIResource(); map.put("toggleExpanded", new ToggleExpandedAction()); return map; } @Override public void uninstallUI(JComponent c) { uninstallListeners(); super.uninstallUI(c); } /** * Uninstalls previously installed listeners to free component for garbage * collection. */ protected void uninstallListeners() { mapLayerLegend.removeMouseListener(mouseListener); mapLayerLegend.removeMouseMotionListener(mouseListener); mapLayerLegend.removeFocusListener(focusListener); mapLayerLegend.removePropertyChangeListener(propertyListener); } /** * Creates new toggle listener. * * @return MouseInputListener reacting on toggle events of task pane. */ protected MouseInputListener createMouseInputListener() { return new ToggleListener(); } /** * Creates property change listener for task pane. * * @return Property change listener reacting on changes to the task pane. */ protected PropertyChangeListener createPropertyListener() { return new ChangeListener(); } /** * Evaluates whenever given mouse even have occurred within borders of task * pane. * * @param event * Evaluated event. * @return True if event occurred within task pane area, false otherwise. */ protected boolean isInBorder(MouseEvent event) { return event.getY() < getTitleHeight(event.getComponent()); } /** * Gets current title height. Default value is 25. * * @return Current title height. * @deprecated. Use getTitleHeight(java.awt.Component) instead. Kept only * for compatibility reasons. Will be removed before 1.0 * release. */ protected int getTitleHeight() { return titleHeight; } /** * Gets current title height. Default value is 25 if not specified * otherwise. Method checks provided component for user set font * (!instanceof FontUIResource), if font is set, height will be calculated * from font metrics instead of using internal preset height. * * @return Current title height. */ protected int getTitleHeight(Component c) { if (c instanceof JXTaskPane) { JXTaskPane taskPane = (JXTaskPane) c; Font font = taskPane.getFont(); int height = titleHeight; if (font != null && !(font instanceof FontUIResource)) { height = taskPane.getFontMetrics(font).getHeight(); } Icon icon = taskPane.getIcon(); if (icon != null) { height = Math.max(height, icon.getIconHeight() + 4); } return height; } return titleHeight; } /** * Creates new border for task pane. * * @return Fresh border on every call. */ protected Border createPaneBorder() { return new PaneBorder(); } @Override public Dimension getPreferredSize(JComponent c) { Component component = mapLayerLegend.getComponent(0); if (!(component instanceof JXCollapsiblePane)) { // something wrong in this JXTaskPane return super.getPreferredSize(c); } JXCollapsiblePane collapsible = (JXCollapsiblePane) component; Dimension dim = collapsible.getPreferredSize(); Border groupBorder = mapLayerLegend.getBorder(); if (groupBorder instanceof PaneBorder) { Dimension border = ((PaneBorder) groupBorder) .getPreferredSize(mapLayerLegend); dim.width = Math.max(dim.width, border.width); dim.height += border.height; } else { dim.height += getTitleHeight(c); } return dim; } /** * Creates content pane border. * * @return Fresh content pane border initialized with current value of * TaskPane.borderColor on every call. */ protected Border createContentPaneBorder() { Color borderColor = UIManager.getColor("TaskPane.borderColor"); return new CompoundBorder(new ContentPaneBorder(borderColor), BorderFactory.createEmptyBorder(2, 1, 1, 6)); // return new CompoundBorder(new ContentPaneBorder(borderColor), // BorderFactory.createEmptyBorder(5, 7, 5, 7)); } @Override public Component createAction(Action action) { JXHyperlink link = new JXHyperlink(action) { @Override public void updateUI() { super.updateUI(); // ensure the ui of this link is correctly update on l&f changes configure(this); } }; configure(link); return link; } /** * Configures internally used hyperlink on new action creation and on every * call to <code>updateUI()</code>. * * @param link * Configured hyperlink. */ protected void configure(JXHyperlink link) { link.setOpaque(false); link.setBorder(null); link.setBorderPainted(false); link.setFocusPainted(true); link.setForeground(UIManager.getColor("TaskPane.titleForeground")); } /** * Ensures expanded group is visible. Issues delayed request for scrolling * to visible. */ protected void ensureVisible() { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { mapLayerLegend.scrollRectToVisible(new Rectangle(mapLayerLegend .getWidth(), mapLayerLegend.getHeight())); } }); } /** * Focus listener responsible for repainting of the taskpane on focus * change. */ static class RepaintOnFocus implements FocusListener { @Override public void focusGained(FocusEvent e) { e.getComponent().repaint(); } @Override public void focusLost(FocusEvent e) { e.getComponent().repaint(); } } /** * Change listener responsible for change handling. */ class ChangeListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent evt) { // if group is expanded but not animated // or if animated has reached expanded state // scroll to visible if scrollOnExpand is enabled // if // ((JXTaskPane.EXPANDED_CHANGED_KEY.equals(evt.getPropertyName()) // && Boolean.TRUE.equals(evt.getNewValue()) && !group // .isAnimated()) // || (JXCollapsiblePane.ANIMATION_STATE_KEY.equals(evt // .getPropertyName()) && "expanded".equals(evt // .getNewValue()))) { // if (group.isScrollOnExpand()) { // ensureVisible(); // } // } else if (JXTaskPane.ICON_CHANGED_KEY // .equals(evt.getPropertyName()) // || JXTaskPane.TITLE_CHANGED_KEY.equals(evt // .getPropertyName()) // || JXTaskPane.SPECIAL_CHANGED_KEY.equals(evt // .getPropertyName())) { // // icon, title, special must lead to a repaint() // group.repaint(); // } } } /** * Mouse listener responsible for handling of toggle events. */ class ToggleListener extends MouseInputAdapter { @Override public void mouseEntered(MouseEvent e) { if (isInBorder(e)) { e.getComponent().setCursor( Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); } else { mouseOver = false; mapLayerLegend.repaint(0, 0, mapLayerLegend.getWidth(), getTitleHeight(mapLayerLegend)); } } @Override public void mouseExited(MouseEvent e) { e.getComponent().setCursor(null); mouseOver = false; mapLayerLegend.repaint(0, 0, mapLayerLegend.getWidth(), getTitleHeight(mapLayerLegend)); } @Override public void mouseMoved(MouseEvent e) { if (isInBorder(e)) { e.getComponent().setCursor( Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); // ************************************************************** // Did we move over the eye? // ************************************************************** if (insideClick(e, controlEyeX, controlEyeY, controlEyeWidth, controlEyeWidth)) { mapLayerLegend.setToolTipText(GpCoreUtil .R("LayerBar.Icons.eye.tooltip")); mapLayerLegend.repaint(controlEyeX, controlEyeY, controlEyeWidth, controlEyeWidth); return; } else if (insideClick(e, controlToolX, controlToolY, controlToolWidth, controlToolWidth)) { mapLayerLegend.setToolTipText(GpCoreUtil .R("LayerBar.Icons.tool.tooltip")); mapLayerLegend.repaint(controlToolX, controlToolY, controlToolWidth, controlToolWidth); return; } else if (((mapLayerLegend).getInfoURL() != null) && insideClick(e, controlInfoX, controlInfoY, controlInfoWidth, controlInfoWidth)) { mapLayerLegend.setToolTipText(GpCoreUtil .R("LayerBar.Icons.info.tooltip")); mapLayerLegend.repaint(controlInfoX, controlInfoY, controlInfoWidth, controlInfoWidth); return; } else { mapLayerLegend.setToolTipText("<html>" + mapLayerLegend.getLegendTooltip() + "</html>"); } mouseOver = true; } else { e.getComponent().setCursor(null); mouseOver = false; } mapLayerLegend.repaint(0, 0, mapLayerLegend.getWidth(), getTitleHeight(mapLayerLegend)); } /** * One click will toggle exand state Doubleclick undoes the previous * signaled expand toggle and zooms to layer boundaries */ @Override public void mouseClicked(MouseEvent evt) { processMouseClickedEvent(evt); } } /** * Check if the {@link MouseEvent} happened inside a region * * @param evt * {@link MouseEvent} * @return inside? * * @author <a href="mailto:skpublic@wikisquare.de">Stefan Alfons Tzeggai</a> */ private boolean insideClick(MouseEvent evt, int x, int y, int w, int h) { int xx = evt.getPoint().x; int yy = evt.getPoint().y; if ((xx <= x + w) && (xx >= x) && (yy >= y) && (yy <= y + h)) { return true; } return false; } public void processMouseClickedEvent(MouseEvent evt) { // ********************************************************************** // The right button shall open the tools menu // ********************************************************************** if (evt.getButton() == MouseEvent.BUTTON3) { mapLayerLegend.getToolMenu().show(mapLayerLegend, controlToolX, controlToolY + controlToolWidth); return; } if (evt.getClickCount() == 1) { // Single-click always // ****************************************************************** // Did we hit him on the eye? // ****************************************************************** if (insideClick(evt, controlEyeX, controlEyeY, controlEyeWidth, controlEyeWidth)) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { mapLayerLegend.setCollapsed(!mapLayerLegend .toggleVisibility()); } }); mapLayerLegend.repaint(controlEyeX, controlEyeY, controlEyeWidth, controlEyeWidth); return; } // ****************************************************************** // Did we hit him on the INFO icon? // ****************************************************************** if (mapLayerLegend.getInfoURL() != null) { if (insideClick(evt, controlInfoX, controlInfoY, controlInfoWidth, controlInfoWidth)) { mapLayerLegend.clickedInfoButton(); mapLayerLegend.repaint(controlInfoX, controlInfoY, controlInfoWidth, controlInfoWidth); return; } } // ****************************************************************** // Did we hit the Tool icon ? // ****************************************************************** if (insideClick(evt, controlToolX, controlToolY, controlToolWidth, controlToolWidth)) { mapLayerLegend.getToolMenu().show(mapLayerLegend, controlToolX, controlToolY + controlToolWidth); return; } // ****************************************************************** // Did we hit the Expand icon ? // ****************************************************************** if (insideClick(evt, controlExpandX, controlExpandY, controlExpandWidth, controlExpandWidth)) { boolean bbb = mapLayerLegend.isCollapsed(); mapLayerLegend.setCollapsed(!bbb); if (mapLayerLegend instanceof AtlasMapLayerLegend) { /** * We have to catch changes to the "Expand-State", because * in the GP we save this state and restore it in the AV. */ AtlasMapLayerLegend alpg = (AtlasMapLayerLegend) mapLayerLegend; alpg.setMinimized(!bbb); alpg.getAtlasMapLegend().recreateLayerList( alpg.getMapLayer()); } return; } } else if (evt.getClickCount() == 2) { // Double-click // ****************************************************************** // No action when double-click on the buttons, otherwise // zoom to layer // ****************************************************************** if (insideClick(evt, controlExpandX, controlExpandY, controlExpandWidth, controlExpandWidth)) { return; } if (insideClick(evt, controlEyeX, controlEyeY, controlEyeWidth, controlEyeWidth)) { return; } if (insideClick(evt, controlToolX, controlToolY, controlToolWidth, controlToolWidth)) { return; } if (insideClick(evt, controlInfoX, controlInfoY, controlInfoWidth, controlInfoWidth)) { return; } // Zoom to layer SwingUtilities.invokeLater(new Runnable() { @Override public void run() { (mapLayerLegend).zoomTo(); if (!(mapLayerLegend).isLayerVisible()) { mapLayerLegend.setCollapsed(!(mapLayerLegend) .toggleVisibility()); } if (mapLayerLegend.isCollapsed()) mapLayerLegend.setCollapsed(false); } }); } } /** * Toggle expanded action. */ class ToggleExpandedAction extends AbstractAction { /** * Serial version UID. */ private static final long serialVersionUID = 5676859881615358815L; public ToggleExpandedAction() { super("toggleExpanded"); } @Override public void actionPerformed(ActionEvent e) { mapLayerLegend.setCollapsed(!mapLayerLegend.isCollapsed()); } @Override public boolean isEnabled() { return mapLayerLegend.isVisible(); } } /** * Toggle icon. */ protected static class ChevronIcon implements Icon { boolean up = true; public ChevronIcon(boolean up) { this.up = up; } @Override public int getIconHeight() { return 3; } @Override public int getIconWidth() { return 6; } @Override public void paintIcon(Component c, Graphics g, int x, int y) { if (up) { g.drawLine(x + 3, y, x, y + 3); g.drawLine(x + 3, y, x + 6, y + 3); } else { g.drawLine(x, y, x + 3, y + 3); g.drawLine(x + 3, y + 3, x + 6, y); } } } /** * The border around the content pane */ protected static class ContentPaneBorder implements Border, UIResource { Color color; public ContentPaneBorder(Color color) { this.color = color; } @Override public Insets getBorderInsets(Component c) { return new Insets(0, 1, 1, 1); } @Override public boolean isBorderOpaque() { return true; } @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { g.setColor(color); g.drawLine(x, y, x, y + height - 1); g.drawLine(x, y + height - 1, x + width - 1, y + height - 1); g.drawLine(x + width - 1, y, x + width - 1, y + height - 1); } } /** * The border of the taskpane group paints the "text", the "icon", the * "expanded" status and the "special" type. * */ protected class PaneBorder implements Border, UIResource { protected Color borderColor; protected Color titleForeground; protected Color specialTitleBackground; protected Color specialTitleForeground; protected Color titleBackgroundGradientStart; protected Color titleBackgroundGradientEnd; protected Color titleOver; protected Color specialTitleOver; protected JLabel label; /** * Creates new instance of individual pane border. */ public PaneBorder() { borderColor = UIManager.getColor("TaskPane.borderColor"); titleForeground = UIManager.getColor("TaskPane.titleForeground"); specialTitleBackground = UIManager .getColor("TaskPane.specialTitleBackground"); specialTitleForeground = UIManager .getColor("TaskPane.specialTitleForeground"); titleBackgroundGradientStart = UIManager .getColor("TaskPane.titleBackgroundGradientStart"); titleBackgroundGradientEnd = UIManager .getColor("TaskPane.titleBackgroundGradientEnd"); titleOver = UIManager.getColor("TaskPane.titleOver"); if (titleOver == null) { titleOver = specialTitleBackground.brighter(); } specialTitleOver = UIManager.getColor("TaskPane.specialTitleOver"); if (specialTitleOver == null) { specialTitleOver = specialTitleBackground.brighter(); } label = new JLabel(); label.setOpaque(false); label.setIconTextGap(8); } @Override public Insets getBorderInsets(Component c) { return new Insets(getTitleHeight(c), 0, 0, 0); } /** * Overwritten to always return <code>true</code> to speed up painting. * Don't use transparent borders unless providing UI delegate that * provides proper return value when calling this method. * * @see javax.swing.border.Border#isBorderOpaque() */ @Override public boolean isBorderOpaque() { return true; } /** * Calculates the preferred border size, its size so all its content * fits. * * @param group * Selected group. */ public Dimension getPreferredSize(JXTaskPane group) { // calculate the title width so it is fully visible // it starts with the title width configureLabel(group); Dimension dim = label.getPreferredSize(); // add the title left offset dim.width += 3; // add the controls width dim.width += getTitleHeight(group); // and some space between label and controls dim.width += 3; dim.height = getTitleHeight(group); return dim; } /** * Paints background of the title. This may differ based on properties * of the group. * * @param layerLegend * Selected layer. * @param g * Target graphics. */ protected void paintTitleBackground(MapLayerLegend layerLegend, Graphics g) { if (layerLegend.isSpecial()) { g.setColor(specialTitleBackground); } else { g.setColor(titleBackgroundGradientStart); } if (layerLegend instanceof AtlasMapLayerLegend) { AtlasMapLayerLegend atlasLayerLegend = (AtlasMapLayerLegend) layerLegend; if (atlasLayerLegend.isHiddenInLegend()) { g.setColor(LAYER_HIDDEN_COLOR); } } g.fillRect(0, 0, layerLegend.getWidth(), getTitleHeight(layerLegend) - 1); } /** * Paints current group title. * * @param group * Selected group. * @param g * Target graphics. * @param textColor * Title color. * @param x * X coordinate of the top left corner. * @param y * Y coordinate of the top left corner. * @param width * Width of the box. * @param height * Height of the box. */ protected void paintTitle(JXTaskPane group, Graphics g, Color textColor, int x, int y, int width, int height) { configureLabel(group); label.setForeground(textColor); if (group.getFont() != null && !(group.getFont() instanceof FontUIResource)) { label.setFont(group.getFont()); } /** * Here we make the title shorter to leave room for the new buttons */ int buttonAnz = 3; if (((MapLayerLegend) group).getInfoURL() == null) buttonAnz--; label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, buttonAnz * controlToolWidth + 7)); g.translate(x, y); label.setBounds(0, 0, width, height); label.paint(g); g.translate(-x, -y); } /** * Configures label for the group using its title, font, icon and * orientation. * * @param group * Selected group. */ protected void configureLabel(JXTaskPane group) { label.applyComponentOrientation(group.getComponentOrientation()); label.setFont(group.getFont()); label.setText(group.getTitle()); label.setIcon(group.getIcon() == null ? new EmptyIcon() : group .getIcon()); } /** * Paints expanded controls. Default implementation does nothing. * * @param group * Expanded group. * @param g * Target graphics. * @param x * X coordinate of the top left corner. * @param y * Y coordinate of the top left corner. * @param width * Width of the box. * @param height * Height of the box. */ protected void paintExpandedControls(JXTaskPane group, Graphics g, int x, int y, int width, int height) { } /** * Gets current paint color. * * @param mapLayerLegend * Selected MapLayerLegend. * @return Color to be used for painting provided group. */ protected Color getPaintColor(JXTaskPane mapLayerLegend) { Color paintColor; if (isMouseOverBorder()) { if (mouseOver) { if (mapLayerLegend.isSpecial()) { paintColor = Color.red; } else { paintColor = Color.red; } } else { if (mapLayerLegend.isSpecial()) { paintColor = specialTitleForeground; } else { paintColor = mapLayerLegend.getForeground() == null || mapLayerLegend.getForeground() instanceof ColorUIResource ? titleForeground : mapLayerLegend.getForeground(); } } } else { if (mapLayerLegend.isSpecial()) { paintColor = specialTitleForeground; } else { paintColor = mapLayerLegend.getForeground() == null || mapLayerLegend.getForeground() instanceof ColorUIResource ? titleForeground : mapLayerLegend.getForeground(); } } return paintColor; } /* * @see javax.swing.border.Border#paintBorder(java.awt.Component, * java.awt.Graphics, int, int, int, int) */ @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { MapLayerLegend layerLegend = (MapLayerLegend) c; // calculate position of title and toggle controls controlExpandWidth = getTitleHeight(layerLegend) - 2 * getRoundHeight(); controlExpandX = layerLegend.getWidth() - getTitleHeight(layerLegend); controlExpandY = getRoundHeight() - 1; controlEyeWidth = controlInfoWidth = controlToolWidth = controlExpandWidth; controlExpandY = controlEyeY = controlInfoY = controlToolY = getRoundHeight() - 1; controlExpandX = layerLegend.getWidth() - getTitleHeight(); controlToolX = controlExpandX - (controlExpandWidth + 2) - 1; controlEyeX = controlToolX - (controlExpandWidth + 2) - 1; controlInfoX = controlEyeX - (controlExpandWidth + 2) - 1; int titleX = 3; int titleY = 0; int titleWidth = layerLegend.getWidth() - getTitleHeight(layerLegend) - 3; int titleHeight = getTitleHeight(layerLegend); if (!layerLegend.getComponentOrientation().isLeftToRight()) { controlExpandX = layerLegend.getWidth() - controlExpandX - controlExpandWidth; titleX = layerLegend.getWidth() - titleX - titleWidth; } // paint the title background paintTitleBackground(layerLegend, g); // paint the the toggles paintExpandedControls(layerLegend, g, controlExpandX, controlExpandY, controlExpandWidth, controlExpandWidth); paintEyeControls(layerLegend, g, controlEyeX, controlEyeY, controlEyeWidth, controlEyeWidth); if (layerLegend.getInfoURL() != null) { Icons.ICON_INFO.paintIcon(layerLegend, g, controlInfoX, controlInfoY); } paintToolControls(layerLegend, g, controlToolX, controlToolY, controlToolWidth, controlToolWidth); // paint the title text and icon Color paintColor = getPaintColor(layerLegend); // focus painted same color as text if (layerLegend.hasFocus()) { paintFocus(g, paintColor, 3, 3, width - 6, getTitleHeight(layerLegend) - 6); } paintTitle(layerLegend, g, paintColor, titleX, titleY, titleWidth, titleHeight); } /** * @author <a href="mailto:skpublic@wikisquare.de">Stefan Alfons * Tzeggai</a> */ public void paintToolControls(JXTaskPane group, Graphics g, int x, int y, int width, int height) { Icons.ICON_TOOL.paintIcon(group, g, x, y); } /** * Paint the the Eye in oen of three states: full visible, half * transparent, not visible * * @author <a href="mailto:skpublic@wikisquare.de">Stefan Alfons * Tzeggai</a> */ public void paintEyeControls(MapLayerLegend mapLayerLegend, Graphics g, int x, int y, int width, int height) { ImageIcon icon = null; if (mapLayerLegend.isLayerVisible()) { if (mapLayerLegend.isTransparent()) icon = Icons.ICON_HALFVISIBLE; else icon = Icons.ICON_VISIBLE; icon.paintIcon(mapLayerLegend, g, x, y); /** * Paint a filter symbol above if the layer is filtered */ if (mapLayerLegend.isFiltered()) { Icons.ICON_FILTER .paintIcon(mapLayerLegend, g, x + 3, y - 2); } } else { Icons.ICON_NOTVISIBLE.paintIcon(mapLayerLegend, g, x, y); } } /** * Paints oval 'border' area around the control itself. * * @param group * Expanded group. * @param g * Target graphics. * @param x * X coordinate of the top left corner. * @param y * Y coordinate of the top left corner. * @param width * Width of the box. * @param height * Height of the box. */ protected void paintRectAroundControls(JXTaskPane group, Graphics g, int x, int y, int width, int height, Color highColor, Color lowColor) { if (mouseOver) { int x2 = x + width; int y2 = y + height; g.setColor(highColor); g.drawLine(x, y, x2, y); g.drawLine(x, y, x, y2); g.setColor(lowColor); g.drawLine(x2, y, x2, y2); g.drawLine(x, y2, x2, y2); } } /** * Paints oval 'border' area around the control itself. * * @param group * Expanded group. * @param g * Target graphics. * @param x * X coordinate of the top left corner. * @param y * Y coordinate of the top left corner. * @param width * Width of the box. * @param height * Height of the box. */ protected void paintOvalAroundControls(JXTaskPane group, Graphics g, int x, int y, int width, int height) { if (group.isSpecial()) { g.setColor(specialTitleBackground.brighter()); g.drawOval(x, y, width, height); } else { g.setColor(titleBackgroundGradientStart); g.fillOval(x, y, width, height); g.setColor(titleBackgroundGradientEnd.darker()); g.drawOval(x, y, width, width); } } /** * Paints controls for the group. * * @param group * Expanded group. * @param g * Target graphics. * @param x * X coordinate of the top left corner. * @param y * Y coordinate of the top left corner. * @param width * Width of the box. * @param height * Height of the box. */ protected void paintChevronControls(JXTaskPane group, Graphics g, int x, int y, int width, int height) { ChevronIcon chevron; if (group.isCollapsed()) { chevron = new ChevronIcon(false); } else { chevron = new ChevronIcon(true); } int chevronX = x + width / 2 - chevron.getIconWidth() / 2; int chevronY = y + (height / 2 - chevron.getIconHeight()); chevron.paintIcon(group, g, chevronX, chevronY); chevron.paintIcon(group, g, chevronX, chevronY + chevron.getIconHeight() + 1); } /** * Paints focused group. * * @param g * Target graphics. * @param paintColor * Focused group color. * @param x * X coordinate of the top left corner. * @param y * Y coordinate of the top left corner. * @param width * Width of the box. * @param height * Height of the box. */ protected void paintFocus(Graphics g, Color paintColor, int x, int y, int width, int height) { g.setColor(paintColor); BasicGraphicsUtils.drawDashedRect(g, x, y, width, height); } /** * Default implementation returns false. * * @return true if this border wants to display things differently when * the mouse is over it */ protected boolean isMouseOverBorder() { return false; } } /** * Gets size of arc used to round corners. * * @return size of arc used to round corners of the panel. */ protected int getRoundHeight() { return roundHeight; } }