summaryrefslogtreecommitdiffstats
path: root/dozentenmodul/src/main/java/org/openslx/dozmod/gui/changemonitor/TableWrapper.java
blob: 6bff2671ac886b93b769787daf9066d88405ae83 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package org.openslx.dozmod.gui.changemonitor;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Comparator;

import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;

/**
 * Monitoring a JTable etc.
 */
class TableWrapper extends AbstractControlWrapper<ClonedTableModel> {
	
	private static final Comparator<ClonedTableModel> COMPARATOR = new Comparator<ClonedTableModel>() {
		public int compare(ClonedTableModel o1, ClonedTableModel o2) {
			if (o1 == null && o2 == null)
				return 0;
			if (o1 == null)
				return -o2.rowCount;
			if (o2 == null)
				return o1.rowCount;
			if (o1.rowCount != o2.rowCount)
				return o2.rowCount - o1.rowCount;
			if (o1.columnCount != o2.columnCount)
				return o2.columnCount - o1.columnCount;
			for (int i = 0; i < o1.grid.length; ++i) {
				Object c1 = o1.grid[i];
				Object c2 = o2.grid[i];
				if (c1 == c2)
					continue;
				if (c1 == null)
					return c2.hashCode();
				if (c2 == null)
					return c1.hashCode();
				if (c1.equals(c2))
					continue;
				return c1.hashCode() - c2.hashCode();
			}
			return 0;
		}
	};
	
	private final JTable component;

	public TableWrapper(DialogChangeMonitor dcm, JTable table) {
		super(dcm, COMPARATOR);
		this.component = table;
		
		final TableModelListener changeListener = new TableModelListener() {
			public void tableChanged(TableModelEvent e) {
				contentChanged();
			}
		};

		// Make sure we notice when the whole model changes
		table.addPropertyChangeListener("model", new PropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent evt) {
				Object o = evt.getOldValue();
				Object n = evt.getNewValue();
				if (o != null && o instanceof TableModel) {
					((TableModel)o).removeTableModelListener(changeListener);
				}
				if (n != null && n instanceof TableModel) {
					((TableModel)n).addTableModelListener(changeListener);
				}
			}
		});
		// Add listener to the current model
		if (table.getModel() != null) {
			table.getModel().addTableModelListener(changeListener);
		}
	}

	ClonedTableModel getCurrentValue() {
		TableModel model = component.getModel();
		if (model == null)
			return null;
		return new ClonedTableModel(model);
	}
}

class ClonedTableModel implements TableModel {
	
	protected final Object[] grid;
	protected final int columnCount, rowCount;
	
	protected ClonedTableModel(TableModel other) {
		columnCount = other.getColumnCount();
		rowCount = other.getRowCount();
		grid = new Object[columnCount * rowCount];
		for (int y = 0; y < rowCount; ++y) {
			for (int x = 0; x < columnCount; ++x) {
				// Hopefully we mostly deal with imutable types so we don't need clone
				grid[y * columnCount + x] = other.getValueAt(y, x);
			}
		}
	}

	@Override
	public int getRowCount() {
		return rowCount;
	}

	@Override
	public int getColumnCount() {
		return columnCount;
	}

	@Override
	public String getColumnName(int columnIndex) {
		return null;
	}

	@Override
	public Class<?> getColumnClass(int columnIndex) {
		if (grid[columnIndex] == null)
			return Object.class;
		return grid[columnIndex].getClass();
	}

	@Override
	public boolean isCellEditable(int rowIndex, int columnIndex) {
		return false;
	}

	@Override
	public Object getValueAt(int rowIndex, int columnIndex) {
		return grid[rowIndex * rowCount + columnCount];
	}

	@Override
	public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
		throw new RuntimeException("A cloned table model is read only");
	}

	@Override
	public void addTableModelListener(TableModelListener l) {
		throw new RuntimeException("A cloned table model is read only");
	}

	@Override
	public void removeTableModelListener(TableModelListener l) {
		throw new RuntimeException("A cloned table model is read only");
	}
	
}