KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > db > sql > loader > SQLCloneableEditor


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.db.sql.loader;
21
22 import java.awt.Component JavaDoc;
23 import java.awt.KeyboardFocusManager JavaDoc;
24 import java.beans.PropertyChangeEvent JavaDoc;
25 import java.beans.PropertyChangeListener JavaDoc;
26 import java.beans.PropertyChangeSupport JavaDoc;
27 import java.io.IOException JavaDoc;
28 import javax.swing.Action JavaDoc;
29 import javax.swing.ActionMap JavaDoc;
30 import javax.swing.JComponent JavaDoc;
31 import javax.swing.JEditorPane JavaDoc;
32 import javax.swing.JPanel JavaDoc;
33 import javax.swing.JSplitPane JavaDoc;
34 import javax.swing.SwingUtilities JavaDoc;
35 import javax.swing.text.BadLocationException JavaDoc;
36 import javax.swing.text.Document JavaDoc;
37 import org.netbeans.api.db.explorer.DatabaseConnection;
38 import org.netbeans.modules.db.api.sql.execute.SQLExecution;
39 import org.netbeans.modules.db.sql.execute.ui.SQLResultPanel;
40 import org.openide.ErrorManager;
41 import org.openide.text.CloneableEditor;
42 import org.openide.util.Lookup;
43 import org.openide.util.Mutex;
44 import org.openide.util.lookup.AbstractLookup;
45 import org.openide.util.lookup.InstanceContent;
46 import org.openide.util.lookup.ProxyLookup;
47 import org.openide.windows.TopComponent;
48
49 /**
50  * Cloneable editor for SQL. It it was opened as a console,
51  * it saves its document when its is deactivated or serialized. Also has
52  * a SQLExecution implementation in its lookup.
53  *
54  * @author Andrei Badea
55  */

56 public class SQLCloneableEditor extends CloneableEditor {
57
58     private transient JPanel JavaDoc container;
59     private transient JSplitPane JavaDoc splitter;
60     private transient SQLResultPanel resultComponent;
61
62     private transient SQLExecutionImpl sqlExecution;
63
64     private transient Lookup originalLookup;
65
66     private transient InstanceContent instanceContent = new InstanceContent();
67     private transient Lookup ourLookup = new AbstractLookup(instanceContent);
68
69     private transient SQLCloneableEditorLookup resultingLookup;
70
71     public SQLCloneableEditor() {
72         super(null);
73     }
74
75     public SQLCloneableEditor(SQLEditorSupport support) {
76         super(support);
77         initialize();
78     }
79
80     public boolean hasResultComponent() {
81         return resultComponent != null;
82     }
83
84     public SQLResultPanel getResultComponent() {
85         assert SwingUtilities.isEventDispatchThread();
86         if (resultComponent == null) {
87             createResultComponent();
88         }
89         return resultComponent;
90     }
91
92     private void createResultComponent() {
93         JPanel JavaDoc container = findContainer(this);
94         if (container == null) {
95             // the editor has just been deserialized and has not been initialized yet
96
// thus CES.wrapEditorComponent() has not been called yet
97
return;
98         }
99
100         Component JavaDoc editor = container.getComponent(0);
101         container.removeAll();
102
103         resultComponent = new SQLResultPanel();
104         splitter = new JSplitPane JavaDoc(JSplitPane.VERTICAL_SPLIT, editor, resultComponent);
105         splitter.setBorder(null);
106
107         container.add(splitter);
108         splitter.setDividerLocation(250);
109         splitter.setDividerSize(7);
110
111         container.invalidate();
112         container.validate();
113         container.repaint();
114
115         // #69642: the parent of the CloneableEditor's ActionMap is
116
// the editor pane's ActionMap, therefore the delete action is always returned by the
117
// CloneableEditor's ActionMap.get(). This workaround delegates to the editor pane
118
// only when the editor pane has the focus.
119
getActionMap().setParent(new DelegateActionMap(getActionMap().getParent(), getEditorPane()));
120
121         if (equals(TopComponent.getRegistry().getActivated())) {
122             // setting back the focus lost when removing the editor from the CloneableEditor
123
requestFocusInWindow();
124         }
125     }
126
127     /**
128      * Finds the container component added by SQLEditorSupport.wrapEditorComponent.
129      * Not very nice, but avoids the API change in #69466.
130      */

131     private JPanel JavaDoc findContainer(Component JavaDoc parent) {
132         if (!(parent instanceof JComponent JavaDoc)) {
133             return null;
134         }
135         Component JavaDoc[] components = ((JComponent JavaDoc)parent).getComponents();
136         for (int i = 0; i < components.length; i++) {
137             Component JavaDoc component = components[i];
138             if (component instanceof JPanel JavaDoc && SQLEditorSupport.EDITOR_CONTAINER.equals(component.getName())) {
139                 return (JPanel JavaDoc)component;
140             }
141             JPanel JavaDoc container = findContainer(component);
142             if (container != null) {
143                 return container;
144             }
145         }
146         return null;
147     }
148
149     public synchronized Lookup getLookup() {
150         Lookup currentLookup = super.getLookup();
151         if (currentLookup != originalLookup) {
152             originalLookup = currentLookup;
153             if (resultingLookup == null) {
154                 resultingLookup = new SQLCloneableEditorLookup();
155             }
156             resultingLookup.updateLookups(new Lookup[] { originalLookup, ourLookup });
157         }
158         return resultingLookup;
159     }
160
161     protected void componentDeactivated() {
162         if (sqlEditorSupport().isConsole()) {
163             try {
164                 cloneableEditorSupport().saveDocument();
165             } catch (IOException JavaDoc e) {
166                 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
167             }
168         }
169         super.componentDeactivated();
170     }
171
172     protected void componentClosed() {
173         sqlExecution.editorClosed();
174         super.componentClosed();
175     }
176
177     public void writeExternal(java.io.ObjectOutput JavaDoc out) throws IOException JavaDoc {
178         if (sqlEditorSupport().isConsole()) {
179             try {
180                 cloneableEditorSupport().saveDocument();
181             } catch (IOException JavaDoc e) {
182                 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
183             }
184         }
185         super.writeExternal(out);
186     }
187
188     public void readExternal(java.io.ObjectInput JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
189         super.readExternal(in);
190         initialize();
191     }
192
193     private void initialize() {
194         sqlExecution = new SQLExecutionImpl();
195         instanceContent.add(sqlExecution);
196     }
197
198     private SQLEditorSupport sqlEditorSupport() {
199         return (SQLEditorSupport)cloneableEditorSupport();
200     }
201
202     private static final class DelegateActionMap extends ActionMap JavaDoc {
203
204         private ActionMap JavaDoc delegate;
205         private JEditorPane JavaDoc editorPane;
206
207         public DelegateActionMap(ActionMap JavaDoc delegate, JEditorPane JavaDoc editorPane) {
208             this.delegate = delegate;
209             this.editorPane = editorPane;
210         }
211
212         public void remove(Object JavaDoc key) {
213
214             super.remove(key);
215         }
216
217         public javax.swing.Action JavaDoc get(Object JavaDoc key) {
218             boolean isEditorPaneFocused = KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner() == editorPane;
219             if (isEditorPaneFocused) {
220                 return delegate.get(key);
221             } else {
222                 return null;
223             }
224         }
225
226         public void put(Object JavaDoc key, Action JavaDoc action) {
227             delegate.put(key, action);
228         }
229
230         public void setParent(ActionMap JavaDoc map) {
231             delegate.setParent(map);
232         }
233
234         public int size() {
235             return delegate.size();
236         }
237
238         public Object JavaDoc[] keys() {
239             return delegate.keys();
240         }
241
242         public ActionMap JavaDoc getParent() {
243             return delegate.getParent();
244         }
245
246         public void clear() {
247             delegate.clear();
248         }
249
250         public Object JavaDoc[] allKeys() {
251             return delegate.allKeys();
252         }
253     }
254
255     private static final class SQLCloneableEditorLookup extends ProxyLookup {
256
257         public SQLCloneableEditorLookup() {
258             super(new Lookup[0]);
259         }
260
261         public void updateLookups(Lookup[] lookups) {
262             setLookups(lookups);
263         }
264     }
265
266     /**
267      * Implementation of SQLExecution delegating to the editor's SQLEditorSupport.
268      */

269     private final class SQLExecutionImpl implements SQLExecution, PropertyChangeListener JavaDoc {
270
271         // we add the property change listeners to our own support instead of
272
// the editor's one to ensure the editor does not reference e.g. actions
273
// which forgot the remove their listeners. the editor would
274
// prevent them from begin GCd (since the editor's life will usually
275
// be longer than that of the actions)
276
private final PropertyChangeSupport JavaDoc propChangeSupport = new PropertyChangeSupport JavaDoc(this);
277
278         public SQLExecutionImpl() {
279             sqlEditorSupport().addSQLPropertyChangeListener(this);
280         }
281
282         private void editorClosed() {
283             sqlEditorSupport().removeSQLPropertyChangeListener(this);
284         }
285
286         public void propertyChange(PropertyChangeEvent JavaDoc event) {
287             propChangeSupport.firePropertyChange(event);
288         }
289
290         public void addPropertyChangeListener(PropertyChangeListener JavaDoc listener) {
291             propChangeSupport.addPropertyChangeListener(listener);
292         }
293
294         public void removePropertyChangeListener(PropertyChangeListener JavaDoc listener) {
295             propChangeSupport.removePropertyChangeListener(listener);
296         }
297
298         public DatabaseConnection getDatabaseConnection() {
299             return sqlEditorSupport().getDatabaseConnection();
300         }
301
302         public void setDatabaseConnection(DatabaseConnection dbconn) {
303             sqlEditorSupport().setDatabaseConnection(dbconn);
304         }
305
306         public void execute() {
307             String JavaDoc text = Mutex.EVENT.readAccess(new Mutex.Action<String JavaDoc>() {
308                 public String JavaDoc run() {
309                     return getText(getEditorPane());
310                 }
311             });
312             sqlEditorSupport().execute(text, 0, text.length());
313         }
314
315         public void executeSelection() {
316             final int[] offsets = new int[2];
317             String JavaDoc text = Mutex.EVENT.readAccess(new Mutex.Action<String JavaDoc>() {
318                 public String JavaDoc run() {
319                     JEditorPane JavaDoc editorPane = getEditorPane();
320                     int startOffset = editorPane.getSelectionStart();
321                     int endOffset = editorPane.getSelectionEnd();
322                     if (startOffset == endOffset) {
323                         // there is no selection, execute the statement under
324
// the caret
325
offsets[0] = offsets[1] = editorPane.getCaretPosition();
326                     } else {
327                         offsets[0] = startOffset;
328                         offsets[1] = endOffset;
329                     }
330                     return getText(editorPane);
331                 }
332             });
333             sqlEditorSupport().execute(text, offsets[0], offsets[1]);
334         }
335
336         public boolean isExecuting() {
337             return sqlEditorSupport().isExecuting();
338         }
339
340         public boolean isSelection() {
341             Boolean JavaDoc result = Mutex.EVENT.readAccess(new Mutex.Action<Boolean JavaDoc>() {
342                 public Boolean JavaDoc run() {
343                     JEditorPane JavaDoc editorPane = getEditorPane();
344                     return Boolean.valueOf(editorPane.getSelectionStart() < editorPane.getSelectionEnd());
345                 }
346             });
347             return result.booleanValue();
348         }
349         
350         public String JavaDoc toString() {
351             return "SQLExecution[support=" + sqlEditorSupport().messageName() + ", dbconn=" + sqlEditorSupport().getDatabaseConnection() + "]"; // NOI18N
352
}
353         
354         private String JavaDoc getText(JEditorPane JavaDoc editorPane) {
355             // issue 75529: must not use the simpler JEditorPane.getText()
356
// since we want to obtain the text from the document, which has
357
// line ends normalized to '\n'
358
Document JavaDoc doc = editorPane.getDocument();
359             try {
360                 return doc.getText(0, doc.getLength());
361             } catch (BadLocationException JavaDoc e) {
362                 // should not happen
363
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
364                 return ""; // NOI18N
365
}
366         }
367     }
368 }
369
Popular Tags