fixed Bug 1024299
[phpeclipse.git] / archive / net.sourceforge.phpeclipse.quantum.sql / src / com / quantum / view / SQLQueryView.java
1 package com.quantum.view;
2
3 import java.sql.SQLException;
4 import java.util.ArrayList;
5 import java.util.LinkedList;
6 import java.util.List;
7 import java.util.NoSuchElementException;
8 import java.util.Vector;
9
10 import com.quantum.ImageStore;
11 import com.quantum.Messages;
12 import com.quantum.PluginPreferences;
13 import com.quantum.QuantumPlugin;
14 import com.quantum.actions.ExecuteAction;
15 import com.quantum.actions.ExportQueryAction;
16 import com.quantum.actions.ImportQueryAction;
17 import com.quantum.editors.ColorManager;
18 import com.quantum.model.Bookmark;
19 import com.quantum.model.BookmarkCollection;
20 import com.quantum.model.NotConnectedException;
21 import com.quantum.sql.MultiSQLServer;
22 import com.quantum.sql.SQLGrammar;
23 import com.quantum.sql.parser.SQLLexx;
24 import com.quantum.sql.parser.Token;
25 import com.quantum.ui.dialog.ExceptionDisplayDialog;
26 import com.quantum.ui.dialog.SQLExceptionDialog;
27 import com.quantum.util.versioning.VersioningHelper;
28
29 import org.eclipse.jface.action.Action;
30 import org.eclipse.jface.action.IToolBarManager;
31 import org.eclipse.jface.action.Separator;
32 import org.eclipse.jface.preference.IPreferenceStore;
33 import org.eclipse.jface.preference.PreferenceConverter;
34 import org.eclipse.jface.util.IPropertyChangeListener;
35 import org.eclipse.jface.util.PropertyChangeEvent;
36 import org.eclipse.jface.viewers.ILabelProvider;
37 import org.eclipse.jface.viewers.ILabelProviderListener;
38 import org.eclipse.jface.viewers.IStructuredContentProvider;
39 import org.eclipse.jface.viewers.Viewer;
40 import org.eclipse.swt.SWT;
41 import org.eclipse.swt.custom.ExtendedModifyEvent;
42 import org.eclipse.swt.custom.ExtendedModifyListener;
43 import org.eclipse.swt.custom.StyleRange;
44 import org.eclipse.swt.custom.StyledText;
45 import org.eclipse.swt.dnd.Clipboard;
46 import org.eclipse.swt.dnd.TransferData;
47 import org.eclipse.swt.graphics.Color;
48 import org.eclipse.swt.graphics.Font;
49 import org.eclipse.swt.graphics.FontData;
50 import org.eclipse.swt.graphics.Image;
51 import org.eclipse.swt.layout.GridData;
52 import org.eclipse.swt.layout.GridLayout;
53 import org.eclipse.swt.widgets.Composite;
54 import org.eclipse.swt.widgets.Display;
55 import org.eclipse.ui.IActionBars;
56 import org.eclipse.ui.IWorkbenchActionConstants;
57 import org.eclipse.ui.part.ViewPart;
58
59 public class SQLQueryView extends ViewPart {
60         private class ClearAction extends Action {
61                 
62                 public ClearAction() {
63                         setImageDescriptor(ImageStore.getImageDescriptor(ImageStore.CLEAR));
64                         setToolTipText(Messages.getString("sqlqueryview.clear"));
65                 }
66
67                 public void run() {
68                         setQuery("");
69                 }
70         }
71
72         private class AutoCommitPreferenceAction extends Action {
73                 
74                 public AutoCommitPreferenceAction() {
75                         super(Messages.getString("SQLQueryView.AutoCommit"));
76                         setToolTipText(Messages.getString("SQLQueryView.AutoCommit"));
77                         setImageDescriptor(ImageStore.getImageDescriptor(ImageStore.AUTOCOMMIT));
78                 }
79                 
80                 public void run() {
81                         setAutoCommitPreference(isChecked());
82                 }
83         }
84         
85         private class RollbackAction extends Action {
86                 public RollbackAction() {
87                         setText(Messages.getString("SQLQueryView.RollBack"));
88                         setToolTipText(Messages.getString("SQLQueryView.RollBack"));
89                 }
90                 
91                 public void run() {
92                 Bookmark[] bookmarks = BookmarkCollection.getInstance().getBookmarks();
93                 for (int i = 0, length = bookmarks == null ? 0 : bookmarks.length; i < length; i++) {
94                         try {
95                                         if (bookmarks[i].isConnected() && !bookmarks[i].getConnection().getAutoCommit()) {
96                                                 MultiSQLServer.getInstance().rollback(bookmarks[i].getConnection());
97                                         }
98                     } catch (SQLException e) {
99                         SQLExceptionDialog.openException(getSite().getShell(), bookmarks[i], e);
100                     } catch (NotConnectedException e) {
101                         ExceptionDisplayDialog.openError(getSite().getShell(), null, null, e);
102                     }
103                         }
104                 }
105         }
106         
107         
108         private class CommitAction extends Action {
109                 public CommitAction() {
110                         setText(Messages.getString("SQLQueryView.Commit"));
111                         setToolTipText(Messages.getString("SQLQueryView.Commit"));
112                 }
113                 
114                 public void run() {
115                 Bookmark[] bookmarks = BookmarkCollection.getInstance().getBookmarks();
116                 for (int i = 0, length = bookmarks == null ? 0 : bookmarks.length; i < length; i++) {
117                         try {
118                                         if (bookmarks[i].isConnected() && !bookmarks[i].getConnection().getAutoCommit()) {
119                                                 MultiSQLServer.getInstance().commit(bookmarks[i].getConnection());
120                                         }
121                     } catch (SQLException e) {
122                         SQLExceptionDialog.openException(getSite().getShell(), bookmarks[i], e);
123                     } catch (NotConnectedException e) {
124                         ExceptionDisplayDialog.openError(getSite().getShell(), null, null, e);
125                     }
126                         }
127                 }
128         }
129         
130         
131         public class LabelProviderImpl implements ILabelProvider {
132                 public Image getImage(Object element) {
133                         return ImageStore.getImage(ImageStore.BOOKMARK);
134                 }
135                 public String getText(Object element) {
136                         if (element instanceof Bookmark) {
137                                 return ((Bookmark) element).getName();
138                         } else {
139                                 return null;
140                         }
141                 }
142                 public void addListener(ILabelProviderListener listener) {
143                 }
144                 public void dispose() {
145                 }
146                 public boolean isLabelProperty(Object element, String property) {
147                         return false;
148                 }
149                 public void removeListener(ILabelProviderListener listener) {
150                 }
151         }
152         public class ContentProviderImpl implements IStructuredContentProvider {
153                 public Object[] getElements(Object inputElement) {
154                         if (inputElement instanceof BookmarkCollection) {
155                                 return ((BookmarkCollection) inputElement).getBookmarks();
156                         } else {
157                                 return null;
158                         }
159                 }
160                 public void dispose() {
161                 }
162                 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
163                 }
164         }
165         
166         private ExecuteAction executeAction;
167         private ImportQueryAction importQueryAction;
168         private ExportQueryAction exportQueryAction;
169         private StyledText widget;
170         private AutoCommitPreferenceAction autoCommitPreferenceAction;
171         private RollbackAction rollbackAction;
172         private CommitAction commitAction;
173         private boolean autoCommitPreference = true;
174         private IPropertyChangeListener listener;
175         private ColorManager colorManager = new ColorManager();
176
177         private SyntaxHighlighter textUpdater = new SyntaxHighlighter(this.colorManager);
178         
179         
180         public SQLQueryView() {
181                 super();
182                 this.listener = new IPropertyChangeListener() {
183                         public void propertyChange(PropertyChangeEvent event) {
184                                 setFont();
185                         }
186                 };
187                 QuantumPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(listener);
188         }
189         
190         public void dispose() {
191                 QuantumPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this.listener);
192                 this.colorManager.dispose();
193                 super.dispose();
194         }
195         
196         public static SQLQueryView getInstance() {
197                 return (SQLQueryView) QuantumPlugin.getDefault().getView("com.quantum.view.sqlqueryview");
198
199         }
200
201         public void createPartControl(org.eclipse.swt.widgets.Composite parent) {
202                 initActions();
203                 
204                 initializeColours(parent);
205                 GridLayout layout = new GridLayout(1, false);
206                 layout.horizontalSpacing = 0;
207                 layout.verticalSpacing = 0;
208                 layout.marginHeight = 0;
209                 layout.marginWidth = 0;
210                 parent.setLayout(layout);
211                 parent.setLayoutData(new GridData(GridData.FILL_BOTH));
212                 
213                 widget = new StyledText(parent, SWT.H_SCROLL | SWT.V_SCROLL);
214                 
215                 setFont();
216
217                 IActionBars bars = this.getViewSite().getActionBars();
218                 bars.setGlobalActionHandler(IWorkbenchActionConstants.CUT, cutAction);
219                 bars.setGlobalActionHandler(IWorkbenchActionConstants.COPY, copyAction);
220                 bars.setGlobalActionHandler(IWorkbenchActionConstants.PASTE, pasteAction);
221                 bars.setGlobalActionHandler(IWorkbenchActionConstants.SELECT_ALL, selectAllAction);
222
223                 widget.setEditable(true);
224                 widget.addExtendedModifyListener(modifyListener);
225
226                 widget.setLayoutData(new GridData(GridData.FILL_BOTH));
227
228                 VersioningHelper.registerActionToKeyBindingService(getSite(), 
229                                 new String[] { "org.eclipse.ui.globalScope", "com.quantum.view.sql" }, 
230                         this.executeAction);
231         }
232
233         /**
234          * @param widget2
235          */
236         private void setFont() {
237                 FontData font = PreferenceConverter.getFontData(
238                                 QuantumPlugin.getDefault().getPreferenceStore(), 
239                                 "quantum.font"); //$NON-NLS-1$
240                 if (font != null && this.widget != null) {
241                         this.widget.setFont(new Font(Display.getCurrent(), font));
242                 }
243         }
244         /**
245          * @param parent
246          */
247         private void initializeColours(Composite parent) {
248             IPreferenceStore store = QuantumPlugin.getDefault().getPreferenceStore();
249
250                 parent.setBackground(this.colorManager.getColor(
251                                 PreferenceConverter.getColor(store, PluginPreferences.BACKGROUND_COLOR)));
252                 this.textUpdater.initializeColours();
253         }
254         
255         private void initActions() {
256
257                 IToolBarManager toolBar = getViewSite().getActionBars().getToolBarManager();
258
259                 executeAction = new ExecuteAction(this);
260                 toolBar.add(this.executeAction);
261                 toolBar.add(new ClearAction());
262                 
263         IActionBars actionBars = getViewSite().getActionBars();
264                 this.importQueryAction = new ImportQueryAction();
265                 this.importQueryAction.init(this);
266         actionBars.getMenuManager().add(this.importQueryAction);
267         this.exportQueryAction = new ExportQueryAction();
268         this.exportQueryAction.init(this);
269         actionBars.getMenuManager().add(this.exportQueryAction);
270         actionBars.getMenuManager().add(new Separator());
271         this.autoCommitPreferenceAction = new AutoCommitPreferenceAction();
272         this.autoCommitPreferenceAction.setChecked(this.autoCommitPreference);
273         actionBars.getMenuManager().add(this.autoCommitPreferenceAction);
274
275         this.rollbackAction = new RollbackAction();
276         actionBars.getMenuManager().add(this.rollbackAction);
277
278         this.commitAction = new CommitAction();
279         actionBars.getMenuManager().add(this.commitAction);
280 }
281
282         public String getQuery() {
283                 return widget.getText();
284         }
285         
286         public void setQuery(String text) {
287                 widget.setText(text);
288         }
289         
290         private class UpdateRequest {
291                 public UpdateRequest(String text, int start, int length) {
292                         this.text = text;
293                         this.start = start;
294                         this.length = length;
295                 }
296                 public String text;
297                 public int start;
298                 public int length;
299         }
300         
301         private class SyntaxHighlighter extends Thread {
302                 
303                 private Color STRING_LITERAL;
304                 private Color KEYWORD;
305                 private Color COMMENT;
306                 private Color NUMERIC;
307                 private Color DEFAULT;
308                 
309                 private boolean running = true;
310                 private LinkedList requests = new LinkedList();
311                 private final ColorManager colorManager;
312                 public SyntaxHighlighter(ColorManager colorManager) {
313                         super();
314                         this.colorManager = colorManager;
315                         
316                         setPriority(Thread.MIN_PRIORITY);
317                         start();
318                 }
319                 public void initializeColours() {
320                     IPreferenceStore store = QuantumPlugin.getDefault().getPreferenceStore();
321
322                         this.DEFAULT = this.colorManager.getColor(
323                                         PreferenceConverter.getColor(store, PluginPreferences.TEXT_COLOR));
324                         this.KEYWORD = this.colorManager.getColor(
325                                         PreferenceConverter.getColor(store, PluginPreferences.KEYWORD_COLOR)); 
326                         this.STRING_LITERAL = this.colorManager.getColor(
327                                         PreferenceConverter.getColor(store, PluginPreferences.STRING_COLOR));
328                         this.COMMENT = this.colorManager.getColor(
329                                         PreferenceConverter.getColor(store, PluginPreferences.COMMENT_COLOR));
330                         this.NUMERIC = this.colorManager.getColor(
331                                         PreferenceConverter.getColor(store, PluginPreferences.NUMERIC_COLOR));
332                         
333                 }
334                 public synchronized void updateText(String text, int start, int length) {
335                         requests.add(new UpdateRequest(text, start, length));
336                         notify();
337                 }
338                 public void run() {
339                         while (running) {
340                                 try {
341                                         synchronized (this) {
342                                                 if (requests.size() <= 0) {
343                                                         wait();
344                                                 } else {
345                                                         Thread.sleep(10);
346                                                 }
347                                         }
348                                         UpdateRequest request = (UpdateRequest) requests.removeFirst();
349                                         String text = request.text.toUpperCase();
350                                         //int dirtyStart = request.start;
351                                         //int dirtyEnd = request.start + request.length;
352                                         StyleRange styleRange;
353                                         List tokens = SQLLexx.parse(text);
354                                         List styles = new ArrayList();
355                                         int min = Integer.MAX_VALUE;
356                                         int max = 0;
357                                         for (int i = 0; i < tokens.size(); i++) {
358                                                 Token t = (Token) tokens.get(i);
359                                                 String value = t.getValue();
360                                                 int start = t.getStart();
361                                                 int length = t.getEnd() - t.getStart();
362                                                 styleRange = new StyleRange();
363                                                 styleRange.start = start;
364                                                 styleRange.length = value.length();
365                                                 styleRange.fontStyle = SWT.NULL;
366                                                 styleRange.foreground = DEFAULT;
367                                                 //boolean upper = start <= dirtyEnd && start >= dirtyStart;
368                                                 //boolean lower = ((start + length) >= dirtyStart && (start + length) <= dirtyEnd);
369                                                 //boolean both = (start <= dirtyStart && (start + length) >= dirtyEnd);
370                                                 //if (upper || lower || both) {
371                                                 if (true) { // Let's update the whole text, as some comment changes can alter everything
372                                                         min = Math.min(start, min);
373                                                         max = Math.max(max, start + length);
374                                                         if (t.getType() == Token.IDENTIFIER) {
375                                                                 boolean keyword = false;
376                                                                 for (int index = 0; index < SQLGrammar.KEYWORDS.length; index++) {
377                                                                         if (value.equals(SQLGrammar.KEYWORDS[index])) {
378                                                                                 keyword = true;
379                                                                         }
380                                                                 }
381                                                                 if (keyword) {
382                                                                         styleRange.fontStyle = SWT.BOLD;
383                                                                         styleRange.foreground = KEYWORD;
384                                                                 } else {
385                                                                         styleRange.foreground = DEFAULT;
386                                                                 }
387                                                                 styles.add(styleRange);
388                                                         } else if (t.getType() == Token.COMMENT) {
389                                                                 styleRange.foreground = COMMENT;
390                                                                 styles.add(styleRange);
391                                                         } else if (t.getType() == Token.LITERAL) {
392                                                                 styleRange.foreground = STRING_LITERAL;
393                                                                 styles.add(styleRange);
394                                                         } else if (t.getType() == Token.NUMERIC) {
395                                                                 styleRange.foreground = NUMERIC;
396                                                                 styles.add(styleRange);
397                                                         } else {
398                                                                 styles.add(styleRange);
399                                                         }
400                                                 }
401                                         }
402                                         StyleRange[] ranges = 
403                                                         (StyleRange[]) styles.toArray(new StyleRange[styles.size()]);
404                                         if (max >= 0 && ranges.length > 0) {
405                                                 setStyles(ranges, min, max - min);
406                                         }
407                                 } catch (NoSuchElementException e) {
408                                         // ignore a missing request
409                                 } catch (InterruptedException e) {
410                                         // ignore any interruptions
411                                 }
412                         }
413                 }
414         }
415         public void setStyles(final StyleRange[] styles, final int start, final int length) {
416                 getViewSite().getShell().getDisplay().asyncExec(new Runnable() {
417                         public void run() {
418                                 try {
419                                         for (int i = 0; i < styles.length; i++) {
420                                                 widget.setStyleRange(styles[i]);
421                                         }
422                                 } catch (Throwable t) {
423                                         System.out.println("Error with styles: " + t.getClass().toString()); //$NON-NLS-1$
424                                         // ignore any errors
425                                 }
426                         }
427                 });
428         }
429         
430         ExtendedModifyListener modifyListener = new ExtendedModifyListener() {
431                 public void modifyText(ExtendedModifyEvent event) {
432                         textUpdater.updateText(getQuery(), event.start, event.length);
433                 }
434         };
435                 
436         private Action cutAction = new Action() {
437                 public void run() {
438                         widget.cut();
439                 }
440         };
441         private Action copyAction = new Action() {
442                 public void run() {
443                         widget.copy();
444                 }
445         };
446         private Action pasteAction = new Action() {
447                 public void run() {
448                         widget.paste();
449                 }
450         };
451         private Action selectAllAction = new Action() {
452                 public void run() {
453                         widget.selectAll();
454                 }
455         };
456
457         public void setFocus() {
458         }
459         public boolean isAutoCommitPreference() {
460                 return this.autoCommitPreference;
461         }
462         public void setAutoCommitPreference(boolean autoCommitPreference) {
463                 this.autoCommitPreference = autoCommitPreference;
464         }
465 }