/** * Copyright (C) 2001-2017 by RapidMiner and the contributors * * Complete list of developers available at our web site: * * http://rapidminer.com * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * This program 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 * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. * If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.gui.tools.components; import java.awt.Component; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.RenderingHints; import javax.swing.BorderFactory; import javax.swing.DefaultListCellRenderer; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JLayer; import javax.swing.JList; import javax.swing.SwingConstants; import javax.swing.plaf.LayerUI; import com.rapidminer.gui.look.Colors; import com.rapidminer.gui.tools.ListHoverHelper; /** * A cell renderer for lists containing {@link Card}s. * * @author Nils Woehler * */ public class CardCellRenderer extends DefaultListCellRenderer { private static final long serialVersionUID = 1L; protected static final int MAX_CAPTION_LENGTH = 13; private boolean selected = false; private boolean highlighted = false; private JLayer<JLabel> layer; private class CardLayerUI extends LayerUI<JLabel> { private static final long serialVersionUID = 1L; @Override public void paint(Graphics g, JComponent c) { Graphics2D g2 = (Graphics2D) g.create(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); Rectangle rec = getBounds(); g2.setColor(Colors.CARD_PANEL_BACKGROUND); g2.fillRect(rec.x, rec.y, rec.width - 1, rec.height); int w = (int) rec.getWidth(); int h = (int) rec.getHeight(); int x = (int) rec.getX(); int y = (int) rec.getY(); if (highlighted) { g2.setColor(Colors.CARD_PANEL_BACKGROUND_HIGHLIGHT); g2.fillRect(x, y, w, h); } if (selected) { g2.setColor(Colors.CARD_PANEL_BACKGROUND_SELECTED); g2.fillRect(x, y, w, h); } g2.dispose(); super.paint(g, c); } } /** * Creates a {@link CardCellRenderer} that is used by lists containing {@link Card}s. */ public CardCellRenderer() { setVerticalTextPosition(SwingConstants.BOTTOM); setHorizontalTextPosition(SwingConstants.CENTER); setHorizontalAlignment(CENTER); setOpaque(false); layer = new JLayer<>(this, new CardLayerUI()); } @Override public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) { JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); if (isSelected) { selected = true; label.setBorder(null); } else { selected = false; label.setBorder(BorderFactory.createEmptyBorder(8, 2, 8, 2)); } if (ListHoverHelper.index(list) == index) { highlighted = true; } else { highlighted = false; } Card card = (Card) value; String title = card.getTitle(); String caption = card.getFooter(); if (caption != null) { StringBuilder builder = new StringBuilder(); builder.append("<html>"); builder.append("<div style='text-align: center;width: 40px;'>"); builder.append("<div>"); builder.append(title); builder.append("</div>"); builder.append("<div style='font-size:x-small; font-style:italic;margin-top:3px;'>"); builder.append("("); if (caption.length() > MAX_CAPTION_LENGTH) { builder.append(getShortenedCaption(caption)); } else { builder.append(caption); } builder.append(")"); builder.append("</div>"); builder.append("</div>"); builder.append("</html>"); title = builder.toString(); } label.setText(title); label.setIcon(card.getIcon()); layer.setToolTipText(card.getTip()); return layer; } /** * @param caption * the full length caption * * @return a shortened caption that has at most {@link #MAX_CAPTION_LENGTH} characters. */ private Object getShortenedCaption(String caption) { // split caption by spaces String[] captionParts = caption.split(" "); int captionLength = 0; // start with the last part of the caption int index = captionParts.length - 1; // create shortened version of caption only if caption has been splitted into multiple // parts.. if (index != -1) { // add more splitted caption parts as long as string length is less than // MAX_CAPTION_LENGTH while (index >= 0 && captionLength < MAX_CAPTION_LENGTH) { captionLength += captionParts[index].length(); // increase length by one for all missing spaces except the last part if (index < captionParts.length - 1) { ++captionLength; } // only decrease index if caption is still short enough if (captionLength < MAX_CAPTION_LENGTH) { --index; } else { // else remove last added part ++index; } } // sanity checks if (index < 0) { ++index; } if (index == captionParts.length) { --index; } StringBuilder captionBuilder = new StringBuilder(); // build shortened caption string, starting from the calculated index for (int i = index; i < captionParts.length; ++i) { captionBuilder.append(captionParts[i]); // add spaces for all parts except the last one if (i < captionParts.length - 1) { captionBuilder.append(" "); } } // generate shortened caption from caption builder caption = captionBuilder.toString(); } // check once more if max caption length has not been violated if (caption.length() > MAX_CAPTION_LENGTH) { caption = caption.substring(caption.length() - MAX_CAPTION_LENGTH); } caption = "..." + caption; return caption; } }