net.sf.housekeeper.swing.item.ItemsView.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.housekeeper.swing.item.ItemsView.java

Source

/*
 * This file is part of Housekeeper.
 * 
 * Housekeeper 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.
 * 
 * Housekeeper 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
 * Housekeeper; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 * 
 * Copyright 2003-2004, The Housekeeper Project
 * http://housekeeper.berlios.de
 */

package net.sf.housekeeper.swing.item;

import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import net.sf.housekeeper.domain.Category;
import net.sf.housekeeper.domain.ExpirableItem;
import net.sf.housekeeper.domain.Item;
import net.sf.housekeeper.domain.ItemDAO;
import net.sf.housekeeper.event.HousekeeperEvent;
import net.sf.housekeeper.swing.util.SortableTable;

import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.richclient.application.PageComponentContext;
import org.springframework.richclient.application.support.AbstractView;
import org.springframework.richclient.command.CommandGroup;
import org.springframework.richclient.command.support.AbstractActionCommandExecutor;
import org.springframework.richclient.command.support.GlobalCommandIds;
import org.springframework.richclient.dialog.TitledPageApplicationDialog;
import org.springframework.richclient.form.Form;
import org.springframework.richclient.util.PopupMenuMouseListener;
import org.springframework.util.Assert;

/**
 * A customizable view for any type of {@link net.sf.housekeeper.domain.Item}s.
 * 
 * @author Adrian Gygax
 * @version $Revision$, $Date$
 */
public class ItemsView extends AbstractView implements ApplicationListener {

    private Category category;

    private List<Object> customPopupMenuEntries;

    private final DeleteCommandExecutor deleteExecutor = new DeleteCommandExecutor();

    private final DuplicateCommandExecutor duplicateExecutor = new DuplicateCommandExecutor();

    private final EditCommandExecutor editExecutor = new EditCommandExecutor();

    private Class itemClass;

    private ItemDAO itemDAO;

    private SortableTable table;

    private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

    /*
     * (non-Javadoc)
     * 
     * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
     */
    public void onApplicationEvent(ApplicationEvent e) {
        if (e instanceof HousekeeperEvent) {
            final HousekeeperEvent le = (HousekeeperEvent) e;

            if (le.objectIs(itemClass)) {
                setCategory(category);
            } else if (le.objectIs(Category.class) && le.isEventType(HousekeeperEvent.SELECTED)) {
                final Category cat;
                if (le.getSource() != Category.NULL_OBJECT) {
                    cat = (Category) le.getSource();
                } else {
                    cat = null;
                }

                SwingUtilities.invokeLater(new Runnable() {

                    public void run() {
                        setCategory(cat);
                    }
                });
            } else if (le.isEventType(HousekeeperEvent.DATA_REPLACED)) {
                SwingUtilities.invokeLater(new Runnable() {

                    public void run() {
                        refresh();
                    }
                });
            }
        }
    }

    /**
     * @param customPopupMenuEntries The customPopupMenuEntries to set.
     */
    public void setCustomPopupMenuEntries(List<Object> customPopupMenuEntries) {
        this.customPopupMenuEntries = customPopupMenuEntries;
    }

    /**
     * @param itemClass The itemClass to set.
     */
    public void setItemClass(String itemClass) {
        try {
            this.itemClass = Class.forName(itemClass);
            LogFactory.getLog(getClass())
                    .debug("Listening for events related to class: " + this.itemClass.getName());
        } catch (ClassNotFoundException e) {
            LogFactory.getLog(getClass()).error("Class to filter after set to null", e);
        }
    }

    /**
     * Sets the manager which holds the data to display.
     * 
     * @param manager
     */
    public void setItemDAO(final ItemDAO manager) {
        this.itemDAO = manager;
    }

    /**
     * Sets the table this view shall use.
     * 
     * @param table != null
     */
    public void setTable(SortableTable table) {
        this.table = table;
    }

    /**
     * Returns the selected item in this view.
     * 
     * @return The selected item or null if none is selected.
     */
    public Item getSelectedItem() {
        return (Item) table.getSelected().get(0);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.springframework.richclient.factory.AbstractControlFactory#createControl()
     */
    protected JComponent createControl() {
        Assert.notNull(table);

        configureTable(table);
        refresh();

        final JPanel panel = new JPanel();
        // Without that, the tables won't grow and shrink with the window's
        // size.
        panel.setLayout(new GridLayout());
        panel.add(new JScrollPane(table));

        return panel;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.springframework.richclient.application.support.AbstractView#registerLocalCommandExecutors(org.springframework.richclient.application.PageComponentContext)
     */
    protected void registerLocalCommandExecutors(PageComponentContext context) {
        context.register(GlobalCommandIds.DELETE, deleteExecutor);
        context.register(GlobalCommandIds.PROPERTIES, editExecutor);

        // TODO Quick Fix for #004362
        if (itemClass.equals(ExpirableItem.class)) {
            context.register("duplicateCommand", duplicateExecutor);
        }

    }

    private void configureTable(JTable table) {
        table.getSelectionModel().addListSelectionListener(new TableSelectionListener());
        table.addMouseListener(new PopupTriggerListener(createContextMenu()));
        table.addMouseListener(new DoubleClickListener());
    }

    private JPopupMenu createContextMenu() {
        final List<Object> commands = new ArrayList<Object>();
        commands.addAll(customPopupMenuEntries);
        // TODO Quick Fix for #004362
        if (itemClass.equals(ExpirableItem.class)) {
            commands.add("duplicateCommand");
        }

        commands.add(GlobalCommandIds.PROPERTIES);
        commands.add(GlobalCommandIds.DELETE);

        CommandGroup convCommandGroup = getWindowCommandManager().createCommandGroup("tablePopupCommandGroup",
                commands.toArray());
        return convCommandGroup.createPopupMenu();
    }

    private void refresh() {
        final List items = itemDAO.findAllOfCategory(category);
        table.replaceAll(items);
    }

    private void setCategory(Category category) {
        this.category = category;
        refresh();
    }

    /**
     * Enables and disables Actions (and thus the buttons) depending on the
     * current selection state.
     */
    private void updateActionEnablement() {
        final boolean hasSelection = table.hasSelection();
        final boolean hasSingleSelection = table.hasSelection();
        duplicateExecutor.setEnabled(hasSingleSelection);
        editExecutor.setEnabled(hasSingleSelection);
        deleteExecutor.setEnabled(hasSelection);
    }

    private class DeleteCommandExecutor extends AbstractActionCommandExecutor {

        public void execute() {
            final Iterator i = table.getSelected().iterator();
            while (i.hasNext()) {
                Item element = (Item) i.next();
                itemDAO.delete(element);
            }
        }
    }

    private final class DoubleClickListener extends MouseAdapter {

        public void mouseClicked(MouseEvent e) {
            if (e.getClickCount() == 2) {
                getWindowCommandManager().getActionCommand(GlobalCommandIds.PROPERTIES).execute();
            }
        }
    }

    /**
     * Duplicates the selected item.
     */
    private class DuplicateCommandExecutor extends AbstractActionCommandExecutor {

        public void execute() {
            final ExpirableItem selectedItem = (ExpirableItem) getSelectedItem();
            itemDAO.store(new ExpirableItem(selectedItem));
        }
    }

    /**
     * Shows a dialog for modifying the currently selected item and updates it.
     */
    private class EditCommandExecutor extends AbstractActionCommandExecutor {

        public void execute() {
            final Item foodObject = (Item) table.getSelected().get(0);
            final Form form = Factory.createForm(foodObject);

            final TitledPageApplicationDialog dialog = new TitledPageApplicationDialog(form, getWindowControl()) {

                protected void onAboutToShow() {
                    setEnabled(true);
                }

                protected boolean onFinish() {
                    form.commit();
                    itemDAO.store(foodObject);
                    return true;
                }
            };
            dialog.showDialog();
        }
    }

    private class PopupTriggerListener extends PopupMenuMouseListener {

        private PopupTriggerListener(final JPopupMenu menu) {
            super(menu);
        }

        /**
         * Selects the row beneath the cursor before showing the popup menu
         */
        protected boolean onAboutToShow(MouseEvent e) {
            final int row = table.rowAtPoint(e.getPoint());

            if (!table.isRowSelected(row)) {
                table.getSelectionModel().setSelectionInterval(row, row);
            }

            return super.onAboutToShow(e);
        }
    }

    private final class TableSelectionListener implements ListSelectionListener {
        public void valueChanged(ListSelectionEvent e) {
            if (!e.getValueIsAdjusting()) {
                updateActionEnablement();
                propertyChangeSupport.firePropertyChange("selection", null, table.getSelected());
            }

        }
    }
}