package org.korsakow.ide.ui.components.pool; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.HashMap; import javax.swing.BoxLayout; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.korsakow.ide.ui.components.KCollapsiblePane; import org.korsakow.ide.ui.components.KLayoutPanel; import org.korsakow.ide.util.WeakReferenceMap; public abstract class AbstractPool<HE extends HeaderEntry, CE extends ContentEntry> extends JPanel implements ListDataListener { public static final String ACTION_PANEL_EXPAND = "Pool.ACTION_PANEL_EXPAND"; private AbstractPoolModel<HE> model = null; private JScrollPane scrollPane; private JPanel contentPane; private JPanel headingPane; private ActionListener paneActionListener; private ListSelectionListener paneSelectionListener; /** * Using a weak map so we can be lazy about cleaning up. */ private WeakReferenceMap<Object, KCollapsiblePane> paneMap = new WeakReferenceMap<Object, KCollapsiblePane>(); public AbstractPool() { this(null); } public AbstractPool(AbstractPoolModel<HE> model) { initUI(); setModel(model); } public KCollapsiblePane getPane(Object id) { return paneMap.get(id); } public void setModel(AbstractPoolModel<HE> model) { if (this.model != null) { this.model.removeListDataListener(this); } this.model = model; if (this.model != null) { model.addListDataListener(this); rebuild(); } revalidate(); // maybe necessary? repaint(); // necessary: artifacts seen when repainting to a smaller size } public AbstractPoolModel<HE> getModel() { return this.model; } public void contentsChanged(ListDataEvent e) { if (e.getIndex0() == -1) rebuild(); else { for (int i = e.getIndex0(); i <= e.getIndex1(); ++i) { HE entry = model.getEntry(i); KCollapsiblePane pane = (KCollapsiblePane)contentPane.getComponent(i); AbstractHeader header = (AbstractHeader)pane.getHeader(); Content<CE> content = (Content<CE>)pane.getContent(); updateEntry(pane, header, content, entry); } } revalidate(); } public void setHeadingPane ( JPanel headingPane ) { if ( headingPane == null ) { // if we set the header to null, remove from contentPane if ( this.headingPane != null ) { remove(this.headingPane); } // otherwise do nothing this.headingPane = null; } else { this.headingPane = headingPane; add(this.headingPane, BorderLayout.NORTH); } } public JPanel getHeadingPane () { return this.headingPane; } public void intervalAdded(ListDataEvent e) { } public void intervalRemoved(ListDataEvent e) { } public void addActionListener(ActionListener listener) { listenerList.add(ActionListener.class, listener); } public void addListSelectionListener(ListSelectionListener listener) { listenerList.add(ListSelectionListener.class, listener); } private void rebuild() { contentPane.removeAll(); for (HE entry : model.getData()) { KCollapsiblePane pane = createPane(entry); pane.setExpanded(false); pane.addActionListener(paneActionListener); contentPane.add(pane); } revalidate(); } protected KCollapsiblePane createPane(HE entry) { AbstractHeader header = createHeader(entry); Content content = createContent(entry); KCollapsiblePane pane = new KCollapsiblePane(header, content); Object id = getModel().getId(entry); pane.putClientProperty("poolid", id); header.putClientProperty("poolid", id); content.addListSelectionListener(paneSelectionListener); paneMap.put(id, pane); return pane; } protected abstract AbstractHeader createHeader(HE entry); protected abstract Content<CE> createContent(HE entry); protected abstract void updateEntry(KCollapsiblePane pane, AbstractHeader header, Content<CE> content, HE entry); protected void initUI() { setLayout(new BorderLayout()); contentPane = new KLayoutPanel(); // contentPane.setLayout(new VerticalFlowLayout()); contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); // setLayout(new BorderLayout()); scrollPane = new JScrollPane(contentPane); // scrollPane.setPreferredSize(new Dimension(100,100)); scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); add(scrollPane, BorderLayout.CENTER); paneActionListener = new ActionListener() { public void actionPerformed(ActionEvent event) { fireActionEvent(event.getSource(), ACTION_PANEL_EXPAND); } }; paneSelectionListener = new ListSelectionListener() { public void valueChanged(ListSelectionEvent event) { fireListSelectionEvent(event); } }; } protected void fireListSelectionEvent(ListSelectionEvent event) { for (ListSelectionListener listener : listenerList.getListeners(ListSelectionListener.class)) listener.valueChanged(event); } protected void fireActionEvent(Object source, String command) { ActionEvent event = new ActionEvent(source, 0, command); for (ActionListener listener : listenerList.getListeners(ActionListener.class)) listener.actionPerformed(event); } }