/*
* Copyright 2013 Hewlett-Packard Development Company, L.P
*
* 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 com.hp.alm.ali.idea.ui;
import com.hp.alm.ali.idea.model.ItemsProvider;
import com.hp.alm.ali.idea.model.KeyValue;
import com.hp.alm.ali.idea.translate.Translator;
import com.hp.alm.ali.idea.translate.ValueCallback;
import com.intellij.util.ui.UIUtil;
import javax.swing.table.AbstractTableModel;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class MultipleItemsDialogModel<K, E extends KeyValue<K>> extends AbstractTableModel {
private String columnName;
private boolean multiple;
private ItemsProvider<E> provider;
private List<E> allFields;
private List<K> selectedFields;
private boolean additional;
private Translator translator;
private boolean showingSelected;
private boolean ignoreSelectionChange;
public MultipleItemsDialogModel(String columnName, boolean multiple, ItemsProvider<E> provider, List<K> selectedFields, Translator translator) {
this.columnName = columnName;
this.multiple = multiple;
this.provider = provider;
this.selectedFields = selectedFields;
this.translator = translator;
allFields = new ArrayList<E>();
}
@Override
public int getRowCount() {
if(showingSelected) {
return selectedFields.size();
} else {
return allFields.size();
}
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public Class getColumnClass(int col) {
if(col == 0) {
return Boolean.class;
} else {
return String.class;
}
}
@Override
public Object getValueAt(final int row, int col) {
if(showingSelected) {
if(col == 0) {
return true;
} else {
K key = selectedFields.get(row);
for(E field: allFields) {
if(field.getKey().equals(key)) {
return field.getValue();
}
}
if(translator != null) {
return translator.translate(key.toString(), new ValueCallback() {
@Override
public void value(String value) {
fireTableRowsUpdated(row, row);
}
});
}
return key;
}
} else {
KeyValue<K> field = allFields.get(row);
if(col == 0) {
return selectedFields.contains(field.getKey());
} else {
return field.getValue();
}
}
}
@Override
public void setValueAt(Object o, int row, int col) {
if(ignoreSelectionChange) {
// keep selection when switching to/from showingSelected
} else if(showingSelected) {
if(Boolean.FALSE.equals(o)) {
selectedFields.remove(row);
// removal causes structural change, need to update whole table
fireTableDataChanged();
}
} else {
KeyValue<K> field = allFields.get(row);
if(Boolean.TRUE.equals(o)) {
if(!selectedFields.contains(field.getKey())) {
if(!isMultiple() && !selectedFields.isEmpty()) {
selectedFields.clear();
selectedFields.add(field.getKey());
fireTableRowsUpdated(0, allFields.size() - 1);
} else {
selectedFields.add(field.getKey());
fireTableRowsUpdated(row, row);
}
}
} else if(selectedFields.remove(field.getKey())) {
fireTableRowsUpdated(row, row);
}
// NOTE: fireTableCellUpdated(row, col) is not enough if filter is specified for (un)selected fields
// there is probably no reason to complicate things here, simply update whole table on every update...W
}
}
@Override
public String getColumnName(int col) {
if(col == 0) {
return "";
} else {
return columnName;
}
}
@Override
public boolean isCellEditable(int row, int col) {
return col == 0;
}
public void fireTableDataChanged() {
ignoreSelectionChange = true;
try {
super.fireTableDataChanged();
} finally {
ignoreSelectionChange = false;
}
}
public void setShowingSelected(boolean showingSelected) {
if(showingSelected != this.showingSelected) {
this.showingSelected = showingSelected;
fireTableDataChanged();
}
}
public boolean isShowingSelected() {
return showingSelected;
}
public boolean isMultiple() {
return multiple;
}
public List<K> getSelectedFields() {
return selectedFields;
}
public List<E> getFields() {
return allFields;
}
public void load(String filter) {
final LinkedList<E> data = new LinkedList<E>();
final boolean more = provider.load(filter, data);
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
allFields.clear();
allFields.addAll(data);
additional = more;
fireTableDataChanged();
}
});
}
public boolean hasMore() {
return additional;
}
}