/*
Copyright 2009 Hauke Rehfeld
This file is part of QuakeInjector.
QuakeInjector 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 3 of the License, or
(at your option) any later version.
QuakeInjector 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 QuakeInjector. If not, see <http://www.gnu.org/licenses/>.
*/
package de.haukerehfeld.quakeinjector.packagelist.model;
import java.awt.Component;
import java.awt.FlowLayout;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.List;
import java.util.List;
import java.util.regex.Pattern;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.RowFilter;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TableModelEvent;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
import de.haukerehfeld.quakeinjector.ChangeListenerList;
import de.haukerehfeld.quakeinjector.Package;
import de.haukerehfeld.quakeinjector.PackageList;
import de.haukerehfeld.quakeinjector.Utils;
public class PackageListModel extends AbstractTableModel implements ChangeListener {
private ChangeListenerList listeners = new ChangeListenerList();
private PackageList data;
public PackageListModel(PackageList data) {
setMapList(data);
}
public void size(JTable table) {
TableColumnModel m = table.getColumnModel();
m.getColumn(Column.getColumnNumber(Column.NAME)).setPreferredWidth(80);
m.getColumn(Column.getColumnNumber(Column.TITLE)).setPreferredWidth(150);
m.getColumn(Column.getColumnNumber(Column.AUTHOR)).setPreferredWidth(100);
m.getColumn(Column.getColumnNumber(Column.INSTALLED)).setResizable(false);
m.getColumn(Column.getColumnNumber(Column.INSTALLED)).setMaxWidth(16);
m.getColumn(Column.getColumnNumber(Column.INSTALLED)).setMinWidth(16);
int ratingSize = 5 * (RatingRenderer.ICONSIZE + RatingRenderer.HORIZONTALGAP)
+ RatingRenderer.HORIZONTALGAP;
m.getColumn(Column.getColumnNumber(Column.RATING)).setMinWidth(ratingSize);
m.getColumn(Column.getColumnNumber(Column.RATING)).setMaxWidth(ratingSize);
m.getColumn(Column.getColumnNumber(Column.RATING)).setResizable(false);
m.getColumn(Column.getColumnNumber(Column.RELEASEDATE)).setMinWidth(75);
m.getColumn(Column.getColumnNumber(Column.RELEASEDATE)).setPreferredWidth(80);
//m.getColumn(Column.getColumnNumber(Column.RELEASEDATE)).setMaxWidth(80);
}
// public List<Package> getPackageList() {
// return this.data;
// }
public void setMapList(PackageList data) {
if (this.data != null) {
//remove from all old
this.data.removeChangeListener(this);
for (Package map: this.data) {
map.removeChangeListener(this);
}
}
data.sort();
//add to new
this.data = data;
data.addChangeListener(this);
for (Package map: data) {
map.addChangeListener(this);
}
fireTableChanged(new TableModelEvent(this));
}
public int getColumnCount() {
return Column.count();
}
@Override
public String getColumnName(int col) {
return Column.getColumn(col).header;
}
/*
* data
*/
@Override
public int getRowCount() {
return data.size();
}
public Object getColumnData(int col, Package info) {
return Column.getColumn(col).getData(info);
}
@Override
public Class<? extends Object> getColumnClass(int c) {
return Column.getColumn(c).getColumnClass();
}
@Override
public Object getValueAt(int row, int col) {
return getColumnData(col, data.get(row));
}
@Override
public boolean isCellEditable(int row, int col) {
return false;
}
public Package getPackage(int row) {
return data.get(row);
}
public void addChangeListener(ChangeListener l) {
listeners.addChangeListener(l);
}
public void stateChanged(ChangeEvent e) {
if (e.getSource() instanceof PackageList) {
setMapList((PackageList) e.getSource());
listeners.notifyChangeListeners(e.getSource());
return;
}
if (e.getSource() instanceof Package) {
Package r = (Package) e.getSource();
listeners.notifyChangeListeners(r);
int i = data.indexOf(r);
super.fireTableRowsUpdated(i, i);
return;
}
throw new RuntimeException("didn't recognise what changed!");
}
/**
* Update the row filter regular expression from the expression in
* the text box.
*/
public RowFilter<PackageListModel, Integer> filter(final String filterText) {
final int[] columnsToCheck = { Column.getColumnNumber(Column.NAME),
Column.getColumnNumber(Column.AUTHOR),
Column.getColumnNumber(Column.TITLE),
Column.getColumnNumber(Column.RELEASEDATE)
};
String[] filterTexts = filterText.split(" ");
final List<Pattern> patterns = new ArrayList<Pattern>(filterTexts.length);
for (String filter: filterTexts) {
try {
patterns.add(Pattern.compile(".*" + filter + ".*",
Pattern.CASE_INSENSITIVE + Pattern.UNICODE_CASE));
} catch (java.util.regex.PatternSyntaxException e) {
continue;
}
}
RowFilter<PackageListModel, Integer> rf = new RowFilter<PackageListModel,Integer>() {
@Override
public boolean include(Entry<? extends PackageListModel, ? extends Integer> entry) {
//match all patters in at least one column
for (Pattern pattern: patterns) {
boolean matches = false;
for (int i: columnsToCheck) {
if (pattern.matcher(entry.getStringValue(i)).matches()) {
matches = true;
}
}
if (!matches) {
return false;
}
}
return true;
}
};
return rf;
}
public static class RatingRenderer extends JPanel implements TableCellRenderer {
private static final int HORIZONTALGAP = 2;
private static final int ICONSIZE = 8;
private ImageIcon activeIcon;
private ImageIcon inactiveIcon;
private List<JLabel> ratingLabels = new ArrayList<JLabel>(5);
public RatingRenderer() {
super();
try {
activeIcon = Utils.createImageIcon("/star_spirit_8.png", "activeStar");
inactiveIcon = Utils.createImageIcon("/star_spirit_8_inactive.png", "inactiveStar");
}
catch (java.io.IOException e) {
System.err.println("WARNING: Couldn't load rating image!");
}
EmptyBorder border = new EmptyBorder(0,0,0,0);
setBorder(border);
((FlowLayout) getLayout()).setHgap(HORIZONTALGAP);
((FlowLayout) getLayout()).setVgap(4);
for (int i = 0; i < 5; ++i) {
JLabel label = new JLabel(activeIcon);
label.setDisabledIcon(inactiveIcon);
label.setBorder(border);
label.setOpaque(false);
add(label);
ratingLabels.add(label);
}
}
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
if (value instanceof Package.Rating) {
Package.Rating rating = (Package.Rating) value;
int i = 0;
for (JLabel label: ratingLabels) {
boolean enabled = true;
if (i >= rating.getRating()) {
enabled = false;
}
label.setEnabled(enabled);
++i;
}
}
return this;
}
}
// /*
// * Don't need to implement this method unless your table's
// * data can change.
// */
// public void setValueAt(Object value, int row, int col) {
// data[row][col] = value;
// fireTableCellUpdated(row, col);
// }{
}