Index: lutinutil/src/java/org/codelutin/vcs/ui/FileStateTableModel.java diff -u /dev/null lutinutil/src/java/org/codelutin/vcs/ui/FileStateTableModel.java:1.1 --- /dev/null Fri Jan 4 09:58:56 2008 +++ lutinutil/src/java/org/codelutin/vcs/ui/FileStateTableModel.java Fri Jan 4 09:58:51 2008 @@ -0,0 +1,239 @@ +/* +* ##% Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Code Lutin, +* Benjamin Poussin, Tony Chemit +* +* +* 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. +* ##% */ +package org.codelutin.vcs.ui; + +import org.codelutin.vcs.VCSFileState; +import org.codelutin.vcs.VCSAction; +import org.codelutin.vcs.VCSState; + +import static org.codelutin.i18n.I18n._; + +import javax.swing.table.AbstractTableModel; +import static java.lang.Boolean.FALSE; +import static java.lang.Boolean.TRUE; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.EnumSet; + +/** + * TODO Use FieldAccessManager + * + * @author tchemit + * @see org.codelutin.vcs.ui.FieldAccessManager + * @see org.codelutin.vcs.ui.FieldModelUtil + * @see org.codelutin.vcs.ui.FieldAccess + */ + +public class FileStateTableModel extends AbstractTableModel { + + private static final long serialVersionUID = 5764217576707763232L; + + public static enum FIELD_ACCESS { + MODULE(_("lutinutil.common.module"), String.class) { + public Object getValue(VCSFileState item) { + return item.getModuleName(); + } + }, + NAME(_("lutinutil.common.file"), String.class) { + public Object getValue(VCSFileState item) { + return item.getModuleRelativeFileName(); + } + }, + LOGDIFF(_("lutinutil.common.logDiff"), String.class) { + public Object getValue(VCSFileState item) { + final String changeLog = item.getChangeLog(); + return changeLog == null ? "" : changeLog; + } + }, + REV(_("lutinutil.common.rev"), Long.class) { + public Object getValue(VCSFileState item) { + return item.getRev(); + } + }; + + protected String columnName; + protected Class columnClass; + + FIELD_ACCESS(String columnName, Class columnClass) { + this.columnName = columnName; + this.columnClass = columnClass; + } + + public String getColumnName() { + return columnName; + } + + public Class getColumnClass() { + return columnClass; + } + + public abstract Object getValue(VCSFileState item); + } + + protected Map selected; + protected List data; + protected VCSState state; + protected List actions; + + public FileStateTableModel(List data, EnumSet actions) { + this.data = data; + this.selected = new HashMap(); + List tmp = new ArrayList(); + + if (!data.isEmpty()) { + // determine vcsstates used here for the moment a unique type + state = data.get(0).getState(); + + for (VCSAction action : Arrays.asList(state.getActions())) { + if (action.isVisible() && actions.contains(action)) { + tmp.add(action); + } + } + } + this.actions = tmp; + } + + /** + * @return Returns the selected. + */ + public List getSelected() { + List result = new ArrayList(); + for (Map.Entry item : selected.entrySet()) + if (item.getValue() != null) { + item.getKey().setAction(item.getValue()); + result.add(item.getKey()); + } + return result; + } + + public int getSelectedSize() { + int result = 0; + for (Map.Entry item : selected.entrySet()) { + if (item.getValue() != null) { + result++; + } + } + return result; + } + + public List getActions() { + return actions; + } + + public VCSAction getAction(int row) { + return selected.get(data.get(row)); + } + + /* (non-Javadoc) + * @see javax.swing.table.TableModel#getColumnCount() + */ + public int getColumnCount() { + return _FIELD_ACCESS.length + actions.size() - 2; + } + + /* (non-Javadoc) + * @see javax.swing.table.TableModel#getRowCount() + */ + public int getRowCount() { + return data.size(); + } + + /* (non-Javadoc) + * @see javax.swing.table.AbstractTableModel#getColumnClass(int) + */ + @Override + public Class getColumnClass(int columnIndex) { + Class result; + if (columnIndex < actions.size()) { + result = Boolean.class; + } else { + result = _FIELD_ACCESS[columnIndex - actions.size()].getColumnClass(); + } + return result; + } + + /* (non-Javadoc) + * @see javax.swing.table.AbstractTableModel#getColumnName(int) + */ + @Override + public String getColumnName(int columnIndex) { + String result; + if (columnIndex < actions.size()) { + result = actions.get(columnIndex).getLibelle().substring(0,1); + } else { + result = _FIELD_ACCESS[columnIndex - actions.size()].getColumnName(); + } + return result; + } + + /* (non-Javadoc) + * @see javax.swing.table.AbstractTableModel#isCellEditable(int, int) + */ + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return columnIndex < actions.size(); + } + + /* (non-Javadoc) + * @see javax.swing.table.AbstractTableModel#setValueAt(Object, int, int) + */ + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + if (columnIndex < actions.size()) { + VCSFileState item = data.get(rowIndex); + VCSAction action = actions.get(columnIndex); + final boolean b = TRUE.equals(aValue); + selected.put(item, b ? action : null); + } + } + + /* (non-Javadoc) + * @see javax.swing.table.TableModel#getValueAt(int, int) + */ + public Object getValueAt(int rowIndex, int columnIndex) { + VCSFileState item = data.get(rowIndex); + Object result; + if (getRowCount() == 0) return null; + if (columnIndex < actions.size()) { + result = selected.get(item); + VCSAction action = actions.get(columnIndex); + result = result == null || action != result ? FALSE : TRUE; + } else { + result = _FIELD_ACCESS[columnIndex - actions.size()].getValue(item); + } + + return result; + } + + + public void checkAll(int index, boolean value) { + if (actions.size()!=1 || index >= actions.size()) return; + //if (getActions().size() == 1) return; + // the only case we can automaticly check-uncheck items + for (int i = 0; i < getRowCount(); i++) setValueAt(value, i, index); + } + + private static final FIELD_ACCESS[] _FIELD_ACCESS = FIELD_ACCESS.values(); +} + + Index: lutinutil/src/java/org/codelutin/vcs/ui/FieldAccessManager.java diff -u /dev/null lutinutil/src/java/org/codelutin/vcs/ui/FieldAccessManager.java:1.1 --- /dev/null Fri Jan 4 09:58:56 2008 +++ lutinutil/src/java/org/codelutin/vcs/ui/FieldAccessManager.java Fri Jan 4 09:58:51 2008 @@ -0,0 +1,153 @@ +/* +* ##% Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Code Lutin, +* Benjamin Poussin, Tony Chemit +* +* +* 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. +* ##% */ +package org.codelutin.vcs.ui; + +import org.apache.commons.logging.Log; +import static org.apache.commons.logging.LogFactory.getLog; +import static org.codelutin.i18n.I18n._; + +/** + * Class pour gérer un cache de {@link FieldAccessEntry} indexés à partir de + * {@link FieldAccess}. + * + * @author chemit + */ +public class FieldAccessManager { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = getLog(FieldAccessManager.class); + + /** cache of registred FiledModelEntry associated to a FieldAccess */ + static protected java.util.Map cache; + + /** + * Register a FieldAccess in the cache + * + * @param constant the constant to be used + * @param libelle name of the field (libelle to display in row header) + * @param clazz class of the object used for this field + */ + public static void registerFieldAccess(FieldAccess constant, String libelle, Class clazz) { + checkAlreadyRegistredEntry(constant); + FieldAccessEntry entry = new FieldAccessEntry(constant, libelle, clazz); + log.debug(entry); + getCache().put(constant, entry); + } + + /** + * Obtain the class of a field via his constant type safe value + * + * @param constant the constant to be used + * @return the class defined for the field + */ + public static Class getFieldClass(FieldAccess constant) { + FieldAccessEntry entry = getEntry(constant, true); + return entry == null ? null : entry.getClazz(); + } + + /** + * Obtain the libelle of a field via his constant type safe value + * + * @param constant the constant to be used + * @return the libelle defined for the field + */ + public static String getFieldName(FieldAccess constant) { + FieldAccessEntry entry = getEntry(constant, true); + return entry == null ? null : entry.getLibelle(); + } + + /** + * Obtain for a item the value of his field via his constant type safe value + * + * @param constant the constant to be used + * @param item the item to be inspect + * @return the class defined for the field + */ + public static Object getFieldValue(FieldAccess constant, D item) { + FieldAccessEntry entry = getEntry(constant, true); + return entry == null ? null : entry.getValue(item); + } + + @SuppressWarnings({"unchecked"}) + protected static FieldAccessEntry getEntry(FieldAccess constant, boolean safe) { + FieldAccessEntry entry = getCache().get(constant); + checkExistingEntry(constant, safe, entry); + return entry; + } + + private static void checkExistingEntry(FieldAccess constant, boolean safe, FieldAccessEntry entry) { + if (safe && entry == null) { + throw new RuntimeException(_("lutinutil.error.fieldmodel.not.registred", constant)); + } + } + + private static void checkAlreadyRegistredEntry(FieldAccess constant) throws RuntimeException { + FieldAccessEntry entry = getEntry(constant, false); + if (entry != null) { + throw new RuntimeException(_("lutinutil.error.fieldmodel.already.registred", constant)); + } + } + + + private static java.util.Map getCache() { + if (cache == null) + cache = new java.util.HashMap(); + return cache; + } + + protected static class FieldAccessEntry implements FieldAccess { + + private final String libelle; + private final Class clazz; + private final FieldAccess constant; + + FieldAccessEntry(FieldAccess constant, String libelle, Class clazz) { + this.constant = constant; + // keep only translated libelle + this.libelle = _(libelle); + this.clazz = clazz; + } + + public String getLibelle() { + return libelle; + } + + public Class getClazz() { + return clazz; + } + + public Object getValue(D item) { + return constant.getValue(item); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(this.getClass().getSimpleName()); + sb.append('@').append(Math.abs(hashCode())); + sb.append(" [").append(constant).append("] [").append(libelle).append("] ["); + sb.append(clazz).append(']'); + return sb.toString(); + } + } + + protected FieldAccessManager() { + } + +} Index: lutinutil/src/java/org/codelutin/vcs/ui/FieldModelUtil.java diff -u /dev/null lutinutil/src/java/org/codelutin/vcs/ui/FieldModelUtil.java:1.1 --- /dev/null Fri Jan 4 09:58:56 2008 +++ lutinutil/src/java/org/codelutin/vcs/ui/FieldModelUtil.java Fri Jan 4 09:58:51 2008 @@ -0,0 +1,119 @@ +/* +* ##% Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Code Lutin, +* Benjamin Poussin, Tony Chemit +* +* +* 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. +* ##% */ +package org.codelutin.vcs.ui; + +import static org.codelutin.i18n.I18n._; +import org.codelutin.vcs.VCSFileState; + +import java.io.File; + +public class FieldModelUtil { + + static public ModuleFile createModuleFileTableModel(java.util.List data) { + return new ModuleFile(SimpleModuleFileAccess.getAcces(), data); + } + + static public ModuleFile createModuleFileTableModelWithSelect(java.util.List data) { + return new ModuleFile(SimpleModuleFileAccess.getAcces(), data, Boolean.class, _("lutinutil.common.select")); + } + + static public ModuleFile createModuleFileTableModelWithSelect(FieldAccess[] model, java.util.List data) { + return new ModuleFile(model, data, Boolean.class, _("lutinutil.common.select")); + } + + static public ModuleFile createModuleFileTableModel(FieldAccess[] model, java.util.List data) { + return new ModuleFile(model, data); + } + + public static class ModuleFile extends AbstractTableModel { + private static final long serialVersionUID = 4067521432762944991L; + + protected ModuleFile(FieldAccess[] model, java.util.List data, Class klazz, String select) { + super(data, model, klazz, select); + } + + protected ModuleFile(FieldAccess[] model, java.util.List data) { + super(data, model); + } + } + + + public static enum SimpleModuleFileWithActionAccess implements FieldAccess { + ACTION(_("lutinutil.common.action"), String.class) { + public Object getValue(VCSFileState item) { + return item.getAction().getLibelle(); + } + }, + MODULE(_("lutinutil.common.module"), String.class) { + public Object getValue(VCSFileState item) { + return item.getModuleName(); + } + }, + NAME(_("lutinutil.common.file"), String.class) { + public Object getValue(VCSFileState item) { + return item.getModuleRelativeFileName(); + } + }; + + SimpleModuleFileWithActionAccess(String libelle, Class clazz) { + FieldAccessManager.registerFieldAccess(this, libelle, clazz); + } + } + + public static enum SimpleModuleFileAccess implements FieldAccess { + + MODULE(_("lutinutil.common.module"), String.class) { + public Object getValue(String item) { + return item.contains(java.io.File.separator) ? item.substring( + 0, item.lastIndexOf(java.io.File.separator)) : item; + } + }, + NAME(_("isisfish.common.file"), String.class) { + public Object getValue(String item) { + return item.contains(java.io.File.separator) ? item + .substring(item.lastIndexOf(java.io.File.separator) + 1) + : ""; + } + }; + + SimpleModuleFileAccess(String libelle, Class clazz) { + FieldAccessManager.registerFieldAccess(this, libelle, clazz); + } + + public static FieldAccess[] getAcces() { + return values(); + } + + } + + public static enum SimpleFileAccess implements FieldAccess { + + NAME(_("lutinutil.common.file"), File.class) { + public Object getValue(File item) { + return item.getAbsolutePath(); + } + }; + + SimpleFileAccess(String libelle, Class clazz) { + FieldAccessManager.registerFieldAccess(this, libelle, clazz); + } + } + +} Index: lutinutil/src/java/org/codelutin/vcs/ui/FieldAccess.java diff -u /dev/null lutinutil/src/java/org/codelutin/vcs/ui/FieldAccess.java:1.1 --- /dev/null Fri Jan 4 09:58:56 2008 +++ lutinutil/src/java/org/codelutin/vcs/ui/FieldAccess.java Fri Jan 4 09:58:51 2008 @@ -0,0 +1,31 @@ +/* +* ##% Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Code Lutin, +* Benjamin Poussin, Tony Chemit +* +* +* 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. +* ##% */ +package org.codelutin.vcs.ui; + +/** + * A simple contract for a field access in vcs ui, says a cell + * + * @author chemit + */ +public interface FieldAccess { + + Object getValue(D item); + +} Index: lutinutil/src/java/org/codelutin/vcs/ui/AbstractTableModel.java diff -u /dev/null lutinutil/src/java/org/codelutin/vcs/ui/AbstractTableModel.java:1.1 --- /dev/null Fri Jan 4 09:58:56 2008 +++ lutinutil/src/java/org/codelutin/vcs/ui/AbstractTableModel.java Fri Jan 4 09:58:51 2008 @@ -0,0 +1,189 @@ +/* +* ##% Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Code Lutin, +* Benjamin Poussin, Tony Chemit +* +* +* 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. +* ##% */ +package org.codelutin.vcs.ui; + +import static org.codelutin.i18n.I18n._; + +import static java.lang.Boolean.TRUE; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** TODO-TC */ +public abstract class AbstractTableModel extends javax.swing.table.AbstractTableModel { + + + protected final FieldAccess[] modelAccess; + protected List data; + + protected final int nbOptions; + protected Map[] options; + protected final String[] optionNames; + protected final Class[] optionClass; + protected boolean[] optionChecks; + + private static final long serialVersionUID = 4697917831388337369L; + + @SuppressWarnings({"unchecked"}) + protected AbstractTableModel( + List data, FieldAccess[] modelAccess, + Class[] optionsClass, String[] optionsNames) throws RuntimeException { + if (optionsClass.length != optionsNames.length) + throw new RuntimeException(_("lutinutil.error.fieldmodel.unmatchin.options")); + + this.data = data; + this.optionClass = optionsClass; + this.optionNames = optionsNames; + this.modelAccess = modelAccess; + this.nbOptions = optionsClass.length; + this.options = new Map[this.nbOptions]; + this.optionChecks = new boolean[this.nbOptions]; + } + + protected AbstractTableModel(List data, FieldAccess[] modelAccess, + Class optionsClass, String optionsNames) { + this(data, modelAccess, new Class[]{optionsClass}, + new String[]{optionsNames}); + } + + protected AbstractTableModel(List data, FieldAccess[] modelAccess) { + this(data, modelAccess, new Class[0], new String[0]); + } + + protected Map getOptionMap(int rowindex) { + if (rowindex >= nbOptions) return null; + Map map = options[rowindex]; + if (map == null) + map = options[rowindex] = new LinkedHashMap(); + return map; + } + + /** + * @param index option index + * @return Returns the selected for an option. + */ + public List getSelected(int index) { + List result = new ArrayList(); + Map option = nbOptions == 0 ? null : options[index]; + if (index >= nbOptions || option == null) return result; + for (Map.Entry item : option.entrySet()) + if (java.lang.Boolean.TRUE.equals(item.getValue())) + result.add(item.getKey()); + return result; + } + + public int getSelectedSize(int index) { + int result = 0; + Map option = nbOptions == 0 ? null : options[index]; + if (index >= nbOptions || option == null) return result; + for (Map.Entry item : option.entrySet()) + if (java.lang.Boolean.TRUE.equals(item.getValue())) + result++; + return result; + } + + public List getData() { + return data; + } + + public int getColumnCount() { + return modelAccess.length + nbOptions; + } + + public int getRowCount() { + return data.size(); + } + + public void checkAll() { + if (nbOptions != 1) return; + for (int i = 0; i < nbOptions; i++) checkAll(i); + } + + @Override + public Class getColumnClass(int columnIndex) { + Class result; + if (columnIndex < nbOptions) { + + result = this.optionClass[columnIndex]; + } else { + result = FieldAccessManager.getFieldClass(modelAccess[columnIndex - nbOptions]); + } + return result; + } + + @Override + public String getColumnName(int columnIndex) { + String result; + if (columnIndex < nbOptions) + result = this.optionNames[columnIndex]; + else + result = FieldAccessManager.getFieldName(modelAccess[columnIndex - nbOptions]); + return result; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return columnIndex < nbOptions; + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + D item = data.get(rowIndex); + if (columnIndex < nbOptions) + setOptionValueAt(item, aValue, columnIndex); + // read only data + } + + public Object getValueAt(int rowIndex, int columnIndex) { + D item = data.get(rowIndex); + if (columnIndex < nbOptions) + return getOptionValueAt(item, columnIndex); + return modelAccess[columnIndex - nbOptions].getValue(item); + } + + protected void setOptionValueAt(D item, Object aValue, int index) { + getOptionMap(index).put(item, TRUE.equals(aValue)); + } + + protected void checkAll(int index, boolean value) { + if (index >= nbOptions || nbOptions > 1) return; + for (int i = 0; i < getRowCount(); i++) + setValueAt(value, i, index); + } + + protected void checkAll(int index) { + if (index >= nbOptions || nbOptions > 1) return; + checkAll(index, optionChecks[index] = !optionChecks[index]); + } + + protected Boolean getOptionValueAt(D item, int index) { + return getOptionMap(index).get(item); + } + + protected FieldAccess[] getFiedAccess() { + return modelAccess; + } + + public void reset(List states) { + data.clear(); + data.addAll(states); + } +}