Moved to test plugin to eliminate dependency upon junit plugin
[phpeclipse.git] / archive / net.sourceforge.phpeclipse.sql / src / net / sourceforge / phpdt / sql / view / SQLQueryView.java
1 package net.sourceforge.phpdt.sql.view;
2
3 import java.util.LinkedList;
4 import java.util.NoSuchElementException;
5 import java.util.Vector;
6
7 import net.sourceforge.phpdt.sql.IConstants;
8 import net.sourceforge.phpdt.sql.PHPEclipseSQLPlugin;
9 import net.sourceforge.phpdt.sql.actions.ExecuteAction;
10 import net.sourceforge.phpdt.sql.actions.ExportQueryAction;
11 import net.sourceforge.phpdt.sql.actions.ImportQueryAction;
12 import net.sourceforge.phpdt.sql.parser.SQLLexx;
13 import net.sourceforge.phpdt.sql.parser.Token;
14 import net.sourceforge.phpdt.sql.sql.MultiSQLServer;
15
16 import org.eclipse.jface.action.Action;
17 import org.eclipse.swt.SWT;
18 import org.eclipse.swt.custom.ExtendedModifyEvent;
19 import org.eclipse.swt.custom.ExtendedModifyListener;
20 import org.eclipse.swt.custom.StyleRange;
21 import org.eclipse.swt.custom.StyledText;
22 import org.eclipse.swt.dnd.Clipboard;
23 import org.eclipse.swt.events.SelectionEvent;
24 import org.eclipse.swt.events.SelectionListener;
25 import org.eclipse.swt.graphics.Color;
26 import org.eclipse.swt.graphics.Image;
27 import org.eclipse.swt.layout.GridData;
28 import org.eclipse.swt.layout.GridLayout;
29 import org.eclipse.swt.widgets.Composite;
30 import org.eclipse.swt.widgets.Label;
31 import org.eclipse.swt.widgets.ProgressBar;
32 import org.eclipse.swt.widgets.ToolBar;
33 import org.eclipse.swt.widgets.ToolItem;
34 import org.eclipse.ui.IActionBars;
35 import org.eclipse.ui.IWorkbenchActionConstants;
36 import org.eclipse.ui.part.ViewPart;
37
38 public class SQLQueryView extends ViewPart implements IConstants {
39         private ExecuteAction executeAction;
40         private ImportQueryAction importQueryAction;
41         private ExportQueryAction exportQueryAction;
42         private Clipboard clip;
43         private Label statusImage;
44         private Label status;
45         private ProgressBar progress;
46         private static SQLQueryView instance = null;
47         private StyledText widget;
48         private Color STRING_LITERAL;
49         private Color KEYWORD;
50         private Color COMMENT;
51         private Color NUMERIC;
52         private Color DEFAULT;
53         private long parseTime = 0;
54         private long fullTime = 0;
55         public SQLQueryView() {
56                 super();
57         }
58         public void setFocus() {
59                 widget.setFocus();
60         }
61         public static SQLQueryView getInstance() {
62                 return instance;
63         }
64
65         public void createPartControl(org.eclipse.swt.widgets.Composite parent) {
66                 instance = this;
67                 initActions();
68                 KEYWORD = new Color(parent.getShell().getDisplay(), 126, 0, 75);
69                 STRING_LITERAL = new Color(parent.getShell().getDisplay(), 0, 0, 255);
70                 COMMENT = new Color(parent.getShell().getDisplay(), 88, 148, 64);
71                 NUMERIC = new Color(parent.getShell().getDisplay(), 255, 0, 0);
72             DEFAULT = new Color(parent.getShell().getDisplay(), 0, 0, 0);
73                 clip = new Clipboard(getSite().getShell().getDisplay());
74                 Composite main = new Composite(parent, SWT.NONE);
75                 GridLayout layout = new GridLayout(1, false);
76                 layout.horizontalSpacing = 0;
77                 layout.verticalSpacing = 0;
78                 main.setLayout(layout);
79                 ToolBar toolbar = new ToolBar(main, SWT.HORIZONTAL);
80                 ToolItem item = new ToolItem(toolbar, SWT.PUSH);
81                 item.setImage(PHPEclipseSQLPlugin.getImage("play.gif")); //$NON-NLS-1$
82                 item.setToolTipText(Messages.getString("sqlqueryview.executeQuery")); //$NON-NLS-1$
83                 item.addSelectionListener(new SelectionListener() {
84                         public void widgetDefaultSelected(SelectionEvent e) {
85                         }
86                         public void widgetSelected(SelectionEvent e) {
87                                 executeAction.run();
88                         }
89                 });
90                 item = new ToolItem(toolbar, SWT.SEPARATOR);
91                 item = new ToolItem(toolbar, SWT.PUSH);
92                 item.setImage(PHPEclipseSQLPlugin.getImage("import.gif")); //$NON-NLS-1$
93                 item.setToolTipText(Messages.getString("sqlqueryview.importQuery")); //$NON-NLS-1$
94                 item.addSelectionListener(new SelectionListener() {
95                         public void widgetDefaultSelected(SelectionEvent e) {
96                         }
97                         public void widgetSelected(SelectionEvent e) {
98                                 importQueryAction.run();
99                         }
100                 });
101                 item = new ToolItem(toolbar, SWT.PUSH);
102                 item.setImage(PHPEclipseSQLPlugin.getImage("export.gif")); //$NON-NLS-1$
103                 item.setToolTipText(Messages.getString("sqlqueryview.exportQuery")); //$NON-NLS-1$
104                 item.addSelectionListener(new SelectionListener() {
105                         public void widgetDefaultSelected(SelectionEvent e) {
106                         }
107                         public void widgetSelected(SelectionEvent e) {
108                                 exportQueryAction.run();
109                         }
110                 });
111                 item = new ToolItem(toolbar, SWT.PUSH);
112                 item.setImage(PHPEclipseSQLPlugin.getImage("clear.gif")); //$NON-NLS-1$
113                 item.setToolTipText(Messages.getString("sqlqueryview.clear")); //$NON-NLS-1$
114                 item.addSelectionListener(new SelectionListener() {
115                         public void widgetDefaultSelected(SelectionEvent e) {
116                         }
117                         public void widgetSelected(SelectionEvent e) {
118                                 setQuery("");
119                         }
120                 });
121
122                 item = new ToolItem(toolbar, SWT.SEPARATOR);
123
124                 item = new ToolItem(toolbar, SWT.PUSH);
125                 final ToolItem commit = item;
126                 item.setImage(PHPEclipseSQLPlugin.getImage("commit.gif")); //$NON-NLS-1$
127                 item.setToolTipText("Commit");
128                 item.addSelectionListener(new SelectionListener() {
129                         public void widgetDefaultSelected(SelectionEvent e) {
130                         }
131                         public void widgetSelected(SelectionEvent e) {
132                                 MultiSQLServer.getInstance().commit();
133                         }
134                 });
135                 item.setEnabled(false);
136                 
137                 item = new ToolItem(toolbar, SWT.PUSH);
138                 final ToolItem rollback = item;
139                 item.setImage(PHPEclipseSQLPlugin.getImage("rollback.gif")); //$NON-NLS-1$
140                 item.setToolTipText("RollBack");
141                 item.addSelectionListener(new SelectionListener() {
142                         public void widgetDefaultSelected(SelectionEvent e) {
143                         }
144                         public void widgetSelected(SelectionEvent e) {
145                                 MultiSQLServer.getInstance().rollback();
146                         }
147                 });
148                 item.setEnabled(false);
149                 
150                 item = new ToolItem(toolbar, SWT.CHECK);
151                 final ToolItem autocommit = item;
152                 item.setImage(PHPEclipseSQLPlugin.getImage("autocommit.gif")); //$NON-NLS-1$
153                 item.setToolTipText("AutoCommit");
154                 item.addSelectionListener(new SelectionListener() {
155                         public void widgetDefaultSelected(SelectionEvent e) {
156                         }
157                         public void widgetSelected(SelectionEvent e) {
158                                 MultiSQLServer.getInstance().setAutoCommit(autocommit.getSelection());
159                                 if (autocommit.getSelection()) {
160                                         commit.setEnabled(false);
161                                         rollback.setEnabled(false);
162                                 } else {
163                                         commit.setEnabled(true);
164                                         rollback.setEnabled(true);
165                                 }
166                         }
167                 });
168                 item.setSelection(true);
169                 
170                 widget = new StyledText(main, SWT.H_SCROLL | SWT.V_SCROLL);
171
172                 IActionBars bars = this.getViewSite().getActionBars();
173                 bars.setGlobalActionHandler(IWorkbenchActionConstants.CUT, cutAction);
174                 bars.setGlobalActionHandler(IWorkbenchActionConstants.COPY, copyAction);
175                 bars.setGlobalActionHandler(IWorkbenchActionConstants.PASTE, pasteAction);
176                 bars.setGlobalActionHandler(IWorkbenchActionConstants.SELECT_ALL, selectAllAction);
177
178                 widget.setEditable(true);
179                 widget.addExtendedModifyListener(modifyListener);
180
181                 GridData gridData = new GridData();
182                 gridData.horizontalAlignment = GridData.FILL;
183                 gridData.verticalAlignment = GridData.FILL;
184                 gridData.grabExcessHorizontalSpace = true;
185                 gridData.grabExcessVerticalSpace = true;
186                 widget.setLayoutData(gridData);
187
188                 Composite bottomStatus = new Composite(main, SWT.NONE);
189                 gridData = new GridData();
190                 gridData.horizontalAlignment = GridData.FILL;
191                 gridData.grabExcessHorizontalSpace = true;
192                 bottomStatus.setLayoutData(gridData);
193                 
194                 GridLayout horizontal = new GridLayout(3, false);
195                 layout.horizontalSpacing = 0;
196                 layout.verticalSpacing = 0;
197                 layout.marginHeight = 0;
198                 layout.marginWidth = 0;
199                 bottomStatus.setLayout(horizontal);
200
201                 statusImage = new Label(bottomStatus, SWT.NONE);
202                 status = new Label(bottomStatus, SWT.NONE);
203                 gridData = new GridData();
204                 gridData.horizontalAlignment = GridData.FILL;
205                 gridData.grabExcessHorizontalSpace = true;
206                 status.setLayoutData(gridData);
207
208                 progress = new ProgressBar(bottomStatus, SWT.HORIZONTAL);
209
210                 status.setText(Messages.getString("sqlqueryview.done"));
211                 statusImage.setImage(PHPEclipseSQLPlugin.getImage("success.gif"));
212                 progress.setMinimum(0);
213         }
214
215         public void setProgress(int increment, int max) {
216                 progress.setMaximum(max);
217                 progress.setSelection(increment);
218         }
219         
220         private void initActions() {
221                 executeAction = new ExecuteAction();
222                 executeAction.init(this);
223                 importQueryAction = new ImportQueryAction();
224                 importQueryAction.init(this);
225                 exportQueryAction = new ExportQueryAction();
226                 exportQueryAction.init(this);
227         }
228
229         public void setStatus(String text) {
230                 statusImage.setImage(null);
231                 status.setText(text);
232         }
233
234         public void setStatus(Image img, String text) {
235                 statusImage.setImage(img);
236                 status.setText(text);
237         }
238         
239         public String getQuery() {
240                 return widget.getText();
241         }
242         
243         public void setQuery(String text) {
244                 widget.setText(text);
245         }
246         
247         private String[] keywords = {"SELECT", "DROP", "FROM", 
248                 "INSERT", "INTO", "VALUES",
249                 "CREATE", "TABLE", "VIEW", "SEQUENCE",
250                 "UPDATE", "SET", "WHERE"};
251
252         SyntaxHighlighter textUpdater = new SyntaxHighlighter();
253         
254         private class UpdateRequest {
255                 public UpdateRequest(String text, int start, int length) {
256                         this.text = text;
257                         this.start = start;
258                         this.length = length;
259                 }
260                 public String text;
261                 public int start;
262                 public int length;
263         }
264         
265         private class SyntaxHighlighter extends Thread {
266                 private boolean running = true;
267                 private LinkedList requests = new LinkedList();
268                 public SyntaxHighlighter() {
269                         super();
270                         setPriority(Thread.MIN_PRIORITY);
271                         start();
272                 }
273                 public synchronized void updateText(String text, int start, int length) {
274                         requests.add(new UpdateRequest(text, start, length));
275                         notify();
276                 }
277                 public synchronized void shutdown() {
278                         running = false;
279                         interrupt();
280                 }
281                 public void run() {
282                         while (running) {
283                                 try {
284                                         synchronized (this) {
285                                                 if (requests.size() <= 0) {
286                                                         wait();
287                                                 } else {
288                                                         Thread.sleep(10);
289                                                 }
290                                         }
291                                         UpdateRequest request = (UpdateRequest) requests.removeFirst();
292                                         String text = request.text.toUpperCase();
293                                         int dirtyStart = request.start;
294                                         int dirtyEnd = request.start + request.length;
295                                         StyleRange styleRange;
296                                         long startTime = System.currentTimeMillis();
297                                         Vector tokens = SQLLexx.parse(text);
298                                         long subTime = System.currentTimeMillis();
299                                         Vector styles = new Vector();
300                                         int min = Integer.MAX_VALUE;
301                                         int max = 0;
302                                         for (int i = 0; i < tokens.size(); i++) {
303                                                 Token t = (Token) tokens.elementAt(i);
304                                                 String value = t.getValue();
305                                                 int start = t.getStart();
306                                                 int length = t.getEnd() - t.getStart();
307                                                 styleRange = new StyleRange();
308                                                 styleRange.start = start;
309                                                 styleRange.length = value.length();
310                                                 styleRange.fontStyle = SWT.NULL;
311                                                 styleRange.foreground = DEFAULT;
312                                                 boolean upper = start <= dirtyEnd && start >= dirtyStart;
313                                                 boolean lower = ((start + length) >= dirtyStart && (start + length) <= dirtyEnd);
314                                                 boolean both = (start <= dirtyStart && (start + length) >= dirtyEnd);
315                                                 if (upper || lower || both) {
316                                                         min = Math.min(start, min);
317                                                         max = Math.max(max, start + length);
318                                                         if (t.getType() == t.IDENTIFIER) {
319                                                                 boolean keyword = false;
320                                                                 for (int index = 0; index < keywords.length; index++) {
321                                                                         if (value.equals(keywords[index])) {
322                                                                                 keyword = true;
323                                                                         }
324                                                                 }
325                                                                 if (keyword) {
326                                                                         styleRange.fontStyle = SWT.BOLD;
327                                                                         styleRange.foreground = KEYWORD;
328                                                                 } else {
329                                                                         styleRange.foreground = DEFAULT;
330                                                                 }
331                                                                 styles.addElement(styleRange);
332                                                         } else if (t.getType() == t.COMMENT) {
333                                                                 styleRange.foreground = COMMENT;
334                                                                 styles.addElement(styleRange);
335                                                         } else if (t.getType() == t.LITERAL) {
336                                                                 styleRange.foreground = STRING_LITERAL;
337                                                                 styles.addElement(styleRange);
338                                                         } else if (t.getType() == t.NUMERIC) {
339                                                                 styleRange.foreground = NUMERIC;
340                                                                 styles.addElement(styleRange);
341                                                         } else {
342                                                                 styles.addElement(styleRange);
343                                                         }
344                                                 }
345                                         }
346                                         StyleRange[] ranges = new StyleRange[styles.size()];
347                                         for (int k = 0; k < ranges.length; k++) {
348                                                 ranges[k] = (StyleRange) styles.elementAt(k);
349                                         }
350                                         if (max >= 0 && ranges.length > 0) {
351                                                 setStyles(ranges, min, max - min);
352                                         }
353                                         long endTime = System.currentTimeMillis();
354                                         parseTime = subTime - startTime;
355                                         fullTime = endTime - startTime;
356                                 } catch (NoSuchElementException e) {
357                                         // ignore a missing request
358                                 } catch (InterruptedException e) {
359                                         // ignore any interruptions
360                                 }
361                         }
362                 }
363         }
364         public void setStyles(final StyleRange[] styles, final int start, final int length) {
365                 getViewSite().getShell().getDisplay().asyncExec(new Runnable() {
366                         public void run() {
367                                 try {
368                                         for (int i = 0; i < styles.length; i++) {
369                                                 widget.setStyleRange(styles[i]);
370                                         }
371                                 } catch (Throwable t) {
372           if (DEBUG) {
373                                         System.out.println("Error with styles: " + t.getClass().toString());
374                                         // ignore any errors
375           }
376                                 }
377                         }
378                 });
379         }
380         
381         ExtendedModifyListener modifyListener = new ExtendedModifyListener() {
382                 public void modifyText(ExtendedModifyEvent event) {
383                         textUpdater.updateText(getQuery(), event.start, event.length);
384                 }
385         };
386                 
387         private Action cutAction = new Action() {
388                 public void run() {
389                         widget.cut();
390                 }
391         };
392         private Action copyAction = new Action() {
393                 public void run() {
394                         widget.copy();
395                 }
396         };
397         private Action pasteAction = new Action() {
398                 public void run() {
399                         widget.paste();
400                 }
401         };
402         private Action selectAllAction = new Action() {
403                 public void run() {
404                         widget.selectAll();
405                 }
406         };
407 }