Java tutorial
// BlogBridge -- RSS feed reader, manager, and web based service // Copyright (C) 2002-2007 by R. Pito Salas // // This program is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free Software Foundation; // either version 2 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 General Public License for more details. // // You should have received a copy of the GNU General Public License along with this program; // if not, write to the Free Software Foundation, Inc., 59 Temple Place, // Suite 330, Boston, MA 02111-1307 USA // // Contact: R. Pito Salas // mailto:pitosalas@users.sourceforge.net // More information: about BlogBridge // http://www.blogbridge.com // http://sourceforge.net/projects/blogbridge // // $Id: ResultGroupPanel.java,v 1.8 2007/06/27 09:49:19 spyromus Exp $ // package com.salas.bb.search; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; import com.salas.bb.utils.i18n.Strings; import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * The header of items group. */ public class ResultGroupPanel extends JPanel { private final MoreItem moreItem; private final List<ResultItemPanel> items = new ArrayList<ResultItemPanel>(); private final JLabel lbCount; private boolean collapsed; private int itemLimit = 2; private long limitTime; private JLabel lbTitle; private Color backgroundColor1; private Color backgroundColor2; /** * Creates group item. * * @param name name. */ public ResultGroupPanel(String name) { this(name, null, Color.decode("#6b9eee"), Color.decode("#488bf4")); } /** * Creates group item. * * @param name name. * @param tooltip tooltip. * @param color1 first background color. * @param color2 second background color. */ public ResultGroupPanel(String name, String tooltip, Color color1, Color color2) { backgroundColor1 = color1; backgroundColor2 = color2; moreItem = new MoreItem(); lbCount = new JLabel("0"); setLayout(new FormLayout("5px, 10px, 5px, 50px:grow, 5px, 30px, 5px", "2px, p, 2px")); CellConstraints cc = new CellConstraints(); GroupCollapseIcon icon = new GroupCollapseIcon(); icon.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); add(icon, cc.xy(2, 2)); Font fnt = new Font("Lucida Grande", Font.BOLD, 12); lbTitle = new JLabel(name); lbTitle.setFont(fnt); lbTitle.setForeground(Color.WHITE); lbCount.setFont(fnt); lbCount.setForeground(Color.WHITE); lbCount.setAlignmentX(0.5f); add(lbTitle, cc.xy(4, 2)); add(lbCount, cc.xy(6, 2)); setBackground(backgroundColor1); if (tooltip != null) setToolTipText(tooltip); } /** * Paints background and children. * * @param g context. */ public void paint(Graphics g) { // Paint background int width = getSize().width; int height = getSize().height; Graphics2D g2 = (Graphics2D) g; Paint storedPaint = g2.getPaint(); g2.setPaint(new GradientPaint(0, 0, backgroundColor1, 0, height, backgroundColor2)); g2.fillRect(0, 0, width, height); g2.setPaint(storedPaint); paintChildren(g); } /** * Sets the limit. * * @param aItemLimit limit. */ public void setItemLimit(int aItemLimit) { itemLimit = aItemLimit; int hidden = 0; for (int i = 0; i < items.size(); i++) { ResultItemPanel item = items.get(i); item.setVisibility(i < itemLimit); if (i >= itemLimit) hidden++; } moreItem.setCount(hidden); } /** * Registers item within the group. * * @param item item. * * @return index within the group. */ public int register(ResultItemPanel item) { int visibleItemsCount = getVisibleItemsCount(); boolean priority = item.getItem().isPriority(); int index = priority ? 0 : items.size(); items.add(index, item); boolean filtered = isFiltered(item); item.setFiltered(filtered); if (!filtered) recalcView(); if (visibleItemsCount == 0) setVisible(true); return index; } /** * Recalculates the view. */ private void recalcView() { int more = 0; int visible = 0; for (ResultItemPanel itm : items) { if (itm.isFiltered()) { itm.setVisibility(false); } else if (visible >= itemLimit) { itm.setVisibility(false); more++; } else { itm.setVisibility(true); visible++; } } moreItem.setCount(more); lbCount.setText(Integer.toString(visible + more)); } /** * Collapses / expands the group. * * @param col <code>TRUE</code> to collapse. */ public void setCollapsed(boolean col) { collapsed = col; for (ResultItemPanel item : items) item.setCollapsed(col); moreItem.updateVisibility(); } /** * Returns more-component. * * @return component. */ public JComponent getMoreComponent() { return moreItem; } /** * Returns the number of items potentially visible to the client. * * @return items. */ private int getVisibleItemsCount() { int cnt = 0; for (ResultItemPanel item : items) if (item.isVisibility() && !item.isFiltered()) cnt++; return cnt; } /** * Invoked when the user asks for more items. */ private void onShowMore() { for (ResultItemPanel item : items) item.setVisibility(true); moreItem.setCount(0); } /** * Sets filtering time. If the time is set to <code>-1</code> then filtering is off. * Otherwise it shows the time after which all items are allowed. * * @param aLimitTime the time used for limiting. */ public void setLimitTime(long aLimitTime) { limitTime = aLimitTime; int shown = 0; int hidden = 0; for (ResultItemPanel item : items) { item.setFiltered(isFiltered(item)); item.setVisibility(!item.isFiltered() && shown < itemLimit); if (item.isVisible()) shown++; else if (!item.isFiltered()) hidden++; } setVisible(shown > 0); moreItem.setCount(hidden); } /** * Returns <code>TRUE</code> if the item should be filtered out. * * @param aItem item to check. * * @return <code>TRUE</code> if the item should be filtered out. */ private boolean isFiltered(ResultItemPanel aItem) { if (limitTime == -1L) return false; Date date = aItem.getItem().getDate(); return date == null || date.getTime() <= limitTime; } /** * Removes the panel of the item from the group. * * @param item item to remove the panel of. * * @return panel removed or <code>NULL</code> if not found. */ public ResultItemPanel removeItemPanelFor(ResultItem item) { for (ResultItemPanel panel : items) { if (item == panel.getItem()) { // Panel found items.remove(panel); recalcView(); return panel; } } return null; } /** * Removes all items from the given container. * * @param container container. */ public void removeAllItemsFrom(Container container) { for (ResultItemPanel item : items) container.remove(item); } /** * Updates the title of the group. * * @param title new title. */ public void setTitle(String title) { lbTitle.setText(title); } /** More ... item component. */ private class MoreItem extends JPanel { private final JLabel lbMore; private int count; public MoreItem() { setBorder(new ResultItemBorder(Color.decode("#f7f7f7"))); setBackground(Color.decode("#fafafa")); Font font = getFont().deriveFont(10f); setLayout(new FormLayout("41px, p, 5px", "2px, p, 2px")); CellConstraints cc = new CellConstraints(); lbMore = new JLabel(); lbMore.setFont(font); lbMore.setForeground(Color.decode("#567fca")); lbMore.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); add(lbMore, cc.xy(2, 2)); setCount(0); enableEvents(AWTEvent.MOUSE_EVENT_MASK); } /** * Processes clicks. * * @param e event. */ protected void processMouseEvent(MouseEvent e) { if (e.getID() == MouseEvent.MOUSE_PRESSED) onShowMore(); } /** * Sets counter and shows/hides label. * * @param cnt counter. */ public void setCount(int cnt) { count = cnt; lbMore.setText(MessageFormat.format(Strings.message("search.0.more"), Integer.toString(count))); updateVisibility(); } /** * Updates visibility state. */ private void updateVisibility() { setVisible(count > 0 && !collapsed); } } /** * Collapse / expand icon. */ public static class GroupCollapseIcon extends JComponent { private boolean collapsed; /** Creates icon. */ public GroupCollapseIcon() { Dimension size = new Dimension(9, 9); setMinimumSize(size); setPreferredSize(size); setMaximumSize(size); enableEvents(AWTEvent.MOUSE_EVENT_MASK); } /** * Mouse event processor. * * @param e event. */ protected void processMouseEvent(MouseEvent e) { if (e.getID() == MouseEvent.MOUSE_PRESSED && SwingUtilities.isLeftMouseButton(e)) { setCollapsed(!collapsed); ResultGroupPanel group = (ResultGroupPanel) getParent(); group.setCollapsed(collapsed); } } /** * Collapses / expands icon. * * @param aCollapsed new state. */ public void setCollapsed(boolean aCollapsed) { collapsed = aCollapsed; repaint(); } /** * Paints the icon. * * @param g context. */ public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; g.setColor(Color.WHITE); Object aaval = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); if (collapsed) { int arrowX = 1; int arrowY = 0; g.fillPolygon(new int[] { arrowX, arrowX + 7, arrowX }, new int[] { arrowY, arrowY + 4, arrowY + 9 }, 3); } else { int arrowX = 0; int arrowY = 1; g.fillPolygon(new int[] { arrowX, arrowX + 4, arrowX + 9 }, new int[] { arrowY, arrowY + 7, arrowY }, 3); } g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, aaval); } } }