1 package com.quantum.view;
3 import java.sql.SQLException;
4 import java.util.ArrayList;
5 import java.util.LinkedList;
7 import java.util.NoSuchElementException;
9 import org.eclipse.jface.action.Action;
10 import org.eclipse.jface.action.IToolBarManager;
11 import org.eclipse.jface.action.Separator;
12 import org.eclipse.jface.preference.IPreferenceStore;
13 import org.eclipse.jface.preference.PreferenceConverter;
14 import org.eclipse.jface.util.IPropertyChangeListener;
15 import org.eclipse.jface.util.PropertyChangeEvent;
16 import org.eclipse.jface.viewers.ILabelProvider;
17 import org.eclipse.jface.viewers.ILabelProviderListener;
18 import org.eclipse.jface.viewers.IStructuredContentProvider;
19 import org.eclipse.jface.viewers.Viewer;
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.custom.ExtendedModifyEvent;
22 import org.eclipse.swt.custom.ExtendedModifyListener;
23 import org.eclipse.swt.custom.StyleRange;
24 import org.eclipse.swt.custom.StyledText;
25 import org.eclipse.swt.graphics.Color;
26 import org.eclipse.swt.graphics.Font;
27 import org.eclipse.swt.graphics.FontData;
28 import org.eclipse.swt.graphics.Image;
29 import org.eclipse.swt.layout.GridData;
30 import org.eclipse.swt.layout.GridLayout;
31 import org.eclipse.swt.widgets.Composite;
32 import org.eclipse.swt.widgets.Display;
33 import org.eclipse.ui.IActionBars;
34 import org.eclipse.ui.IWorkbenchActionConstants;
35 import org.eclipse.ui.part.ViewPart;
37 import com.quantum.ImageStore;
38 import com.quantum.Messages;
39 import com.quantum.PluginPreferences;
40 import com.quantum.QuantumPlugin;
41 import com.quantum.actions.ExecuteAction;
42 import com.quantum.actions.ExportQueryAction;
43 import com.quantum.actions.ImportQueryAction;
44 import com.quantum.editors.ColorManager;
45 import com.quantum.model.Bookmark;
46 import com.quantum.model.BookmarkCollection;
47 import com.quantum.model.NotConnectedException;
48 import com.quantum.sql.MultiSQLServer;
49 import com.quantum.sql.SQLGrammar;
50 import com.quantum.sql.parser.SQLLexx;
51 import com.quantum.sql.parser.Token;
52 import com.quantum.ui.dialog.ExceptionDisplayDialog;
53 import com.quantum.ui.dialog.SQLExceptionDialog;
54 import com.quantum.util.versioning.VersioningHelper;
56 public class SQLQueryView extends ViewPart {
57 private class ClearAction extends Action {
59 public ClearAction() {
60 setImageDescriptor(ImageStore.getImageDescriptor(ImageStore.CLEAR));
61 setToolTipText(Messages.getString("sqlqueryview.clear"));
69 private class AutoCommitPreferenceAction extends Action {
71 public AutoCommitPreferenceAction() {
72 super(Messages.getString("SQLQueryView.AutoCommit"));
73 setToolTipText(Messages.getString("SQLQueryView.AutoCommit"));
74 setImageDescriptor(ImageStore.getImageDescriptor(ImageStore.AUTOCOMMIT));
78 setAutoCommitPreference(isChecked());
82 private class RollbackAction extends Action {
83 public RollbackAction() {
84 setText(Messages.getString("SQLQueryView.RollBack"));
85 setToolTipText(Messages.getString("SQLQueryView.RollBack"));
89 Bookmark[] bookmarks = BookmarkCollection.getInstance().getBookmarks();
90 for (int i = 0, length = bookmarks == null ? 0 : bookmarks.length; i < length; i++) {
92 if (bookmarks[i].isConnected() && !bookmarks[i].getConnection().getAutoCommit()) {
93 MultiSQLServer.getInstance().rollback(bookmarks[i].getConnection());
95 } catch (SQLException e) {
96 SQLExceptionDialog.openException(getSite().getShell(), bookmarks[i], e);
97 } catch (NotConnectedException e) {
98 ExceptionDisplayDialog.openError(getSite().getShell(), null, null, e);
105 private class CommitAction extends Action {
106 public CommitAction() {
107 setText(Messages.getString("SQLQueryView.Commit"));
108 setToolTipText(Messages.getString("SQLQueryView.Commit"));
112 Bookmark[] bookmarks = BookmarkCollection.getInstance().getBookmarks();
113 for (int i = 0, length = bookmarks == null ? 0 : bookmarks.length; i < length; i++) {
115 if (bookmarks[i].isConnected() && !bookmarks[i].getConnection().getAutoCommit()) {
116 MultiSQLServer.getInstance().commit(bookmarks[i].getConnection());
118 } catch (SQLException e) {
119 SQLExceptionDialog.openException(getSite().getShell(), bookmarks[i], e);
120 } catch (NotConnectedException e) {
121 ExceptionDisplayDialog.openError(getSite().getShell(), null, null, e);
128 public class LabelProviderImpl implements ILabelProvider {
129 public Image getImage(Object element) {
130 return ImageStore.getImage(ImageStore.BOOKMARK);
132 public String getText(Object element) {
133 if (element instanceof Bookmark) {
134 return ((Bookmark) element).getName();
139 public void addListener(ILabelProviderListener listener) {
141 public void dispose() {
143 public boolean isLabelProperty(Object element, String property) {
146 public void removeListener(ILabelProviderListener listener) {
149 public class ContentProviderImpl implements IStructuredContentProvider {
150 public Object[] getElements(Object inputElement) {
151 if (inputElement instanceof BookmarkCollection) {
152 return ((BookmarkCollection) inputElement).getBookmarks();
157 public void dispose() {
159 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
163 private ExecuteAction executeAction;
164 private ImportQueryAction importQueryAction;
165 private ExportQueryAction exportQueryAction;
166 private StyledText widget;
167 private AutoCommitPreferenceAction autoCommitPreferenceAction;
168 private RollbackAction rollbackAction;
169 private CommitAction commitAction;
170 private boolean autoCommitPreference = true;
171 private IPropertyChangeListener listener;
172 private ColorManager colorManager = new ColorManager();
174 private SyntaxHighlighter textUpdater = new SyntaxHighlighter(this.colorManager);
177 public SQLQueryView() {
179 this.listener = new IPropertyChangeListener() {
180 public void propertyChange(PropertyChangeEvent event) {
184 QuantumPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(listener);
187 public void dispose() {
188 QuantumPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this.listener);
189 this.colorManager.dispose();
193 public static SQLQueryView getInstance() {
194 return (SQLQueryView) QuantumPlugin.getDefault().getView("com.quantum.view.sqlqueryview");
198 public void createPartControl(org.eclipse.swt.widgets.Composite parent) {
201 initializeColours(parent);
202 GridLayout layout = new GridLayout(1, false);
203 layout.horizontalSpacing = 0;
204 layout.verticalSpacing = 0;
205 layout.marginHeight = 0;
206 layout.marginWidth = 0;
207 parent.setLayout(layout);
208 parent.setLayoutData(new GridData(GridData.FILL_BOTH));
210 widget = new StyledText(parent, SWT.H_SCROLL | SWT.V_SCROLL);
214 IActionBars bars = this.getViewSite().getActionBars();
215 bars.setGlobalActionHandler(IWorkbenchActionConstants.CUT, cutAction);
216 bars.setGlobalActionHandler(IWorkbenchActionConstants.COPY, copyAction);
217 bars.setGlobalActionHandler(IWorkbenchActionConstants.PASTE, pasteAction);
218 bars.setGlobalActionHandler(IWorkbenchActionConstants.SELECT_ALL, selectAllAction);
220 widget.setEditable(true);
221 widget.addExtendedModifyListener(modifyListener);
223 widget.setLayoutData(new GridData(GridData.FILL_BOTH));
225 VersioningHelper.registerActionToKeyBindingService(getSite(),
226 new String[] { "org.eclipse.ui.globalScope", "com.quantum.view.sql" },
230 private void setFont() {
231 FontData font = PreferenceConverter.getFontData(
232 QuantumPlugin.getDefault().getPreferenceStore(),
233 "quantum.font"); //$NON-NLS-1$
234 if (font != null && this.widget != null) {
235 this.widget.setFont(new Font(Display.getCurrent(), font));
241 private void initializeColours(Composite parent) {
242 IPreferenceStore store = QuantumPlugin.getDefault().getPreferenceStore();
244 parent.setBackground(this.colorManager.getColor(
245 PreferenceConverter.getColor(store, PluginPreferences.BACKGROUND_COLOR)));
246 this.textUpdater.initializeColours();
249 private void initActions() {
251 IToolBarManager toolBar = getViewSite().getActionBars().getToolBarManager();
253 executeAction = new ExecuteAction(this);
254 toolBar.add(this.executeAction);
255 toolBar.add(new ClearAction());
257 IActionBars actionBars = getViewSite().getActionBars();
258 this.importQueryAction = new ImportQueryAction();
259 this.importQueryAction.init(this);
260 actionBars.getMenuManager().add(this.importQueryAction);
261 this.exportQueryAction = new ExportQueryAction();
262 this.exportQueryAction.init(this);
263 actionBars.getMenuManager().add(this.exportQueryAction);
264 actionBars.getMenuManager().add(new Separator());
265 this.autoCommitPreferenceAction = new AutoCommitPreferenceAction();
266 this.autoCommitPreferenceAction.setChecked(this.autoCommitPreference);
267 actionBars.getMenuManager().add(this.autoCommitPreferenceAction);
269 this.rollbackAction = new RollbackAction();
270 actionBars.getMenuManager().add(this.rollbackAction);
272 this.commitAction = new CommitAction();
273 actionBars.getMenuManager().add(this.commitAction);
277 * Returns the query to be executed. The query is either 1) the
278 * text currently highlighted/selected in the editor or 2) all of
279 * the text in the editor.
280 * @return query string to be executed
282 public String getQuery() {
285 if (widget.getSelectionText().length() > 0)
286 query = widget.getSelectionText();
288 query = widget.getText();
293 public void setQuery(String text) {
294 widget.setText(text);
297 private class UpdateRequest {
298 public UpdateRequest(String text, int start, int length) {
301 this.length = length;
308 private class SyntaxHighlighter extends Thread {
310 private Color STRING_LITERAL;
311 private Color KEYWORD;
312 private Color COMMENT;
313 private Color NUMERIC;
314 private Color DEFAULT;
316 private boolean running = true;
317 private LinkedList requests = new LinkedList();
318 private final ColorManager colorManager;
319 public SyntaxHighlighter(ColorManager colorManager) {
321 this.colorManager = colorManager;
323 setPriority(Thread.MIN_PRIORITY);
326 public void initializeColours() {
327 IPreferenceStore store = QuantumPlugin.getDefault().getPreferenceStore();
329 this.DEFAULT = this.colorManager.getColor(
330 PreferenceConverter.getColor(store, PluginPreferences.TEXT_COLOR));
331 this.KEYWORD = this.colorManager.getColor(
332 PreferenceConverter.getColor(store, PluginPreferences.KEYWORD_COLOR));
333 this.STRING_LITERAL = this.colorManager.getColor(
334 PreferenceConverter.getColor(store, PluginPreferences.STRING_COLOR));
335 this.COMMENT = this.colorManager.getColor(
336 PreferenceConverter.getColor(store, PluginPreferences.COMMENT_COLOR));
337 this.NUMERIC = this.colorManager.getColor(
338 PreferenceConverter.getColor(store, PluginPreferences.NUMERIC_COLOR));
341 public synchronized void updateText(String text, int start, int length) {
342 requests.add(new UpdateRequest(text, start, length));
348 synchronized (this) {
349 if (requests.size() <= 0) {
355 UpdateRequest request = (UpdateRequest) requests.removeFirst();
356 String text = request.text.toUpperCase();
357 //int dirtyStart = request.start;
358 //int dirtyEnd = request.start + request.length;
359 StyleRange styleRange;
360 List tokens = SQLLexx.parse(text);
361 List styles = new ArrayList();
362 int min = Integer.MAX_VALUE;
364 for (int i = 0; i < tokens.size(); i++) {
365 Token t = (Token) tokens.get(i);
366 String value = t.getValue();
367 int start = t.getStart();
368 int length = t.getEnd() - t.getStart();
369 styleRange = new StyleRange();
370 styleRange.start = start;
371 styleRange.length = value.length();
372 styleRange.fontStyle = SWT.NULL;
373 styleRange.foreground = DEFAULT;
374 //boolean upper = start <= dirtyEnd && start >= dirtyStart;
375 //boolean lower = ((start + length) >= dirtyStart && (start + length) <= dirtyEnd);
376 //boolean both = (start <= dirtyStart && (start + length) >= dirtyEnd);
377 //if (upper || lower || both) {
378 if (true) { // Let's update the whole text, as some comment changes can alter everything
379 min = Math.min(start, min);
380 max = Math.max(max, start + length);
381 if (t.getType() == Token.IDENTIFIER) {
382 boolean keyword = false;
383 for (int index = 0; index < SQLGrammar.KEYWORDS.length; index++) {
384 if (value.equals(SQLGrammar.KEYWORDS[index])) {
389 styleRange.fontStyle = SWT.BOLD;
390 styleRange.foreground = KEYWORD;
392 styleRange.foreground = DEFAULT;
394 styles.add(styleRange);
395 } else if (t.getType() == Token.COMMENT) {
396 styleRange.foreground = COMMENT;
397 styles.add(styleRange);
398 } else if (t.getType() == Token.LITERAL) {
399 styleRange.foreground = STRING_LITERAL;
400 styles.add(styleRange);
401 } else if (t.getType() == Token.NUMERIC) {
402 styleRange.foreground = NUMERIC;
403 styles.add(styleRange);
405 styles.add(styleRange);
409 StyleRange[] ranges =
410 (StyleRange[]) styles.toArray(new StyleRange[styles.size()]);
411 if (max >= 0 && ranges.length > 0) {
412 setStyles(ranges, min, max - min);
414 } catch (NoSuchElementException e) {
415 // ignore a missing request
416 } catch (InterruptedException e) {
417 // ignore any interruptions
422 public void setStyles(final StyleRange[] styles, final int start, final int length) {
423 getViewSite().getShell().getDisplay().asyncExec(new Runnable() {
426 for (int i = 0; i < styles.length; i++) {
427 widget.setStyleRange(styles[i]);
429 } catch (Throwable t) {
430 System.out.println("Error with styles: " + t.getClass().toString()); //$NON-NLS-1$
437 ExtendedModifyListener modifyListener = new ExtendedModifyListener() {
438 public void modifyText(ExtendedModifyEvent event) {
439 textUpdater.updateText(getQuery(), event.start, event.length);
443 private Action cutAction = new Action() {
448 private Action copyAction = new Action() {
453 private Action pasteAction = new Action() {
458 private Action selectAllAction = new Action() {
464 public void setFocus() {
466 public boolean isAutoCommitPreference() {
467 return this.autoCommitPreference;
469 public void setAutoCommitPreference(boolean autoCommitPreference) {
470 this.autoCommitPreference = autoCommitPreference;