package net.sourceforge.phpdt.sql.view; import java.util.LinkedList; import java.util.NoSuchElementException; import java.util.Vector; import org.eclipse.jface.action.Action; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ExtendedModifyEvent; import org.eclipse.swt.custom.ExtendedModifyListener; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.ProgressBar; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.part.ViewPart; import net.sourceforge.phpdt.sql.IConstants; import net.sourceforge.phpdt.sql.Messages; import net.sourceforge.phpdt.sql.PHPEclipseSQLPlugin; import net.sourceforge.phpdt.sql.actions.ExecuteAction; import net.sourceforge.phpdt.sql.actions.ExportQueryAction; import net.sourceforge.phpdt.sql.actions.GeneratePHPAction; import net.sourceforge.phpdt.sql.actions.ImportQueryAction; import net.sourceforge.phpdt.sql.sql.MultiSQLServer; import net.sourceforge.phpdt.sql.sql.parser.SQLLexx; import net.sourceforge.phpdt.sql.sql.parser.Token; import net.sourceforge.phpdt.sql.view.bookmark.BookmarkNode; public class SQLQueryView extends ViewPart implements IConstants { ExecuteAction executeAction; ImportQueryAction importQueryAction; ExportQueryAction exportQueryAction; GeneratePHPAction generatePHPAction; private Clipboard clip; private Label statusImage; private Label status; private ProgressBar progress; private static SQLQueryView instance = null; private StyledText widget; private Color STRING_LITERAL; private Color KEYWORD; private Color COMMENT; private Color NUMERIC; private Color DEFAULT; private long parseTime = 0; private long fullTime = 0; public SQLQueryView() { super(); } public void setFocus() { widget.setFocus(); } public static SQLQueryView getInstance() { return instance; } public void createPartControl(org.eclipse.swt.widgets.Composite parent) { instance = this; initActions(); KEYWORD = new Color(parent.getShell().getDisplay(), 126, 0, 75); STRING_LITERAL = new Color(parent.getShell().getDisplay(), 0, 0, 255); COMMENT = new Color(parent.getShell().getDisplay(), 88, 148, 64); NUMERIC = new Color(parent.getShell().getDisplay(), 255, 0, 0); DEFAULT = new Color(parent.getShell().getDisplay(), 0, 0, 0); clip = new Clipboard(getSite().getShell().getDisplay()); Composite main = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(1, false); layout.horizontalSpacing = 0; layout.verticalSpacing = 0; main.setLayout(layout); ToolBar toolbar = new ToolBar(main, SWT.HORIZONTAL); ToolItem item = new ToolItem(toolbar, SWT.PUSH); item.setImage(PHPEclipseSQLPlugin.getImage("play.gif")); //$NON-NLS-1$ item.setToolTipText(Messages.getString("sqlqueryview.executeQuery")); //$NON-NLS-1$ item.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { } public void widgetSelected(SelectionEvent e) { executeAction.run(); } }); item = new ToolItem(toolbar, SWT.SEPARATOR); item = new ToolItem(toolbar, SWT.PUSH); item.setImage(PHPEclipseSQLPlugin.getImage("import.gif")); //$NON-NLS-1$ item.setToolTipText(Messages.getString("sqlqueryview.importQuery")); //$NON-NLS-1$ item.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { } public void widgetSelected(SelectionEvent e) { importQueryAction.run(); } }); item = new ToolItem(toolbar, SWT.PUSH); item.setImage(PHPEclipseSQLPlugin.getImage("export.gif")); //$NON-NLS-1$ item.setToolTipText(Messages.getString("sqlqueryview.exportQuery")); //$NON-NLS-1$ item.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { } public void widgetSelected(SelectionEvent e) { exportQueryAction.run(); } }); item = new ToolItem(toolbar, SWT.PUSH); item.setImage(PHPEclipseSQLPlugin.getImage("php.gif")); //$NON-NLS-1$ item.setToolTipText(Messages.getString("sqlqueryview.generatePHP")); //$NON-NLS-1$ item.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { } public void widgetSelected(SelectionEvent e) { generatePHPAction.run(); } }); item = new ToolItem(toolbar, SWT.PUSH); item.setImage(PHPEclipseSQLPlugin.getImage("clear.gif")); //$NON-NLS-1$ item.setToolTipText(Messages.getString("sqlqueryview.clear")); //$NON-NLS-1$ item.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { } public void widgetSelected(SelectionEvent e) { setQuery(""); //$NON-NLS-1$ } }); item = new ToolItem(toolbar, SWT.SEPARATOR); item = new ToolItem(toolbar, SWT.PUSH); final ToolItem commit = item; item.setImage(PHPEclipseSQLPlugin.getImage("commit.gif")); //$NON-NLS-1$ item.setToolTipText(Messages.getString("SQLQueryView.Commit")); //$NON-NLS-1$ item.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { } public void widgetSelected(SelectionEvent e) { BookmarkNode node = BookmarkView.getInstance().getCurrentBookmark(); MultiSQLServer.getInstance().commit(node.getConnection()); } }); item.setEnabled(false); item = new ToolItem(toolbar, SWT.PUSH); final ToolItem rollback = item; item.setImage(PHPEclipseSQLPlugin.getImage("rollback.gif")); //$NON-NLS-1$ item.setToolTipText(Messages.getString("SQLQueryView.RollBack")); //$NON-NLS-1$ item.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { } public void widgetSelected(SelectionEvent e) { BookmarkNode node = BookmarkView.getInstance().getCurrentBookmark(); MultiSQLServer.getInstance().rollback(node.getConnection()); } }); item.setEnabled(false); item = new ToolItem(toolbar, SWT.CHECK); final ToolItem autocommit = item; item.setImage(PHPEclipseSQLPlugin.getImage("autocommit.gif")); //$NON-NLS-1$ item.setToolTipText(Messages.getString("SQLQueryView.AutoCommit")); //$NON-NLS-1$ item.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { } public void widgetSelected(SelectionEvent e) { BookmarkNode node = BookmarkView.getInstance().getCurrentBookmark(); MultiSQLServer.getInstance().setAutoCommit(node.getConnection(), autocommit.getSelection()); if (autocommit.getSelection()) { commit.setEnabled(false); rollback.setEnabled(false); } else { commit.setEnabled(true); rollback.setEnabled(true); } } }); item.setSelection(true); widget = new StyledText(main, SWT.H_SCROLL | SWT.V_SCROLL); IActionBars bars = this.getViewSite().getActionBars(); bars.setGlobalActionHandler(IWorkbenchActionConstants.CUT, cutAction); bars.setGlobalActionHandler(IWorkbenchActionConstants.COPY, copyAction); bars.setGlobalActionHandler(IWorkbenchActionConstants.PASTE, pasteAction); bars.setGlobalActionHandler(IWorkbenchActionConstants.SELECT_ALL, selectAllAction); widget.setEditable(true); widget.addExtendedModifyListener(modifyListener); GridData gridData = new GridData(); gridData.horizontalAlignment = GridData.FILL; gridData.verticalAlignment = GridData.FILL; gridData.grabExcessHorizontalSpace = true; gridData.grabExcessVerticalSpace = true; widget.setLayoutData(gridData); Composite bottomStatus = new Composite(main, SWT.NONE); gridData = new GridData(); gridData.horizontalAlignment = GridData.FILL; gridData.grabExcessHorizontalSpace = true; bottomStatus.setLayoutData(gridData); GridLayout horizontal = new GridLayout(3, false); layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; bottomStatus.setLayout(horizontal); statusImage = new Label(bottomStatus, SWT.NONE); status = new Label(bottomStatus, SWT.NONE); gridData = new GridData(); gridData.horizontalAlignment = GridData.FILL; gridData.grabExcessHorizontalSpace = true; status.setLayoutData(gridData); progress = new ProgressBar(bottomStatus, SWT.HORIZONTAL); status.setText(Messages.getString("sqlqueryview.done")); //$NON-NLS-1$ statusImage.setImage(PHPEclipseSQLPlugin.getImage("success.gif")); //$NON-NLS-1$ progress.setMinimum(0); } public void setProgress(int increment, int max) { progress.setMaximum(max); progress.setSelection(increment); } private void initActions() { executeAction = new ExecuteAction(); executeAction.init(this); importQueryAction = new ImportQueryAction(); importQueryAction.init(this); exportQueryAction = new ExportQueryAction(); exportQueryAction.init(this); generatePHPAction = new GeneratePHPAction(); generatePHPAction.init(this); } public void setStatus(String text) { statusImage.setImage(null); status.setText(text); } public void setStatus(Image img, String text) { statusImage.setImage(img); status.setText(text); } public String getQuery() { return widget.getText(); } public void setQuery(String text) { widget.setText(text); } private String[] keywords = {"SELECT", "DROP", "FROM", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ "INSERT", "INTO", "VALUES", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ "CREATE", "TABLE", "VIEW", "SEQUENCE", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ "UPDATE", "SET", "WHERE"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ SyntaxHighlighter textUpdater = new SyntaxHighlighter(); private class UpdateRequest { public UpdateRequest(String text, int start, int length) { this.text = text; this.start = start; this.length = length; } public String text; public int start; public int length; } private class SyntaxHighlighter extends Thread { private boolean running = true; private LinkedList requests = new LinkedList(); public SyntaxHighlighter() { super(); setPriority(Thread.MIN_PRIORITY); start(); } public synchronized void updateText(String text, int start, int length) { requests.add(new UpdateRequest(text, start, length)); notify(); } public synchronized void shutdown() { running = false; interrupt(); } public void run() { while (running) { try { synchronized (this) { if (requests.size() <= 0) { wait(); } else { Thread.sleep(10); } } UpdateRequest request = (UpdateRequest) requests.removeFirst(); String text = request.text.toUpperCase(); int dirtyStart = request.start; int dirtyEnd = request.start + request.length; StyleRange styleRange; long startTime = System.currentTimeMillis(); Vector tokens = SQLLexx.parse(text); long subTime = System.currentTimeMillis(); Vector styles = new Vector(); int min = Integer.MAX_VALUE; int max = 0; for (int i = 0; i < tokens.size(); i++) { Token t = (Token) tokens.elementAt(i); String value = t.getValue(); int start = t.getStart(); int length = t.getEnd() - t.getStart(); styleRange = new StyleRange(); styleRange.start = start; styleRange.length = value.length(); styleRange.fontStyle = SWT.NULL; styleRange.foreground = DEFAULT; boolean upper = start <= dirtyEnd && start >= dirtyStart; boolean lower = ((start + length) >= dirtyStart && (start + length) <= dirtyEnd); boolean both = (start <= dirtyStart && (start + length) >= dirtyEnd); if (upper || lower || both) { min = Math.min(start, min); max = Math.max(max, start + length); if (t.getType() == Token.IDENTIFIER) { boolean keyword = false; for (int index = 0; index < keywords.length; index++) { if (value.equals(keywords[index])) { keyword = true; } } if (keyword) { styleRange.fontStyle = SWT.BOLD; styleRange.foreground = KEYWORD; } else { styleRange.foreground = DEFAULT; } styles.addElement(styleRange); } else if (t.getType() == Token.COMMENT) { styleRange.foreground = COMMENT; styles.addElement(styleRange); } else if (t.getType() == Token.LITERAL) { styleRange.foreground = STRING_LITERAL; styles.addElement(styleRange); } else if (t.getType() == Token.NUMERIC) { styleRange.foreground = NUMERIC; styles.addElement(styleRange); } else { styles.addElement(styleRange); } } } StyleRange[] ranges = new StyleRange[styles.size()]; for (int k = 0; k < ranges.length; k++) { ranges[k] = (StyleRange) styles.elementAt(k); } if (max >= 0 && ranges.length > 0) { setStyles(ranges, min, max - min); } long endTime = System.currentTimeMillis(); parseTime = subTime - startTime; fullTime = endTime - startTime; } catch (NoSuchElementException e) { // ignore a missing request } catch (InterruptedException e) { // ignore any interruptions } } } } public void setStyles(final StyleRange[] styles, final int start, final int length) { getViewSite().getShell().getDisplay().asyncExec(new Runnable() { public void run() { try { for (int i = 0; i < styles.length; i++) { widget.setStyleRange(styles[i]); } } catch (Throwable t) { System.out.println("Error with styles: " + t.getClass().toString()); //$NON-NLS-1$ // ignore any errors } } }); } ExtendedModifyListener modifyListener = new ExtendedModifyListener() { public void modifyText(ExtendedModifyEvent event) { textUpdater.updateText(getQuery(), event.start, event.length); } }; private Action cutAction = new Action() { public void run() { widget.cut(); } }; private Action copyAction = new Action() { public void run() { widget.copy(); } }; private Action pasteAction = new Action() { public void run() { widget.paste(); } }; private Action selectAllAction = new Action() { public void run() { widget.selectAll(); } }; }