1 package net.sourceforge.phpdt.sql.view;
3 import java.util.LinkedList;
4 import java.util.NoSuchElementException;
5 import java.util.Vector;
7 import org.eclipse.jface.action.Action;
8 import org.eclipse.swt.SWT;
9 import org.eclipse.swt.custom.ExtendedModifyEvent;
10 import org.eclipse.swt.custom.ExtendedModifyListener;
11 import org.eclipse.swt.custom.StyleRange;
12 import org.eclipse.swt.custom.StyledText;
13 import org.eclipse.swt.dnd.Clipboard;
14 import org.eclipse.swt.events.SelectionEvent;
15 import org.eclipse.swt.events.SelectionListener;
16 import org.eclipse.swt.graphics.Color;
17 import org.eclipse.swt.graphics.Image;
18 import org.eclipse.swt.layout.GridData;
19 import org.eclipse.swt.layout.GridLayout;
20 import org.eclipse.swt.widgets.Composite;
21 import org.eclipse.swt.widgets.Label;
22 import org.eclipse.swt.widgets.ProgressBar;
23 import org.eclipse.swt.widgets.ToolBar;
24 import org.eclipse.swt.widgets.ToolItem;
25 import org.eclipse.ui.IActionBars;
26 import org.eclipse.ui.IWorkbenchActionConstants;
27 import org.eclipse.ui.part.ViewPart;
29 import net.sourceforge.phpdt.sql.IConstants;
30 import net.sourceforge.phpdt.sql.Messages;
31 import net.sourceforge.phpdt.sql.PHPEclipseSQLPlugin;
32 import net.sourceforge.phpdt.sql.actions.ExecuteAction;
33 import net.sourceforge.phpdt.sql.actions.ExportQueryAction;
34 import net.sourceforge.phpdt.sql.actions.GeneratePHPAction;
35 import net.sourceforge.phpdt.sql.actions.ImportQueryAction;
36 import net.sourceforge.phpdt.sql.sql.MultiSQLServer;
37 import net.sourceforge.phpdt.sql.sql.parser.SQLLexx;
38 import net.sourceforge.phpdt.sql.sql.parser.Token;
39 import net.sourceforge.phpdt.sql.view.bookmark.BookmarkNode;
41 public class SQLQueryView extends ViewPart implements IConstants {
42 ExecuteAction executeAction;
43 ImportQueryAction importQueryAction;
44 ExportQueryAction exportQueryAction;
45 GeneratePHPAction generatePHPAction;
46 private Clipboard clip;
47 private Label statusImage;
49 private ProgressBar progress;
50 private static SQLQueryView instance = null;
51 private StyledText widget;
52 private Color STRING_LITERAL;
53 private Color KEYWORD;
54 private Color COMMENT;
55 private Color NUMERIC;
56 private Color DEFAULT;
57 private long parseTime = 0;
58 private long fullTime = 0;
59 public SQLQueryView() {
62 public void setFocus() {
65 public static SQLQueryView getInstance() {
69 public void createPartControl(org.eclipse.swt.widgets.Composite parent) {
72 KEYWORD = new Color(parent.getShell().getDisplay(), 126, 0, 75);
73 STRING_LITERAL = new Color(parent.getShell().getDisplay(), 0, 0, 255);
74 COMMENT = new Color(parent.getShell().getDisplay(), 88, 148, 64);
75 NUMERIC = new Color(parent.getShell().getDisplay(), 255, 0, 0);
76 DEFAULT = new Color(parent.getShell().getDisplay(), 0, 0, 0);
77 clip = new Clipboard(getSite().getShell().getDisplay());
78 Composite main = new Composite(parent, SWT.NONE);
79 GridLayout layout = new GridLayout(1, false);
80 layout.horizontalSpacing = 0;
81 layout.verticalSpacing = 0;
82 main.setLayout(layout);
83 ToolBar toolbar = new ToolBar(main, SWT.HORIZONTAL);
84 ToolItem item = new ToolItem(toolbar, SWT.PUSH);
85 item.setImage(PHPEclipseSQLPlugin.getImage("play.gif")); //$NON-NLS-1$
86 item.setToolTipText(Messages.getString("sqlqueryview.executeQuery")); //$NON-NLS-1$
87 item.addSelectionListener(new SelectionListener() {
88 public void widgetDefaultSelected(SelectionEvent e) {
90 public void widgetSelected(SelectionEvent e) {
94 item = new ToolItem(toolbar, SWT.SEPARATOR);
95 item = new ToolItem(toolbar, SWT.PUSH);
96 item.setImage(PHPEclipseSQLPlugin.getImage("import.gif")); //$NON-NLS-1$
97 item.setToolTipText(Messages.getString("sqlqueryview.importQuery")); //$NON-NLS-1$
98 item.addSelectionListener(new SelectionListener() {
99 public void widgetDefaultSelected(SelectionEvent e) {
101 public void widgetSelected(SelectionEvent e) {
102 importQueryAction.run();
105 item = new ToolItem(toolbar, SWT.PUSH);
106 item.setImage(PHPEclipseSQLPlugin.getImage("export.gif")); //$NON-NLS-1$
107 item.setToolTipText(Messages.getString("sqlqueryview.exportQuery")); //$NON-NLS-1$
108 item.addSelectionListener(new SelectionListener() {
109 public void widgetDefaultSelected(SelectionEvent e) {
111 public void widgetSelected(SelectionEvent e) {
112 exportQueryAction.run();
115 item = new ToolItem(toolbar, SWT.PUSH);
116 item.setImage(PHPEclipseSQLPlugin.getImage("php.gif")); //$NON-NLS-1$
117 item.setToolTipText(Messages.getString("sqlqueryview.generatePHP")); //$NON-NLS-1$
118 item.addSelectionListener(new SelectionListener() {
119 public void widgetDefaultSelected(SelectionEvent e) {
121 public void widgetSelected(SelectionEvent e) {
122 generatePHPAction.run();
125 item = new ToolItem(toolbar, SWT.PUSH);
126 item.setImage(PHPEclipseSQLPlugin.getImage("clear.gif")); //$NON-NLS-1$
127 item.setToolTipText(Messages.getString("sqlqueryview.clear")); //$NON-NLS-1$
128 item.addSelectionListener(new SelectionListener() {
129 public void widgetDefaultSelected(SelectionEvent e) {
131 public void widgetSelected(SelectionEvent e) {
132 setQuery(""); //$NON-NLS-1$
136 item = new ToolItem(toolbar, SWT.SEPARATOR);
138 item = new ToolItem(toolbar, SWT.PUSH);
139 final ToolItem commit = item;
140 item.setImage(PHPEclipseSQLPlugin.getImage("commit.gif")); //$NON-NLS-1$
141 item.setToolTipText(Messages.getString("SQLQueryView.Commit")); //$NON-NLS-1$
142 item.addSelectionListener(new SelectionListener() {
143 public void widgetDefaultSelected(SelectionEvent e) {
145 public void widgetSelected(SelectionEvent e) {
146 BookmarkNode node = BookmarkView.getInstance().getCurrentBookmark();
147 MultiSQLServer.getInstance().commit(node.getConnection());
150 item.setEnabled(false);
152 item = new ToolItem(toolbar, SWT.PUSH);
153 final ToolItem rollback = item;
154 item.setImage(PHPEclipseSQLPlugin.getImage("rollback.gif")); //$NON-NLS-1$
155 item.setToolTipText(Messages.getString("SQLQueryView.RollBack")); //$NON-NLS-1$
156 item.addSelectionListener(new SelectionListener() {
157 public void widgetDefaultSelected(SelectionEvent e) {
159 public void widgetSelected(SelectionEvent e) {
160 BookmarkNode node = BookmarkView.getInstance().getCurrentBookmark();
161 MultiSQLServer.getInstance().rollback(node.getConnection());
164 item.setEnabled(false);
166 item = new ToolItem(toolbar, SWT.CHECK);
167 final ToolItem autocommit = item;
168 item.setImage(PHPEclipseSQLPlugin.getImage("autocommit.gif")); //$NON-NLS-1$
169 item.setToolTipText(Messages.getString("SQLQueryView.AutoCommit")); //$NON-NLS-1$
170 item.addSelectionListener(new SelectionListener() {
171 public void widgetDefaultSelected(SelectionEvent e) {
173 public void widgetSelected(SelectionEvent e) {
174 BookmarkNode node = BookmarkView.getInstance().getCurrentBookmark();
176 MultiSQLServer.getInstance().setAutoCommit(node.getConnection(), autocommit.getSelection());
177 if (autocommit.getSelection()) {
178 commit.setEnabled(false);
179 rollback.setEnabled(false);
181 commit.setEnabled(true);
182 rollback.setEnabled(true);
186 item.setSelection(true);
188 widget = new StyledText(main, SWT.H_SCROLL | SWT.V_SCROLL);
190 IActionBars bars = this.getViewSite().getActionBars();
191 bars.setGlobalActionHandler(IWorkbenchActionConstants.CUT, cutAction);
192 bars.setGlobalActionHandler(IWorkbenchActionConstants.COPY, copyAction);
193 bars.setGlobalActionHandler(IWorkbenchActionConstants.PASTE, pasteAction);
194 bars.setGlobalActionHandler(IWorkbenchActionConstants.SELECT_ALL, selectAllAction);
196 widget.setEditable(true);
197 widget.addExtendedModifyListener(modifyListener);
199 GridData gridData = new GridData();
200 gridData.horizontalAlignment = GridData.FILL;
201 gridData.verticalAlignment = GridData.FILL;
202 gridData.grabExcessHorizontalSpace = true;
203 gridData.grabExcessVerticalSpace = true;
204 widget.setLayoutData(gridData);
206 Composite bottomStatus = new Composite(main, SWT.NONE);
207 gridData = new GridData();
208 gridData.horizontalAlignment = GridData.FILL;
209 gridData.grabExcessHorizontalSpace = true;
210 bottomStatus.setLayoutData(gridData);
212 GridLayout horizontal = new GridLayout(3, false);
213 layout.horizontalSpacing = 0;
214 layout.verticalSpacing = 0;
215 layout.marginHeight = 0;
216 layout.marginWidth = 0;
217 bottomStatus.setLayout(horizontal);
219 statusImage = new Label(bottomStatus, SWT.NONE);
220 status = new Label(bottomStatus, SWT.NONE);
221 gridData = new GridData();
222 gridData.horizontalAlignment = GridData.FILL;
223 gridData.grabExcessHorizontalSpace = true;
224 status.setLayoutData(gridData);
226 progress = new ProgressBar(bottomStatus, SWT.HORIZONTAL);
228 status.setText(Messages.getString("sqlqueryview.done")); //$NON-NLS-1$
229 statusImage.setImage(PHPEclipseSQLPlugin.getImage("success.gif")); //$NON-NLS-1$
230 progress.setMinimum(0);
233 public void setProgress(int increment, int max) {
234 progress.setMaximum(max);
235 progress.setSelection(increment);
238 private void initActions() {
239 executeAction = new ExecuteAction();
240 executeAction.init(this);
241 importQueryAction = new ImportQueryAction();
242 importQueryAction.init(this);
243 exportQueryAction = new ExportQueryAction();
244 exportQueryAction.init(this);
245 generatePHPAction = new GeneratePHPAction();
246 generatePHPAction.init(this);
249 public void setStatus(String text) {
250 statusImage.setImage(null);
251 status.setText(text);
254 public void setStatus(Image img, String text) {
255 statusImage.setImage(img);
256 status.setText(text);
259 public String getQuery() {
260 return widget.getText();
263 public void setQuery(String text) {
264 widget.setText(text);
267 private String[] keywords = {"SELECT", "DROP", "FROM", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
268 "INSERT", "INTO", "VALUES", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
269 "CREATE", "TABLE", "VIEW", "SEQUENCE", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
270 "UPDATE", "SET", "WHERE"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
272 SyntaxHighlighter textUpdater = new SyntaxHighlighter();
274 private class UpdateRequest {
275 public UpdateRequest(String text, int start, int length) {
278 this.length = length;
285 private class SyntaxHighlighter extends Thread {
286 private boolean running = true;
287 private LinkedList requests = new LinkedList();
288 public SyntaxHighlighter() {
290 setPriority(Thread.MIN_PRIORITY);
293 public synchronized void updateText(String text, int start, int length) {
294 requests.add(new UpdateRequest(text, start, length));
297 public synchronized void shutdown() {
304 synchronized (this) {
305 if (requests.size() <= 0) {
311 UpdateRequest request = (UpdateRequest) requests.removeFirst();
312 String text = request.text.toUpperCase();
313 int dirtyStart = request.start;
314 int dirtyEnd = request.start + request.length;
315 StyleRange styleRange;
316 long startTime = System.currentTimeMillis();
317 Vector tokens = SQLLexx.parse(text);
318 long subTime = System.currentTimeMillis();
319 Vector styles = new Vector();
320 int min = Integer.MAX_VALUE;
322 for (int i = 0; i < tokens.size(); i++) {
323 Token t = (Token) tokens.elementAt(i);
324 String value = t.getValue();
325 int start = t.getStart();
326 int length = t.getEnd() - t.getStart();
327 styleRange = new StyleRange();
328 styleRange.start = start;
329 styleRange.length = value.length();
330 styleRange.fontStyle = SWT.NULL;
331 styleRange.foreground = DEFAULT;
332 boolean upper = start <= dirtyEnd && start >= dirtyStart;
333 boolean lower = ((start + length) >= dirtyStart && (start + length) <= dirtyEnd);
334 boolean both = (start <= dirtyStart && (start + length) >= dirtyEnd);
335 if (upper || lower || both) {
336 min = Math.min(start, min);
337 max = Math.max(max, start + length);
338 if (t.getType() == Token.IDENTIFIER) {
339 boolean keyword = false;
340 for (int index = 0; index < keywords.length; index++) {
341 if (value.equals(keywords[index])) {
346 styleRange.fontStyle = SWT.BOLD;
347 styleRange.foreground = KEYWORD;
349 styleRange.foreground = DEFAULT;
351 styles.addElement(styleRange);
352 } else if (t.getType() == Token.COMMENT) {
353 styleRange.foreground = COMMENT;
354 styles.addElement(styleRange);
355 } else if (t.getType() == Token.LITERAL) {
356 styleRange.foreground = STRING_LITERAL;
357 styles.addElement(styleRange);
358 } else if (t.getType() == Token.NUMERIC) {
359 styleRange.foreground = NUMERIC;
360 styles.addElement(styleRange);
362 styles.addElement(styleRange);
366 StyleRange[] ranges = new StyleRange[styles.size()];
367 for (int k = 0; k < ranges.length; k++) {
368 ranges[k] = (StyleRange) styles.elementAt(k);
370 if (max >= 0 && ranges.length > 0) {
371 setStyles(ranges, min, max - min);
373 long endTime = System.currentTimeMillis();
374 parseTime = subTime - startTime;
375 fullTime = endTime - startTime;
376 } catch (NoSuchElementException e) {
377 // ignore a missing request
378 } catch (InterruptedException e) {
379 // ignore any interruptions
384 public void setStyles(final StyleRange[] styles, final int start, final int length) {
385 getViewSite().getShell().getDisplay().asyncExec(new Runnable() {
388 for (int i = 0; i < styles.length; i++) {
389 widget.setStyleRange(styles[i]);
391 } catch (Throwable t) {
392 System.out.println("Error with styles: " + t.getClass().toString()); //$NON-NLS-1$
399 ExtendedModifyListener modifyListener = new ExtendedModifyListener() {
400 public void modifyText(ExtendedModifyEvent event) {
401 textUpdater.updateText(getQuery(), event.start, event.length);
405 private Action cutAction = new Action() {
410 private Action copyAction = new Action() {
415 private Action pasteAction = new Action() {
420 private Action selectAllAction = new Action() {