/* * sulky-modules - several general-purpose modules. * Copyright (C) 2007-2011 Joern Huxhorn * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* * Copyright 2007-2011 Joern Huxhorn * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.huxhorn.sulky.swing; import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.swing.table.DefaultTableColumnModel; import javax.swing.table.TableColumn; /** * This class is based on code and ideas from Stephen Kelvin (mail at StephenKelvin.de) and Thomas Darimont. */ public class PersistentTableColumnModel extends DefaultTableColumnModel { private static final long serialVersionUID = 367475030324866809L; protected List<TableColumn> allTableColumns = new ArrayList<>(); /** * Creates an extended table column model. */ public PersistentTableColumnModel() { allTableColumns = new ArrayList<>(); initColumns(); } /** * Should be implemented by subclasses if needed. */ protected void initColumns() { } /** * Sets the visibility of the specified TableColumn. * The call is ignored if the TableColumn is not found in this column model * or its visibility status did not change. * * @param column the column to show/hide * @param visible its new visibility status */ // listeners will receive columnAdded()/columnRemoved() event public void setColumnVisible(TableColumn column, boolean visible) { if(!visible) { super.removeColumn(column); } else { // find the visible index of the column: // iterate through both collections of visible and all columns, counting // visible columns up to the one that's about to be shown again int noVisibleColumns = tableColumns.size(); int noInvisibleColumns = allTableColumns.size(); int visibleIndex = 0; for(int invisibleIndex = 0; invisibleIndex < noInvisibleColumns; ++invisibleIndex) { TableColumn visibleColumn = (visibleIndex < noVisibleColumns ? tableColumns.get(visibleIndex) : null); TableColumn testColumn = allTableColumns.get(invisibleIndex); if(testColumn == column) { if(visibleColumn != column) { super.addColumn(column); super.moveColumn(tableColumns.size() - 1, visibleIndex); } return; // #################### } if(testColumn == visibleColumn) { ++visibleIndex; } } } } /** * Makes all columns in this model visible */ public void setAllColumnsVisible() { int noColumns = allTableColumns.size(); for(int columnIndex = 0; columnIndex < noColumns; ++columnIndex) { TableColumn visibleColumn = (columnIndex < tableColumns.size() ? tableColumns.get(columnIndex) : null); TableColumn invisibleColumn = allTableColumns.get(columnIndex); if(visibleColumn != invisibleColumn) { super.addColumn(invisibleColumn); super.moveColumn(tableColumns.size() - 1, columnIndex); } } } /** * Checks wether the specified column is currently visible. * * @param aColumn column to check * @return visibility of specified column (false if there is no such column at all. [It's not visible, right?]) */ public boolean isColumnVisible(TableColumn aColumn) { return (tableColumns.indexOf(aColumn) >= 0); } /** * Append <code>column</code> to the right of exisiting columns. * Posts <code>columnAdded</code> event. * * @param column The column to be added * @throws IllegalArgumentException if <code>column</code> is <code>null</code> * @see #removeColumn */ @Override public void addColumn(TableColumn column) { allTableColumns.add(column); super.addColumn(column); } /** * Removes <code>column</code> from this column model. * Posts <code>columnRemoved</code> event. * Will do nothing if the column is not in this model. * * @param column the column to be added * @see #addColumn */ @Override public void removeColumn(TableColumn column) { int allColumnsIndex = allTableColumns.indexOf(column); if(allColumnsIndex != -1) { allTableColumns.remove(allColumnsIndex); } super.removeColumn(column); } /** * Moves the column from <code>oldIndex</code> to <code>newIndex</code>. * Posts <code>columnMoved</code> event. * Will not move any columns if <code>oldIndex</code> equals <code>newIndex</code>. * * @throws IllegalArgumentException if either <code>oldIndex</code> or * <code>newIndex</code> * are not in [0, getColumnCount() - 1] * @param oldIndex index of column to be moved * @param newIndex new index of the column */ @Override public void moveColumn(int oldIndex, int newIndex) { if((oldIndex < 0) || (oldIndex >= getColumnCount()) || (newIndex < 0) || (newIndex >= getColumnCount())) { throw new IllegalArgumentException("moveColumn() - Index out of range"); } TableColumn fromColumn = tableColumns.get(oldIndex); TableColumn toColumn = tableColumns.get(newIndex); int allColumnsOldIndex = allTableColumns.indexOf(fromColumn); int allColumnsNewIndex = allTableColumns.indexOf(toColumn); if(oldIndex != newIndex) { allTableColumns.remove(allColumnsOldIndex); allTableColumns.add(allColumnsNewIndex, fromColumn); } super.moveColumn(oldIndex, newIndex); } /** * Returns the total number of columns in this model. * * @param onlyVisible if set only visible columns will be counted * @return the number of columns in the <code>tableColumns</code> array * @see #getColumns */ public int getColumnCount(boolean onlyVisible) { return (onlyVisible ? tableColumns.size() : allTableColumns.size()); } /** * Returns an <code>Enumeration</code> of all the columns in the model. * * @param onlyVisible if set all invisible columns will be missing from the enumeration. * @return an <code>Enumeration</code> of the columns in the model */ public Iterator<TableColumn> getColumns(boolean onlyVisible) { return (onlyVisible ? tableColumns.iterator() : allTableColumns.iterator()); } /** * Returns the position of the first column whose identifier equals <code>identifier</code>. * Position is the the index in all visible columns if <code>onlyVisible</code> is true or * else the index in all columns. * * @return the index of the first column whose identifier * equals <code>identifier</code> * @throws IllegalArgumentException if <code>identifier</code> * is <code>null</code>, or if no * <code>TableColumn</code> has this * <code>identifier</code> * @param identifier the identifier object to search for * @param onlyVisible if set searches only visible columns * @see #getColumn */ public int getColumnIndex(Object identifier, boolean onlyVisible) { if(identifier == null) { throw new IllegalArgumentException("Identifier is null"); } List<TableColumn> columns = (onlyVisible ? tableColumns : allTableColumns); int noColumns = columns.size(); TableColumn column; for(int columnIndex = 0; columnIndex < noColumns; ++columnIndex) { column = columns.get(columnIndex); if(identifier.equals(column.getIdentifier())) { return columnIndex; } } throw new IllegalArgumentException("Identifier not found"); } public List<TableColumnLayoutInfo> getColumnLayoutInfos() { final List<TableColumnLayoutInfo> tableColumnLayoutInfos = new ArrayList<>(allTableColumns.size()); for(TableColumn current : allTableColumns) { boolean visible = tableColumns.contains(current); TableColumnLayoutInfo tableColumnLayoutInfo = new TableColumnLayoutInfo(current.getIdentifier().toString(), current.getWidth(), visible); tableColumnLayoutInfos.add(tableColumnLayoutInfo); } return tableColumnLayoutInfos; } public static class TableColumnLayoutInfo implements Serializable { private static final long serialVersionUID = 8018128012962924414L; private String columnName; private int width; private boolean visible; public TableColumnLayoutInfo() { } public TableColumnLayoutInfo(String columnName, int width, boolean visible) { this.columnName = columnName; this.width = width; this.visible = visible; } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public String getColumnName() { return columnName; } public void setColumnName(String columnName) { this.columnName = columnName; } public boolean isVisible() { return visible; } public void setVisible(boolean visible) { this.visible = visible; } @Override public String toString() { return "TableColumnLayoutInfo[columnName=" + columnName + ", width=" + width + ", visible=" + visible + "]"; } } }