com.salas.bb.search.ResultGroupPanel.java Source code

Java tutorial

Introduction

Here is the source code for com.salas.bb.search.ResultGroupPanel.java

Source

// 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);
        }
    }
}