1 package net.sourceforge.phpdt.sql.view;
3 import java.util.LinkedList;
4 import java.util.NoSuchElementException;
5 import java.util.Vector;
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;
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;
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;
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() {
58 public void setFocus() {
61 public static SQLQueryView getInstance() {
65 public void createPartControl(org.eclipse.swt.widgets.Composite parent) {
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) {
86 public void widgetSelected(SelectionEvent e) {
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) {
97 public void widgetSelected(SelectionEvent e) {
98 importQueryAction.run();
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) {
107 public void widgetSelected(SelectionEvent e) {
108 exportQueryAction.run();
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) {
117 public void widgetSelected(SelectionEvent e) {
122 item = new ToolItem(toolbar, SWT.SEPARATOR);
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) {
131 public void widgetSelected(SelectionEvent e) {
132 MultiSQLServer.getInstance().commit();
135 item.setEnabled(false);
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) {
144 public void widgetSelected(SelectionEvent e) {
145 MultiSQLServer.getInstance().rollback();
148 item.setEnabled(false);
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) {
157 public void widgetSelected(SelectionEvent e) {
158 MultiSQLServer.getInstance().setAutoCommit(autocommit.getSelection());
159 if (autocommit.getSelection()) {
160 commit.setEnabled(false);
161 rollback.setEnabled(false);
163 commit.setEnabled(true);
164 rollback.setEnabled(true);
168 item.setSelection(true);
170 widget = new StyledText(main, SWT.H_SCROLL | SWT.V_SCROLL);
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);
178 widget.setEditable(true);
179 widget.addExtendedModifyListener(modifyListener);
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);
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);
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);
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);
208 progress = new ProgressBar(bottomStatus, SWT.HORIZONTAL);
210 status.setText(Messages.getString("sqlqueryview.done"));
211 statusImage.setImage(PHPEclipseSQLPlugin.getImage("success.gif"));
212 progress.setMinimum(0);
215 public void setProgress(int increment, int max) {
216 progress.setMaximum(max);
217 progress.setSelection(increment);
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);
229 public void setStatus(String text) {
230 statusImage.setImage(null);
231 status.setText(text);
234 public void setStatus(Image img, String text) {
235 statusImage.setImage(img);
236 status.setText(text);
239 public String getQuery() {
240 return widget.getText();
243 public void setQuery(String text) {
244 widget.setText(text);
247 private String[] keywords = {"SELECT", "DROP", "FROM",
248 "INSERT", "INTO", "VALUES",
249 "CREATE", "TABLE", "VIEW", "SEQUENCE",
250 "UPDATE", "SET", "WHERE"};
252 SyntaxHighlighter textUpdater = new SyntaxHighlighter();
254 private class UpdateRequest {
255 public UpdateRequest(String text, int start, int length) {
258 this.length = length;
265 private class SyntaxHighlighter extends Thread {
266 private boolean running = true;
267 private LinkedList requests = new LinkedList();
268 public SyntaxHighlighter() {
270 setPriority(Thread.MIN_PRIORITY);
273 public synchronized void updateText(String text, int start, int length) {
274 requests.add(new UpdateRequest(text, start, length));
277 public synchronized void shutdown() {
284 synchronized (this) {
285 if (requests.size() <= 0) {
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;
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])) {
326 styleRange.fontStyle = SWT.BOLD;
327 styleRange.foreground = KEYWORD;
329 styleRange.foreground = DEFAULT;
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);
342 styles.addElement(styleRange);
346 StyleRange[] ranges = new StyleRange[styles.size()];
347 for (int k = 0; k < ranges.length; k++) {
348 ranges[k] = (StyleRange) styles.elementAt(k);
350 if (max >= 0 && ranges.length > 0) {
351 setStyles(ranges, min, max - min);
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
364 public void setStyles(final StyleRange[] styles, final int start, final int length) {
365 getViewSite().getShell().getDisplay().asyncExec(new Runnable() {
368 for (int i = 0; i < styles.length; i++) {
369 widget.setStyleRange(styles[i]);
371 } catch (Throwable t) {
373 System.out.println("Error with styles: " + t.getClass().toString());
381 ExtendedModifyListener modifyListener = new ExtendedModifyListener() {
382 public void modifyText(ExtendedModifyEvent event) {
383 textUpdater.updateText(getQuery(), event.start, event.length);
387 private Action cutAction = new Action() {
392 private Action copyAction = new Action() {
397 private Action pasteAction = new Action() {
402 private Action selectAllAction = new Action() {