// BlogBridge -- RSS feed reader, manager, and web based service
// Copyright (C) 2002-2006 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: PluginsTable.java,v 1.6 2007/04/06 09:57:35 spyromus Exp $
//
package com.salas.bb.plugins.gui;
import com.salas.bb.plugins.domain.Package;
import com.salas.bb.utils.uif.CheckBoxList;
import javax.swing.*;
import javax.swing.event.EventListenerList;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* Plug-ins list table.
*/
public class PluginsTable extends CheckBoxList
{
private List<Package> installed;
private List<Package> selected;
private PackagesListModel packages;
/**
* Creates table.
*/
public PluginsTable()
{
packages = new PackagesListModel();
setModel(packages);
}
// ------------------------------------------------------------------------
// Interface
// ------------------------------------------------------------------------
/**
* Sets the list of installed packages.
*
* @param packages installed packages.
*/
public void setInstalledPackages(List<Package> packages)
{
installed = packages;
updateList();
}
/**
* Sets the list of selected packages.
*
* @param packages selected packages.
*/
public void setSelectedPackages(List<Package> packages)
{
selected = packages;
updateList();
}
/**
* Returns the list of selected packages.
*
* @return selected packages.
*/
public List<Package> getSelectedPackages()
{
List<Package> pkgs = new ArrayList<Package>();
for (PackageCheckBox pkgbox : packages)
{
if (pkgbox.isSelected()) pkgs.add(pkgbox.getSource());
}
return pkgs;
}
// ------------------------------------------------------------------------
// Private stuff
// ------------------------------------------------------------------------
/** Adds newly installed items, removes missing, changes the selection. */
private void updateList()
{
if (installed == null)
{
packages.clear();
} else
{
// Add new items
for (Package pkg : installed)
{
boolean found = false;
for (PackageCheckBox pcb : packages)
{
if (pcb.getSource().equals(pkg))
{
found = true;
break;
}
}
if (!found) packages.add(new PackageCheckBox(pkg));
}
// Remove missing
List<PackageCheckBox> toRemove = new ArrayList<PackageCheckBox>();
for (PackageCheckBox pcb : packages)
{
boolean found = false;
for (Package pkg : installed)
{
if (pcb.equals(pkg))
{
found = true;
break;
}
}
if (!found) toRemove.add(pcb);
}
packages.removeAll(toRemove);
}
// Change the selection
if (selected == null)
{
for (PackageCheckBox pcb : packages)
{
pcb.setSelected(false);
}
} else
{
for (PackageCheckBox pcb : packages)
{
if (selected.contains(pcb.getSource())) pcb.setSelected(true);
}
}
}
/**
* Returns highlighted package.
*
* @return package or <code>NULL</code>.
*/
public Package getHighlightedPackage()
{
PackageCheckBox pcb = (PackageCheckBox)getSelectedValue();
return pcb == null ? null : pcb.getSource();
}
/**
* Selects a package by its file name.
*
* @param file file name.
*/
public void selectPackage(File file)
{
String name = file.getName();
for (PackageCheckBox pcb : packages)
{
if (pcb.getSource().getFileName().equals(name))
{
pcb.setSelected(true);
setSelectedIndex(packages.indexOf(pcb));
return;
}
}
}
/**
* Package checkbox.
*/
private static class PackageCheckBox extends JCheckBox
{
private final Package source;
/**
* Creates a package checkbox.
*
* @param source source package.
*/
public PackageCheckBox(Package source)
{
this.source = source;
setText(source.getName());
}
/**
* Returns package.
*
* @return package.
*/
public Package getSource()
{
return source;
}
@Override
public String toString()
{
return source.getName();
}
/**
* Compares this object to another package or package checkbox.
*
* @param o object.
*
* @return <code>TRUE</code> if represent the same package.
*/
public boolean equals(Object o)
{
if (this == o) return true;
Package thatSource = o instanceof Package ? (Package)o : ((PackageCheckBox)o).getSource();
return source != null ? source.equals(thatSource) : thatSource == null;
}
/**
* Returns the hash code.
*
* @return hash code.
*/
public int hashCode()
{
return (source != null ? source.hashCode() : 0);
}
/**
* Checkbox comparator.
*/
public static class PCBComparator implements Comparator<PackageCheckBox>
{
/**
* Compares two objects.
*
* @param o1 first.
* @param o2 second.
*
* @return a negative integer, zero, or a positive integer as the
* first argument is less than, equal to, or greater than the
* second.
*/
public int compare(PackageCheckBox o1, PackageCheckBox o2)
{
return o1.getText().compareTo(o2.getText());
}
}
}
/**
* Packages list model firing necessary events on updates.
*/
private static class PackagesListModel extends ArrayList<PackageCheckBox> implements ListModel
{
private final static Comparator<PackageCheckBox> comparator = new PackageCheckBox.PCBComparator();
@Override
public boolean add(PackageCheckBox o)
{
int i = Collections.binarySearch(this, o, comparator);
if (i < 0)
{
i = -i - 1;
super.add(i, o);
fireIntervalAdded(i, i);
}
return i < 0;
}
@Override
public PackageCheckBox remove(int index)
{
PackageCheckBox el = super.remove(index);
fireIntervalRemoved(index, index);
return el;
}
@Override
public void clear()
{
int s = size();
super.clear();
if (s > 0) fireIntervalRemoved(0, s);
}
// --------------------------------------------------------------------
// Implementation
// --------------------------------------------------------------------
private EventListenerList ell = new EventListenerList();
/**
* Returns the length of the list.
*
* @return the length of the list
*/
public int getSize()
{
return this.size();
}
/**
* Returns the value at the specified index.
*
* @param index the requested index
*
* @return the value at <code>index</code>
*/
public Object getElementAt(int index)
{
return get(index);
}
/**
* Adds a listener to the list that's notified each time a change
* to the data model occurs.
*
* @param l the <code>ListDataListener</code> to be added
*/
public void addListDataListener(ListDataListener l)
{
ell.add(ListDataListener.class, l);
}
/**
* Removes a listener from the list that's notified each time a
* change to the data model occurs.
*
* @param l the <code>ListDataListener</code> to be removed
*/
public void removeListDataListener(ListDataListener l)
{
ell.remove(ListDataListener.class, l);
}
/**
* Fires interval added event.
*
* @param i0 index 0.
* @param i1 index 1.
*/
private void fireIntervalAdded(int i0, int i1)
{
ListDataEvent e = null;
ListDataListener[] ldls = ell.getListeners(ListDataListener.class);
for (ListDataListener ldl : ldls)
{
if (e == null) e = new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, i0, i1);
ldl.intervalAdded(e);
}
}
/**
* Fires interval removed event.
*
* @param i0 index 0.
* @param i1 index 1.
*/
private void fireIntervalRemoved(int i0, int i1)
{
ListDataEvent e = null;
ListDataListener[] ldls = ell.getListeners(ListDataListener.class);
for (ListDataListener ldl : ldls)
{
if (e == null) e = new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, i0, i1);
ldl.intervalRemoved(e);
}
}
}
}