/**
* Copyright 2005 Open Cloud Ltd.
*
* 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 org.mobicents.eclipslee.servicecreation.ui.table;
import java.util.HashMap;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CheckboxCellEditor;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Scale;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
/**
* @author cath
* @author Vladimir Ralev
*/
public class EditableTableViewer extends TableViewer implements SelectionListener {
public static final int EDITOR_TEXT = 0;
public static final int EDITOR_CHECKBOX = 1;
public static final int EDITOR_CHOICE = 2;
public static final int EDITOR_BUTTON = 3;
public static final int EDITOR_NONE = 4; // Uneditable cell
public static final int EDITOR_NUMERIC = 5;
public static final int bigCellHeight = 22;
public static final int bigCellButtonWidth = 100;
Listener itemMeasureListener = new ItemMeasureListener();
public EditableTableViewer(Composite parent, int style, String columnNames[], int columnEditors[], Object editorValues[][]) {
super(parent, style|SWT.FULL_SELECTION);
this.columnNames = columnNames;
this.columnEditors = columnEditors;
this.columnValues = editorValues;
initialize(columnNames, columnEditors, editorValues);
}
public EditableTableViewer(Table table, String columnNames[], int columnEditors[], Object editorValues[][]) {
super(table);
this.columnNames = columnNames;
this.columnEditors = columnEditors;
this.columnValues = editorValues;
initialize(columnNames, columnEditors, editorValues);
}
public void initialize(String [] columnNames, int columnEditors[], Object editorValues[][]) {
if (columnNames.length != columnEditors.length && columnEditors.length != editorValues.length) {
throw new IllegalArgumentException("The size of the columnNames, columnEditors and editorValues arrays must be the same.");
}
getTable().addListener(SWT.MeasureItem, itemMeasureListener);
// Don't use a hash lookup as we're storing HashMaps in the store and the
// hashCode of these changes when the data inside them changes.
setUseHashlookup(false);
Table table = getTable();
CellEditor editors[] = new CellEditor[columnNames.length];
TableColumn tableColumns[] = new TableColumn[columnNames.length];
for (int i = 0; i < columnNames.length; i++) {
tableColumns[i] = new TableColumn(table, SWT.NONE);
tableColumns[i].setText(columnNames[i]);
tableColumns[i].setWidth(150);
tableColumns[i].setResizable(true);
tableColumns[i].pack();
}
setColumnProperties(columnNames);
for (int i = 0; i < columnEditors.length; i++) {
switch (columnEditors[i]) {
case EDITOR_TEXT:
editors[i] = new TextCellEditor(table);
break;
case EDITOR_CHECKBOX:
editors[i] = new CheckboxCellEditor(table);
break;
case EDITOR_CHOICE:
String vals[] = new String[editorValues[i].length];
for (int j = 0; j < editorValues[i].length; j++)
vals[j] = (String) editorValues[i][j];
editors[i] = new ComboBoxCellEditor(table, vals);
break;
case EDITOR_BUTTON:
case EDITOR_NUMERIC:
editors[i] = null;
break;
case EDITOR_NONE:
editors[i] = null;
break; // May need to use a TextCellEditor and make uneditable.
default:
// Error message about unrecognised cell editor.
System.err.println("Invalid cell editor value: " + columnEditors[i]);
}
}
setCellEditors(editors);
table.setHeaderVisible(true);
table.addSelectionListener(this);
store = new DataStore();
setContentProvider(new GenericContentProvider(this, store));
setInput(store);
setCellModifier(new GenericCellModifier(this, columnNames, columnEditors));
setLabelProvider(new GenericLabelProvider(columnNames, columnEditors, editorValues));
}
public void repack() {
TableColumn[] cols = getTable().getColumns();
for(int q=0; q<cols.length; q++) cols[q].pack();
// Try to force a redraw of the table - this may not redraw the buttons though.
getTable().layout(true);
// Try to force a redraw of the editors and buttons
Object data[] = store.getElements();
for (int i= 0; i < data.length; i++) {
HashMap map = (HashMap) data[i];
for (int column = 0; column < columnEditors.length; column++) {
if (columnEditors[column] == EDITOR_BUTTON) {
Button button = (Button) map.get("Button_" + column);
if (button != null) {
button.redraw();
button.getParent().layout(true);
}
TableEditor editor = (TableEditor) map.get("Editor_" + column);
if (editor != null) {
editor.layout();
}
}
if (columnEditors[column] == EDITOR_NUMERIC) {
Scale scale = (Scale) map.get("Scale_" + column);
if (scale != null) {
scale.redraw();
scale.getParent().layout(false);
}
TableEditor editor = (TableEditor) map.get("Editor_" + column);
if (editor != null) {
editor.layout();
}
}
}
}
}
public HashMap addRow(HashMap map) {
// Make the table lines visible
getTable().setLinesVisible(true);
store.add(map);
return map;
}
public HashMap addRow() {
// Make the table lines visible
getTable().setLinesVisible(true);
HashMap map = new HashMap();
// Initialize the HashMap with sensible values.
for (int i = 0; i < columnNames.length; i++) {
switch (columnEditors[i]) {
case EDITOR_CHECKBOX:
map.put(columnNames[i], Boolean.FALSE);
break;
case EDITOR_CHOICE:
map.put(columnNames[i], new Integer(0));
break;
case EDITOR_NUMERIC:
map.put(columnNames[i], new Integer(0));
break;
default:
map.put(columnNames[i], "?");
break;
}
}
store.add(map);
return map;
}
public void removeRow(HashMap map) {
store.remove(map);
}
public void remove(Object o) {
HashMap map = (HashMap) o;
for (int column = 0; column < columnEditors.length; column++) {
if (columnEditors[column] == EDITOR_BUTTON) {
if (map.get("Editor_" + column) != null) {
TableEditor editor = (TableEditor) map.get("Editor_" + column);
Button button = (Button) map.get("Button_" + column);
button.setVisible(false);
button.dispose();
editor.dispose();
map.remove("Editor_" + column);
map.remove("Button_" + column);
}
}
if (columnEditors[column] == EDITOR_NUMERIC) {
if (map.get("Editor_" + column) != null) {
TableEditor editor = (TableEditor) map.get("Editor_" + column);
Scale scale = (Scale) map.get("Scale_" + column);
scale.setVisible(false);
scale.dispose();
editor.dispose();
map.remove("Editor_" + column);
map.remove("Scale_" + column);
}
}
}
/*
* Ugly hack! Not needed for Eclipse 3.3, but Eclipse 3.2 has
* a bug http://dev.eclipse.org/newslists/news.eclipse.platform.swt/msg29738.html
* Reinstall the listener each time you remove seems to work.
*/
this.getTable().removeListener(SWT.MeasureItem, itemMeasureListener);
super.remove(o);
this.getTable().addListener(SWT.MeasureItem, itemMeasureListener);
}
public void add(Object o) {
super.add(o);
// Get all existing rows and find row(s) without a defined button.
// Create buttons for it.
Table table = getTable();
TableItem items[] = getTable().getItems();
for (int column = 0; column < columnEditors.length; column++) {
if (columnEditors[column] == EDITOR_BUTTON) {
for (int row = 0; row < items.length; row++) {
TableItem item = items[row];
HashMap map = (HashMap) item.getData();
if (map.get("Editor_" + column) == null) {
TableEditor editor = new TableEditor(table);
Button button = new Button(table, SWT.NONE);
String buttonText = (String) map.get("ButtonText_" + column);
if(buttonText == null)
button.setText((String) columnValues[column][0]);
else
button.setText(buttonText);
button.addSelectionListener((SelectionListener) columnValues[column][1]);
button.pack();
editor.grabHorizontal = true;
editor.minimumWidth = button.getSize().x;
editor.horizontalAlignment = SWT.LEFT;
editor.setEditor(button, item, column); // TableItem.getItems(row), column
map.put("Editor_" + column, editor);
map.put("Button_" + column, button);
}
}
}
if (columnEditors[column] == EDITOR_NUMERIC) {
for (int row = 0; row < items.length; row++) {
TableItem item = items[row];
HashMap map = (HashMap) item.getData();
if (map.get("Editor_" + column) == null) {
TableEditor editor = new TableEditor(table);
Scale scale = new Scale(table, SWT.NONE);
int min = ((Integer) columnValues[column][0]).intValue();
int max = ((Integer) columnValues[column][1]).intValue();
int increment = ((Integer) columnValues[column][2]).intValue();
scale.setMinimum(min);
scale.setMaximum(max);
scale.setIncrement(increment);
scale.pack();
editor.grabHorizontal = true;
editor.minimumWidth = scale.getSize().x;
editor.horizontalAlignment = SWT.LEFT;
editor.setEditor(scale, item, column);
map.put("Editor_" + column, editor);
map.put("Scale_" + column, scale);
}
}
}
}
}
public void widgetDefaultSelected(SelectionEvent event) {
}
public void widgetSelected(SelectionEvent event) {
// SWT.CHECK in object detail field means a check button changed value
if ((event.detail & SWT.CHECK) == SWT.CHECK) {
System.err.println("A checkbox changed value.");
}
}
public DataStore getStore() {
return store;
}
private class ItemMeasureListener implements Listener
{
public void handleEvent(Event event) {
if (bigCellHeight == SWT.DEFAULT) return;
event.height = bigCellHeight;
TableColumn column = getTable().getColumn(event.index);
TableItem ti = (TableItem) event.item;
HashMap map = (HashMap) ti.getData();
if (map.get("Button_" + event.index) != null)
event.width = bigCellButtonWidth;
}
}
protected DataStore store;
private String columnNames[];
private int columnEditors[];
private Object columnValues[][];
}