001: package net.sourceforge.squirrel_sql.plugins.syntax.netbeans;
002:
003: import java.awt.Event;
004: import java.awt.Font;
005: import java.awt.event.ActionEvent;
006: import java.awt.event.KeyEvent;
007: import java.awt.event.MouseEvent;
008:
009: import javax.swing.AbstractAction;
010: import javax.swing.Action;
011: import javax.swing.JEditorPane;
012: import javax.swing.KeyStroke;
013: import javax.swing.event.UndoableEditListener;
014: import javax.swing.text.Document;
015: import javax.swing.undo.UndoManager;
016:
017: import net.sourceforge.squirrel_sql.client.session.ISession;
018: import net.sourceforge.squirrel_sql.client.session.event.SessionAdapter;
019: import net.sourceforge.squirrel_sql.client.session.event.SessionEvent;
020: import net.sourceforge.squirrel_sql.client.session.parser.ParserEventsAdapter;
021: import net.sourceforge.squirrel_sql.client.session.parser.IParserEventsProcessor;
022: import net.sourceforge.squirrel_sql.client.session.parser.kernel.ErrorInfo;
023: import net.sourceforge.squirrel_sql.fw.id.IIdentifier;
024: import net.sourceforge.squirrel_sql.plugins.syntax.KeyManager;
025: import net.sourceforge.squirrel_sql.plugins.syntax.SyntaxPreferences;
026: import net.sourceforge.squirrel_sql.plugins.syntax.SyntaxPugin;
027:
028: import org.netbeans.editor.BaseDocument;
029: import org.netbeans.editor.BaseSettingsInitializer;
030: import org.netbeans.editor.Settings;
031:
032: public class NetbeansSQLEditorPane extends JEditorPane {
033: /**
034: *
035: */
036: private static final long serialVersionUID = -7433339152923153176L;
037: private boolean _parsingInitialized;
038: private ISession _session;
039: private ErrorInfo[] _currentErrorInfos = new ErrorInfo[0];
040: private SyntaxPreferences _prefs;
041: private SyntaxFactory _syntaxFactory;
042: private SyntaxPugin _plugin;
043:
044: private IIdentifier _sqlEntryPanelIdentifier;
045: private SessionAdapter _sessionListener;
046: private NetbeansPropertiesWrapper _propertiesWrapper;
047:
048: public NetbeansSQLEditorPane(ISession session,
049: SyntaxPreferences prefs, SyntaxFactory syntaxFactory,
050: SyntaxPugin plugin, IIdentifier sqlEntryPanelIdentifier,
051: NetbeansPropertiesWrapper propertiesWrapper) {
052: _session = session;
053:
054: _prefs = prefs;
055: _syntaxFactory = syntaxFactory;
056: _plugin = plugin;
057: _sqlEntryPanelIdentifier = sqlEntryPanelIdentifier;
058: _propertiesWrapper = propertiesWrapper;
059:
060: _syntaxFactory.putEditorPane(_session, this );
061:
062: Settings.removeInitializer(BaseSettingsInitializer.NAME);
063: Settings.addInitializer(new BaseSettingsInitializer(),
064: Settings.CORE_LEVEL);
065: /////////////////////////////////////////////////////////////////////////////////
066: // There are a lot of goodies in the ExtSettingsInitializer
067: // that might be interesting in th future.
068: // Unfortunately some conflicts with some of Squirrels shortcuts
069: // are in ExtSettingsInitializer
070: //Settings.removeInitializer(ExtSettingsInitializer.NAME);
071: //Settings.addInitializer(new ExtSettingsInitializer(), Settings.CORE_LEVEL);
072: //
073: /////////////////////////////////////////////////////////////////////////////
074: Settings.removeInitializer(SQLSettingsInitializer.NAME);
075:
076: Font font = _session.getProperties().getFontInfo().createFont();
077: Settings.addInitializer(new SQLSettingsInitializer(
078: SQLKit.class, _prefs, font, _plugin));
079:
080: //////////////////////////////////////////////////////////////////////////////////////////
081: //Needs to be done at this moment. That's why we can't call updateFromPreferences() here.
082: setEditorKit(new SQLKit(syntaxFactory));
083: //
084: //////////////////////////////////////////////////////////////////////////////////////////
085:
086: modifyKeyStrokes();
087:
088: Document doc = getDocument();
089: _syntaxFactory.putDocument(_session, _propertiesWrapper, doc);
090:
091: _sessionListener = new SessionAdapter() {
092: public void sessionClosed(SessionEvent evt) {
093: dispose(evt);
094: }
095: };
096: _session.getApplication().getSessionManager()
097: .addSessionListener(_sessionListener);
098:
099: setToolTipText("Just to make getToolTiptext() to be called");
100:
101: new KeyManager(this );
102: }
103:
104: private void modifyKeyStrokes() {
105: //////////////////////////////////////////////////////////////////////////////////////////////////////////////
106: // The ctrl enter short cut in the Netbeans editor is set in org.netbeans.editor.ext.BaseKit
107: // to the org.netbeans.editor.ext.BaseKit.SplitLineAction.
108: // Since the ctrl enter shorcut is a basic SQuirreL short cut and is defined via the main menu action
109: // we must remove this binding here.
110: KeyStroke ctrlEnterStroke = KeyStroke.getKeyStroke(
111: KeyEvent.VK_ENTER, java.awt.event.InputEvent.CTRL_MASK);
112: getKeymap().removeKeyStrokeBinding(ctrlEnterStroke);
113:
114: // Removed for the SQLBookmark Plugin
115: KeyStroke ctrlJStroke = KeyStroke.getKeyStroke(KeyEvent.VK_J,
116: java.awt.event.InputEvent.CTRL_MASK);
117: getKeymap().removeKeyStrokeBinding(ctrlJStroke);
118:
119: // Removed for the tools popup
120: KeyStroke ctrlTStroke = KeyStroke.getKeyStroke(KeyEvent.VK_T,
121: java.awt.event.InputEvent.CTRL_MASK);
122: getKeymap().removeKeyStrokeBinding(ctrlTStroke);
123:
124: // Removed for reformatting
125: KeyStroke ctrlShiftFStroke = KeyStroke.getKeyStroke(
126: KeyEvent.VK_F, java.awt.event.InputEvent.CTRL_MASK
127: | java.awt.event.InputEvent.SHIFT_MASK);
128: getKeymap().removeKeyStrokeBinding(ctrlShiftFStroke);
129:
130: // Removed for duplicate line
131: KeyStroke ctrlDStroke = KeyStroke.getKeyStroke(KeyEvent.VK_D,
132: java.awt.event.InputEvent.CTRL_MASK);
133: getKeymap().removeKeyStrokeBinding(ctrlDStroke);
134:
135: // Removed for comment
136: KeyStroke ctrlSubstractStroke = KeyStroke.getKeyStroke(
137: KeyEvent.VK_SUBTRACT,
138: java.awt.event.InputEvent.CTRL_MASK);
139: getKeymap().removeKeyStrokeBinding(ctrlSubstractStroke);
140:
141: // Removed for uncomment
142: KeyStroke ctrlShiftSubstractStroke = KeyStroke.getKeyStroke(
143: KeyEvent.VK_SUBTRACT,
144: java.awt.event.InputEvent.CTRL_MASK
145: | java.awt.event.InputEvent.SHIFT_MASK);
146: getKeymap().removeKeyStrokeBinding(ctrlShiftSubstractStroke);
147:
148: // Removed for cut SQL
149: KeyStroke ctrlShiftXStroke = KeyStroke.getKeyStroke(
150: KeyEvent.VK_X, java.awt.event.InputEvent.CTRL_MASK
151: | java.awt.event.InputEvent.SHIFT_MASK);
152: getKeymap().removeKeyStrokeBinding(ctrlShiftXStroke);
153:
154: // Removed for copy SQL
155: KeyStroke ctrlShiftCStroke = KeyStroke.getKeyStroke(
156: KeyEvent.VK_C, java.awt.event.InputEvent.CTRL_MASK
157: | java.awt.event.InputEvent.SHIFT_MASK);
158: getKeymap().removeKeyStrokeBinding(ctrlShiftCStroke);
159:
160: //
161: ///////////////////////////////////////////////////////////////////////////////////////////////////////////
162:
163: ////////////////////////////////////////////////////////////
164: // The parser didn't get triggered on shift+insert.
165: // We do it here by hand
166: KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_INSERT,
167: Event.SHIFT_MASK);
168: final Action origAction = getKeymap().getAction(ks);
169: Action triggerParserAction = new AbstractAction() {
170: private static final long serialVersionUID = 1158324060321498929L;
171:
172: public void actionPerformed(ActionEvent e) {
173: // This event does not always hit the righr editor !?
174: // That's why we can't use _sqlEntryPanelIdentifier
175: origAction.actionPerformed(e);
176: if (_session.getActiveSessionWindow().hasSQLPanelAPI()) {
177: IIdentifier entryPanelId = _session
178: .getSQLPanelAPIOfActiveSessionWindow()
179: .getSQLEntryPanel().getIdentifier();
180: triggerParser(entryPanelId);
181: }
182: }
183: };
184: //
185: //////////////////////////////////////////////////////////
186:
187: getKeymap().addActionForKeyStroke(ks, triggerParserAction);
188: }
189:
190: private void triggerParser(IIdentifier entryPanelId) {
191: IParserEventsProcessor parserEventsProcessor = _propertiesWrapper
192: .getParserEventsProcessor(entryPanelId, _session);
193:
194: if (null != parserEventsProcessor) {
195: parserEventsProcessor.triggerParser();
196: }
197: }
198:
199: public void updateFromPreferences() {
200: Settings.removeInitializer(BaseSettingsInitializer.NAME);
201: Settings.addInitializer(new BaseSettingsInitializer(),
202: Settings.CORE_LEVEL);
203: /////////////////////////////////////////////////////////////////////////////////
204: // There are a lot of goodies in the ExtSettingsInitializer
205: // that might be interesting in th future.
206: // Unfortunately some conflicts with some of Squirrels shortcuts
207: // are in ExtSettingsInitializer
208: //Settings.removeInitializer(ExtSettingsInitializer.NAME);
209: //Settings.addInitializer(new ExtSettingsInitializer(), Settings.CORE_LEVEL);
210: //
211: /////////////////////////////////////////////////////////////////////////////
212: Settings.removeInitializer(SQLSettingsInitializer.NAME);
213:
214: Font font = _session.getProperties().getFontInfo().createFont();
215: Settings.addInitializer(new SQLSettingsInitializer(
216: SQLKit.class, _prefs, font, _plugin));
217:
218: modifyKeyStrokes();
219:
220: Document doc = getDocument();
221: _syntaxFactory.putDocument(_session, _propertiesWrapper, doc);
222:
223: }
224:
225: public String getToolTipText(MouseEvent event) {
226: int pos = viewToModel(event.getPoint());
227:
228: initParsing();
229:
230: for (int i = 0; i < _currentErrorInfos.length; i++) {
231: if (_currentErrorInfos[i].beginPos - 1 <= pos
232: && pos <= _currentErrorInfos[i].endPos) {
233: return _currentErrorInfos[i].message;
234: }
235: }
236:
237: return null;
238: }
239:
240: private void initParsing() {
241: if (false == _parsingInitialized
242: && null != _propertiesWrapper.getParserEventsProcessor(
243: _sqlEntryPanelIdentifier, _session)) {
244: _parsingInitialized = true;
245: _propertiesWrapper.getParserEventsProcessor(
246: _sqlEntryPanelIdentifier, _session)
247: .addParserEventsListener(new ParserEventsAdapter() {
248: public void errorsFound(ErrorInfo[] errorInfos) {
249: onErrorsFound(errorInfos);
250: }
251: });
252: }
253: }
254:
255: private void onErrorsFound(ErrorInfo[] errorInfos) {
256: _currentErrorInfos = errorInfos;
257: }
258:
259: public String getText() {
260: return super .getText().replaceAll("\r\n", "\n");
261: }
262:
263: public void addUndoableEditListener(UndoableEditListener um) {
264: getDocument().addUndoableEditListener(um);
265: }
266:
267: public void setUndoManager(UndoManager manager) {
268: getDocument().addUndoableEditListener(manager);
269: getDocument().putProperty(BaseDocument.UNDO_MANAGER_PROP,
270: manager);
271: }
272:
273: public IIdentifier getSqlEntryPanelIdentifier() {
274: return _sqlEntryPanelIdentifier;
275: }
276:
277: private void dispose(SessionEvent evt) {
278: if (evt.getSession().getIdentifier().equals(
279: _session.getIdentifier())) {
280: // The SQLSettingsInitializer added above holds a reference to the
281: // SyntaxPreferences of the current Session which itself holds a
282: // reference to the Session. We remove the SQLSettingsInitializer
283: // to give the Session the chance to get Garbage Collected.
284: Settings.removeInitializer(SQLSettingsInitializer.NAME);
285:
286: // With an hanging SessionListener a Session nvere gets Garbage Collected.
287: _session.getApplication().getSessionManager()
288: .removeSessionListener(_sessionListener);
289:
290: // I thought this prevented GC. It doesn't
291: // But if two Sessions are open and one is closed the one left open looses
292: // key bindings. For example the Arrow navigation keys.
293: //getKeymap().removeBindings();
294:
295: _session = null;
296: }
297: }
298: }
|