View Javadoc

1   /*
2    *  Copyright (C) 2003-2005 SINTEF
3    *  Author:  Fredrik Vraalsen (fredrik dot vraalsen at sintef dot no)
4    *  Webpage: http://coras.sourceforge.net/
5    *
6    *  This program is free software; you can redistribute it and/or
7    *  modify it under the terms of the GNU Lesser General Public License
8    *  as published by the Free Software Foundation; either version 2.1
9    *  of the License, or (at your option) any later version.
10   *
11   *  This program is distributed in the hope that it will be useful,
12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   *  Lesser General Public License for more details.
15   *
16   *  You should have received a copy of the GNU Lesser General Public
17   *  License along with this program; if not, write to the Free
18   *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19   *  02111-1307 USA
20   */
21  package coras.table;
22  
23  import java.awt.Component;
24  import java.awt.Dimension;
25  import java.awt.Font;
26  import java.awt.Rectangle;
27  import java.awt.event.ComponentAdapter;
28  import java.awt.event.ComponentEvent;
29  import java.awt.event.KeyAdapter;
30  import java.awt.event.KeyEvent;
31  import java.util.Collection;
32  
33  import javax.swing.AbstractCellEditor;
34  import javax.swing.Action;
35  import javax.swing.JTable;
36  import javax.swing.KeyStroke;
37  import javax.swing.event.DocumentEvent;
38  import javax.swing.event.DocumentListener;
39  import javax.swing.table.TableCellEditor;
40  import javax.swing.text.BadLocationException;
41  import javax.swing.text.JTextComponent;
42  import javax.swing.text.Keymap;
43  
44  /***
45   * @author fvr
46   *
47   * To change the template for this generated type comment go to
48   * Window - Preferences - Java - Code Generation - Code and Comments
49   */
50  public class TextAreaEditor extends AbstractCellEditor implements TableCellEditor {
51      
52  	private ChoiceTextArea textArea = new ChoiceTextArea();
53  	private Keymap keymap = null;
54  	private Action prevAction = null;
55  	private Action nextAction = null;
56  	private Action upAction = null;
57  	private Action downAction = null;
58  	private CorasTable table = null;
59  
60  	public TextAreaEditor() {
61  		super();
62  		keymap = JTextComponent.addKeymap("TextAreaEditorKeymap", textArea.getKeymap());
63  		textArea.setKeymap(keymap);
64  		textArea.setLineWrap(true);
65  		textArea.setWrapStyleWord(true);
66  		textArea.setFont(new Font("SansSerif", Font.PLAIN, 12));
67  
68  		textArea.addKeyListener(new KeyAdapter() {
69  			public void keyPressed(KeyEvent ev) {
70  				int key = ev.getKeyCode();
71  				if (key == KeyEvent.VK_UP || key == KeyEvent.VK_DOWN || key == KeyEvent.VK_RIGHT || key == KeyEvent.VK_LEFT) {
72  					try {
73  						int pos = textArea.getCaretPosition();
74  						int lastPos = textArea.getText().length();
75  						if (key == KeyEvent.VK_UP || key == KeyEvent.VK_DOWN) {
76  							Rectangle rect = textArea.modelToView(pos);
77  							int rowHeight = textArea.getRowHeight();
78  							int row = rect.y / rowHeight;
79  							int lastRow = (textArea.modelToView(lastPos).y / rowHeight); // textArea.getRows();
80  							if (key == KeyEvent.VK_UP && row == 0) {
81  								fireUpAction();
82  							} else if (key == KeyEvent.VK_DOWN && row == lastRow) {
83  								fireDownAction();
84  							}
85  						} else { // key == VK_RIGHT || VK_LEFT
86  							if (key == KeyEvent.VK_LEFT && pos == 0) {
87  								firePrevAction();
88  							} else if (key == KeyEvent.VK_RIGHT && pos == lastPos) {
89  								fireNextAction();
90  							}
91  						}
92  					} catch (BadLocationException e) {
93  						e.printStackTrace();
94  					}
95  				}
96  			}
97  		});
98  		
99  		textArea.addComponentListener(new ComponentAdapter() {
100 			public void componentResized(ComponentEvent e) {
101 				CorasTable localTable = table; // thread safety
102 				if (localTable != null) {
103 					localTable.updateRowHeight(localTable.getEditingRow());
104 				}
105 			}
106 			public void componentMoved(ComponentEvent e) {
107 				textArea.requestFocus(); // TODO: Not the best place to request focus???
108 			}
109 		});
110 		
111 		textArea.getDocument().addDocumentListener(new DocumentListener() {
112 			public void insertUpdate(DocumentEvent e) {
113 				updateTableModel();
114 			}
115 			public void removeUpdate(DocumentEvent e) {
116 				updateTableModel();
117 			}
118 			public void changedUpdate(DocumentEvent e) {
119 				updateTableModel();
120 			}
121 		});
122 	}
123 	
124 	
125 	/***
126 	 * 
127 	 */
128 	protected synchronized void fireNextAction() {
129 		if (nextAction != null)
130 			nextAction.actionPerformed(null);
131 	}
132 	
133 	/***
134 	 * 
135 	 */
136 	protected synchronized void firePrevAction() {
137 		if (prevAction != null)
138 			prevAction.actionPerformed(null);
139 	}
140 	
141 	/***
142 	 * 
143 	 */
144 	protected synchronized void fireDownAction() {
145 		if (downAction != null)
146 			downAction.actionPerformed(null);
147 	}
148 	
149 	/***
150 	 * 
151 	 */
152 	protected synchronized void fireUpAction() {
153 		if (upAction != null)
154 			upAction.actionPerformed(null);
155 	}
156 	
157 	public synchronized void setNextAction(Action a) {
158 		nextAction = a;
159 		setKeyStrokeAction(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), a);
160 	}
161 	
162 	public synchronized void setPrevAction(Action a) {
163 		prevAction = a;
164 		setKeyStrokeAction(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, KeyEvent.SHIFT_MASK), a);
165 	}
166 	
167 	public synchronized void setUpAction(Action a) {
168 		upAction = a;
169 	}
170 	
171 	public synchronized void setDownAction(Action a) {
172 		downAction = a;
173 	}
174 	
175 	private void setKeyStrokeAction(KeyStroke keyStroke, Action a) {
176 		if (a != null)
177 			keymap.addActionForKeyStroke(keyStroke, a);
178 		else
179 			keymap.removeKeyStrokeBinding(keyStroke);
180 	}
181 	
182 	/* (non-Javadoc)
183 	 * @see javax.swing.table.TableCellEditor#getTableCellEditorComponent(javax.swing.JTable, java.lang.Object, boolean, int, int)
184 	 */
185 	public Component getTableCellEditorComponent(final JTable table, Object value,
186 			boolean isSelected, final int row, final int column) {
187 		if (table instanceof CorasTable) {
188 			this.table = (CorasTable) table;
189 			CorasTableModel tableModel = (CorasTableModel) table.getModel();
190 			Collection choices = tableModel.getColumnChoices(column);
191 //			textArea.setToolTipText(choices != null ? "Right click for choices" : null);
192 			textArea.setChoices(choices);
193 			textArea.setUserEditable(tableModel.isUserEditable(column));
194 		} else {
195 			this.table = null;
196 			textArea.setChoices(null);
197 			textArea.setUserEditable(true);
198 		}
199 		if (value instanceof String) {
200 			textArea.setText((String) value);
201 		} else {
202 			textArea.setText(value != null ? value.toString() : "");
203 		}
204 		return textArea;
205 	}
206 	
207 	/* (non-Javadoc)
208 	 * @see javax.swing.CellEditor#getCellEditorValue()
209 	 */
210 	public Object getCellEditorValue() {
211 		String result = textArea.getText();
212 		return result;
213 	}
214 	
215 	public Dimension getPreferredSize() {
216 		return textArea.getPreferredSize();
217 	}
218 	
219 	private void updateTableModel() {
220 		int row = table.getEditingRow();
221 		int col = table.getEditingColumn();
222 		if (row == -1 || col == -1) {
223 			return;
224 		}
225 		CorasTableModel tableModel = (CorasTableModel) table.getModel();
226 		tableModel.setValueAt(getCellEditorValue(), row, col);
227 	}
228 }