svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.expressionevaluator / org.gvsig.expressionevaluator.swing / org.gvsig.expressionevaluator.swing.impl / src / main / java / org / gvsig / expressionevaluator / swing / impl / DefaultCalculatorController.java @ 44644
History | View | Annotate | Download (10.7 KB)
1 | 44076 | jjdelcerro | package org.gvsig.expressionevaluator.swing.impl; |
---|---|---|---|
2 | |||
3 | 44080 | jjdelcerro | import java.awt.Color; |
4 | import java.awt.event.ActionEvent; |
||
5 | import java.awt.event.ActionListener; |
||
6 | import java.awt.event.FocusEvent; |
||
7 | import java.awt.event.FocusListener; |
||
8 | 44098 | jjdelcerro | import java.awt.event.KeyAdapter; |
9 | import java.awt.event.KeyEvent; |
||
10 | 44076 | jjdelcerro | import org.gvsig.expressionevaluator.swing.CalculatorController; |
11 | import java.util.Objects; |
||
12 | 44080 | jjdelcerro | import javax.swing.AbstractAction; |
13 | import javax.swing.Action; |
||
14 | import javax.swing.JPopupMenu; |
||
15 | 44098 | jjdelcerro | import javax.swing.Timer; |
16 | import javax.swing.event.ChangeEvent; |
||
17 | import javax.swing.event.ChangeListener; |
||
18 | import javax.swing.event.DocumentEvent; |
||
19 | import javax.swing.event.DocumentListener; |
||
20 | 44076 | jjdelcerro | import javax.swing.text.JTextComponent; |
21 | 44080 | jjdelcerro | import org.apache.commons.lang3.StringUtils; |
22 | import org.gvsig.expressionevaluator.Expression; |
||
23 | 44076 | jjdelcerro | import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator; |
24 | import org.gvsig.expressionevaluator.ExpressionEvaluatorManager; |
||
25 | 44098 | jjdelcerro | import org.gvsig.expressionevaluator.ExpressionSyntaxException; |
26 | 44076 | jjdelcerro | import org.gvsig.expressionevaluator.MutableSymbolTable; |
27 | import org.gvsig.expressionevaluator.SymbolTable; |
||
28 | 44080 | jjdelcerro | import org.gvsig.expressionevaluator.swing.ExpressionEvaluatorSwingManager; |
29 | 44076 | jjdelcerro | import org.gvsig.tools.dataTypes.DataTypes; |
30 | import org.gvsig.tools.ToolsLocator; |
||
31 | import org.gvsig.tools.dataTypes.CoercionException; |
||
32 | import org.gvsig.tools.dataTypes.DataTypesManager; |
||
33 | 44080 | jjdelcerro | import org.gvsig.tools.i18n.I18nManager; |
34 | 44098 | jjdelcerro | import org.gvsig.tools.swing.api.ChangeListenerHelper; |
35 | 44080 | jjdelcerro | import org.gvsig.tools.swing.api.ToolsSwingLocator; |
36 | import org.gvsig.tools.swing.api.ToolsSwingManager; |
||
37 | import org.gvsig.tools.swing.api.windowmanager.Dialog; |
||
38 | import org.gvsig.tools.swing.api.windowmanager.WindowManager; |
||
39 | import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2; |
||
40 | 44098 | jjdelcerro | import org.slf4j.Logger; |
41 | import org.slf4j.LoggerFactory; |
||
42 | 44076 | jjdelcerro | |
43 | /**
|
||
44 | *
|
||
45 | * @author jjdelcerro
|
||
46 | */
|
||
47 | 44080 | jjdelcerro | @SuppressWarnings("UseSpecificCatch") |
48 | 44098 | jjdelcerro | class DefaultCalculatorController<T> |
49 | implements CalculatorController<T> , ChangeListenerHelper
|
||
50 | { |
||
51 | |||
52 | private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCalculatorController.class); |
||
53 | 44076 | jjdelcerro | |
54 | 44080 | jjdelcerro | private static final Color COLOR_ERROR = new Color(255,225,232); |
55 | |||
56 | 44076 | jjdelcerro | private final JTextComponent text; |
57 | private final int dataType; |
||
58 | private final MutableSymbolTable defaultSymbolTable; |
||
59 | 44098 | jjdelcerro | private final Color color_ok; |
60 | private final ExpressionEvaluatorSwingManager swingManager; |
||
61 | 44080 | jjdelcerro | private DefaultExpressionBuilderConfig config;
|
62 | private Expression expression; |
||
63 | 44098 | jjdelcerro | private boolean warning; |
64 | private final ChangeListenerHelper changeListenerHelper; |
||
65 | private final Timer fireChangeTimer; |
||
66 | private String lastText; |
||
67 | private final ExpressionEvaluatorManager manager; |
||
68 | 44076 | jjdelcerro | |
69 | 44080 | jjdelcerro | public DefaultCalculatorController(ExpressionEvaluatorSwingManager manager, final JTextComponent text, int dataType) { |
70 | 44098 | jjdelcerro | ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager(); |
71 | 44080 | jjdelcerro | I18nManager i18n = ToolsLocator.getI18nManager(); |
72 | |||
73 | 44098 | jjdelcerro | this.swingManager = manager;
|
74 | this.manager = ExpressionEvaluatorLocator.getManager();
|
||
75 | 44080 | jjdelcerro | this.config = null; |
76 | this.expression = null; |
||
77 | 44098 | jjdelcerro | this.warning = false; |
78 | this.changeListenerHelper = toolsSwingManager.createChangeListenerHelper();
|
||
79 | |||
80 | 44076 | jjdelcerro | this.text = text;
|
81 | this.dataType = dataType;
|
||
82 | 44098 | jjdelcerro | this.color_ok = this.text.getBackground(); |
83 | 44076 | jjdelcerro | this.defaultSymbolTable = ExpressionEvaluatorLocator.getManager().createSymbolTable();
|
84 | 44098 | jjdelcerro | this.text.addKeyListener(new KeyAdapter() { |
85 | @Override
|
||
86 | public void keyPressed(KeyEvent e) { |
||
87 | if( e.getKeyCode()==KeyEvent.VK_C && e.isControlDown() ) { |
||
88 | doCalculate(true);
|
||
89 | } |
||
90 | } |
||
91 | }); |
||
92 | this.text.getDocument().addDocumentListener(new DocumentListener() { |
||
93 | @Override
|
||
94 | public void insertUpdate(DocumentEvent e) { |
||
95 | fireChangeEvent(); |
||
96 | } |
||
97 | |||
98 | @Override
|
||
99 | public void removeUpdate(DocumentEvent e) { |
||
100 | fireChangeEvent(); |
||
101 | } |
||
102 | |||
103 | @Override
|
||
104 | public void changedUpdate(DocumentEvent e) { |
||
105 | fireChangeEvent(); |
||
106 | } |
||
107 | }); |
||
108 | 44080 | jjdelcerro | this.text.addFocusListener(new FocusListener() { |
109 | @Override
|
||
110 | public void focusLost(FocusEvent e) { |
||
111 | 44098 | jjdelcerro | doCalculate(true);
|
112 | 44080 | jjdelcerro | } |
113 | |||
114 | @Override
|
||
115 | public void focusGained(FocusEvent e) { |
||
116 | 44098 | jjdelcerro | doCalculate(true);
|
117 | 44080 | jjdelcerro | } |
118 | }); |
||
119 | 44098 | jjdelcerro | toolsSwingManager.addClearButton(this.text, new ActionListener() { |
120 | 44080 | jjdelcerro | @Override
|
121 | public void actionPerformed(ActionEvent e) { |
||
122 | set(null);
|
||
123 | } |
||
124 | }); |
||
125 | 44098 | jjdelcerro | toolsSwingManager.setDefaultPopupMenu(this.text);
|
126 | 44080 | jjdelcerro | JPopupMenu popupMenu = this.text.getComponentPopupMenu(); |
127 | Action showExpressionBuilderAction = new AbstractAction(i18n.getTranslation("_Show_expression_builder")) { |
||
128 | @Override
|
||
129 | public void actionPerformed(ActionEvent e) { |
||
130 | doShowExpressionBuilder(); |
||
131 | } |
||
132 | }; |
||
133 | popupMenu.addSeparator(); |
||
134 | popupMenu.add(showExpressionBuilderAction); |
||
135 | 44098 | jjdelcerro | this.fireChangeTimer = new Timer(100, new ActionListener() { |
136 | @Override
|
||
137 | public void actionPerformed(ActionEvent e) { |
||
138 | fireEvent(); |
||
139 | } |
||
140 | }); |
||
141 | 44076 | jjdelcerro | } |
142 | |||
143 | 44098 | jjdelcerro | private void fireChangeEvent() { |
144 | this.fireChangeTimer.setRepeats(false); |
||
145 | this.fireChangeTimer.restart();
|
||
146 | } |
||
147 | |||
148 | 44080 | jjdelcerro | private void doShowExpressionBuilder() { |
149 | if( this.config == null ) { |
||
150 | 44098 | jjdelcerro | this.config = new DefaultExpressionBuilderConfig(this.swingManager); |
151 | 44080 | jjdelcerro | this.config.addSymbolTable(this.defaultSymbolTable); |
152 | } |
||
153 | if( this.expression == null ) { |
||
154 | this.expression = ExpressionEvaluatorLocator.getManager().createExpression();
|
||
155 | } |
||
156 | expression.setPhrase(this.text.getText());
|
||
157 | |||
158 | 44098 | jjdelcerro | DefaultJExpressionBuilder panel = new DefaultJExpressionBuilder(this.swingManager, this.config); |
159 | 44080 | jjdelcerro | panel.setExpression(this.expression);
|
160 | |||
161 | WindowManager_v2 windowManager = (WindowManager_v2) ToolsSwingLocator.getWindowManager(); |
||
162 | Dialog dialog = windowManager.createDialog(
|
||
163 | panel.asJComponent(), |
||
164 | "Expression builder",
|
||
165 | null,
|
||
166 | WindowManager_v2.BUTTONS_OK_CANCEL |
||
167 | ); |
||
168 | dialog.show(WindowManager.MODE.DIALOG); |
||
169 | if( dialog.getAction()==WindowManager_v2.BUTTON_OK ) {
|
||
170 | this.text.setText(panel.getExpression().getPhrase());
|
||
171 | } |
||
172 | } |
||
173 | |||
174 | 44076 | jjdelcerro | @Override
|
175 | public void addSymbolTable(SymbolTable symbolTable) { |
||
176 | this.defaultSymbolTable.addSymbolTable(symbolTable);
|
||
177 | } |
||
178 | |||
179 | @Override
|
||
180 | public MutableSymbolTable getSymbolTable() {
|
||
181 | return this.defaultSymbolTable; |
||
182 | } |
||
183 | |||
184 | 44098 | jjdelcerro | private Object doCalculate(boolean updateText) { |
185 | 44148 | jjdelcerro | if( !this.text.isEditable() ||!this.text.isEnabled() ) { |
186 | 44098 | jjdelcerro | return null; |
187 | 44080 | jjdelcerro | } |
188 | String source = this.text.getText(); |
||
189 | try {
|
||
190 | if( !StringUtils.isBlank(source) ) {
|
||
191 | 44098 | jjdelcerro | final Object value = this.manager.evaluate(this.defaultSymbolTable, source); |
192 | if( updateText ) {
|
||
193 | String s = Utils.repr(value);
|
||
194 | if( !StringUtils.equals(s, this.lastText) ) { |
||
195 | this.setWarning(false); |
||
196 | this.lastText = s;
|
||
197 | this.text.setText(this.lastText); |
||
198 | } |
||
199 | } |
||
200 | return value;
|
||
201 | 44080 | jjdelcerro | } |
202 | 44098 | jjdelcerro | this.setWarning(false); |
203 | } catch (ExpressionSyntaxException ex) {
|
||
204 | this.setWarning(true, ex.getDescription()); |
||
205 | 44080 | jjdelcerro | } catch (Exception ex) { |
206 | 44098 | jjdelcerro | this.setWarning(true); |
207 | } |
||
208 | return null; |
||
209 | } |
||
210 | |||
211 | public void setWarning(boolean warning) { |
||
212 | this.setWarning(warning, null); |
||
213 | } |
||
214 | |||
215 | public void setWarning(boolean warning, String description) { |
||
216 | this.warning = warning;
|
||
217 | if( warning ) {
|
||
218 | 44080 | jjdelcerro | this.text.setBackground(COLOR_ERROR);
|
219 | 44098 | jjdelcerro | this.text.setToolTipText(description==null?"":description); |
220 | } else {
|
||
221 | this.text.setBackground(this.color_ok); |
||
222 | this.text.setToolTipText(""); |
||
223 | 44080 | jjdelcerro | } |
224 | } |
||
225 | 44098 | jjdelcerro | |
226 | @Override
|
||
227 | public boolean getWarning() { |
||
228 | return warning;
|
||
229 | } |
||
230 | 44152 | jjdelcerro | |
231 | @Override
|
||
232 | public T get(T defaultValue) {
|
||
233 | T v = this.get();
|
||
234 | if( v==null ) { |
||
235 | return defaultValue;
|
||
236 | } |
||
237 | return v;
|
||
238 | } |
||
239 | 44080 | jjdelcerro | |
240 | 44076 | jjdelcerro | @Override
|
241 | public T get() {
|
||
242 | 44148 | jjdelcerro | Object value;
|
243 | if( !this.text.isEditable() ||!this.text.isEnabled() ) { |
||
244 | value = this.text.getText();
|
||
245 | } else {
|
||
246 | value = doCalculate(false);
|
||
247 | } |
||
248 | 44076 | jjdelcerro | try {
|
249 | 44080 | jjdelcerro | DataTypesManager dataManager = ToolsLocator.getDataTypesManager(); |
250 | value = dataManager.coerce(this.dataType, value);
|
||
251 | 44076 | jjdelcerro | return (T) value;
|
252 | } catch (CoercionException ex) {
|
||
253 | return null; |
||
254 | } |
||
255 | } |
||
256 | |||
257 | @Override
|
||
258 | public void set(T value) { |
||
259 | this.text.setText(Objects.toString(value, "")); |
||
260 | 44098 | jjdelcerro | this.text.setBackground(this.color_ok); |
261 | 44076 | jjdelcerro | } |
262 | |||
263 | @Override
|
||
264 | public void coerceAndSet(Object value) { |
||
265 | if (this.dataType != DataTypes.OBJECT) { |
||
266 | DataTypesManager dataManager = ToolsLocator.getDataTypesManager(); |
||
267 | try {
|
||
268 | value = dataManager.coerce(this.dataType, value);
|
||
269 | } catch (CoercionException ex) {
|
||
270 | } |
||
271 | } |
||
272 | this.text.setText(Objects.toString(value, "")); |
||
273 | 44098 | jjdelcerro | this.text.setBackground(this.color_ok); |
274 | 44076 | jjdelcerro | } |
275 | |||
276 | @Override
|
||
277 | public void setEnabled(boolean enabled) { |
||
278 | this.text.setEnabled(enabled);
|
||
279 | } |
||
280 | |||
281 | @Override
|
||
282 | public boolean isEnabled() { |
||
283 | return this.text.isEnabled(); |
||
284 | } |
||
285 | |||
286 | 44080 | jjdelcerro | @Override
|
287 | public void setEditable(boolean editable) { |
||
288 | this.text.setEditable(editable);
|
||
289 | } |
||
290 | |||
291 | @Override
|
||
292 | public boolean isEditable() { |
||
293 | return this.text.isEditable(); |
||
294 | } |
||
295 | 44098 | jjdelcerro | |
296 | @Override
|
||
297 | public void addChangeListener(ChangeListener cl) { |
||
298 | this.changeListenerHelper.addChangeListener(cl);
|
||
299 | } |
||
300 | |||
301 | @Override
|
||
302 | public ChangeListener[] getChangeListeners() { |
||
303 | return this.changeListenerHelper.getChangeListeners(); |
||
304 | } |
||
305 | |||
306 | @Override
|
||
307 | public void removeChangeListener(ChangeListener cl) { |
||
308 | this.changeListenerHelper.removeAllChangeListener();
|
||
309 | } |
||
310 | |||
311 | @Override
|
||
312 | public void removeAllChangeListener() { |
||
313 | this.changeListenerHelper.removeAllChangeListener();
|
||
314 | } |
||
315 | |||
316 | @Override
|
||
317 | public boolean hasChangeListeners() { |
||
318 | return this.changeListenerHelper.hasChangeListeners(); |
||
319 | } |
||
320 | |||
321 | @Override
|
||
322 | public void fireEvent() { |
||
323 | this.changeListenerHelper.fireEvent();
|
||
324 | } |
||
325 | |||
326 | @Override
|
||
327 | public void fireEvent(ChangeEvent ce) { |
||
328 | this.changeListenerHelper.fireEvent(ce);
|
||
329 | } |
||
330 | 44080 | jjdelcerro | |
331 | 44076 | jjdelcerro | } |