package org.reldb.dbrowser.ui.content.cmd; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.graphics.Color; import org.reldb.dbrowser.ui.DbConnection; import org.reldb.dbrowser.ui.content.rev.RelvarEditorPanel; import org.reldb.dbrowser.ui.html.BrowserManager; import org.reldb.dbrowser.ui.preferences.PreferenceChangeAdapter; import org.reldb.dbrowser.ui.preferences.PreferenceChangeEvent; import org.reldb.dbrowser.ui.preferences.PreferenceChangeListener; import org.reldb.dbrowser.ui.preferences.PreferencePageCmd; import org.reldb.dbrowser.ui.preferences.Preferences; import org.reldb.rel.client.parser.ResponseToHTML; import org.reldb.rel.client.parser.core.ParseException; import org.reldb.rel.exceptions.DatabaseFormatVersionException; public class CmdPanelOutput extends Composite { private BrowserManager browser; private StyledText styledText; private RelvarEditorPanel relvarEditor; private Composite outputStack; private StackLayout outputStackLayout; private boolean showOk = true; private boolean isEnhancedOutput = true; private boolean isShowHeadings = true; private boolean isShowHeadingTypes = true; private boolean isAutoclear = true; private Color red = new Color(getDisplay(), 200, 0, 0); private Color green = new Color(getDisplay(), 0, 128, 0); private Color blue = new Color(getDisplay(), 0, 0, 128); private Color black = new Color(getDisplay(), 0, 0, 0); private Color grey = new Color(getDisplay(), 128, 128, 128); private Color yellow = new Color(getDisplay(), 255, 215, 0); private FileDialog saveHtmlDialog; private FileDialog saveTextDialog; private boolean responseFormatted = false; private ConcurrentStringReceiverClient connection; private StringBuffer reply = new StringBuffer(); private PreferenceChangeListener browserPreferenceChangeListener; private PreferenceChangeListener fontPreferenceChangeListener; /** * Create the composite. * @param parent * @param style * @throws IOException * @throws ClassNotFoundException * @throws NumberFormatException * @throws DatabaseFormatVersionException */ public CmdPanelOutput(Composite parent, DbConnection dbConnection, int style) throws NumberFormatException, ClassNotFoundException, IOException, DatabaseFormatVersionException { super(parent, style); setLayout(new FillLayout(SWT.HORIZONTAL)); outputStack = new Composite(this, SWT.NONE); outputStackLayout = new StackLayout(); outputStack.setLayout(outputStackLayout); styledText = new StyledText(outputStack, SWT.BORDER | SWT.V_SCROLL | SWT.MULTI | SWT.H_SCROLL); styledText.setEditable(false); browser = new BrowserManager(); browser.createWidget(outputStack); browserPreferenceChangeListener = new PreferenceChangeAdapter("CmdPanel_browser") { @Override public void preferenceChange(PreferenceChangeEvent preferenceChangeEvent) { browser.changeWidget(outputStack); setEnhancedOutput(getEnhancedOutput()); } }; Preferences.addPreferenceChangeListener(PreferencePageCmd.CMD_BROWSER_SWING, browserPreferenceChangeListener); styledText.setFont(Preferences.getPreferenceFont(getDisplay(), PreferencePageCmd.CMD_FONT)); fontPreferenceChangeListener = new PreferenceChangeAdapter("CmdPanel_font") { @Override public void preferenceChange(PreferenceChangeEvent preferenceChangeEvent) { styledText.setFont(Preferences.getPreferenceFont(getDisplay(), PreferencePageCmd.CMD_FONT)); browser.setContent(browser.getContent()); } }; Preferences.addPreferenceChangeListener(PreferencePageCmd.CMD_FONT, fontPreferenceChangeListener); outputStackLayout.topControl = browser.getWidget(); connection = new ConcurrentStringReceiverClient(this, dbConnection.obtainStringReceiverClient()) { StringBuffer errorBuffer = null; StringBuffer compilerErrorBuffer = null; @Override public void received(String r) { if (r.equals("\n")) { return; } else if (r.equals("Ok.")) { if (showOk) goodResponse(r); reply = new StringBuffer(); } else if (r.equals("Cancel.")) { warningResponse(r); reply = new StringBuffer(); } else if (r.startsWith("ERROR:")) { badResponse(r); outputPlain("\n", black); if (r.startsWith("ERROR: RS0005")) compilerErrorBuffer = new StringBuffer(); reply = new StringBuffer(); errorBuffer = new StringBuffer(); errorBuffer.append(r); errorBuffer.append('\n'); } else if (r.startsWith("NOTICE")) { noticeResponse(r); reply = new StringBuffer(); } else { if (responseFormatted) { reply.append(r); reply.append("\n"); } else if (compilerErrorBuffer == null) { outputHTML(getResponseFormatted(r, responseFormatted)); } else { compilerErrorBuffer.append(r); compilerErrorBuffer.append("<br>"); } responseText(r, black); if (errorBuffer != null) { errorBuffer.append(r); errorBuffer.append('\n'); } } } @Override public void received(Exception e) { badResponse(e.toString()); } @Override public void update() { outputUpdated(); } @Override public void finished() { if (compilerErrorBuffer != null) { outputHTML("<pre>" + compilerErrorBuffer.toString() + "</pre>"); compilerErrorBuffer = null; } if (responseFormatted && reply.length() > 0) { String content = reply.toString(); outputHTML(getResponseFormatted(content, responseFormatted)); } outputUpdated(); if (errorBuffer != null) notifyInputOfError(errorBuffer); else notifyInputOfSuccess(); notifyInputDone(); errorBuffer = null; } }; outputPlain(connection.getInitialServerResponse(), black); outputHTML(ResponseToHTML.textToHTML(connection.getInitialServerResponse())); goodResponse("Ok."); } public static boolean isLastNonWhitespaceCharacter(String s, char c) { int endPosn = s.length() - 1; if (endPosn < 0) return false; while (endPosn >= 0 && Character.isWhitespace(s.charAt(endPosn))) endPosn--; if (endPosn < 0) return false; return (s.charAt(endPosn) == c); } /** Invoke to force toolbar holder to reload our toolbar, because it's probably changed. */ protected void changeToolbar() {} protected void notifyInputDone() {} protected void notifyInputOfSuccess() {} protected void notifyInputOfError(StringBuffer errorBuffer) {} protected void notifyEnhancedOutputChange() {} protected boolean canZoom() { return getParent() instanceof SashForm; } protected void zoom() { if (getParent() instanceof SashForm) { SashForm form = ((SashForm)getParent()); if (form.getMaximizedControl() != this) form.setMaximizedControl(this); else form.setMaximizedControl(null); } } public void clearOutput() { browser.clear(); styledText.setText(""); } public void setEnhancedOutput(boolean selection) { outputStackLayout.topControl = (selection) ? browser.getWidget() : styledText; outputStack.layout(); isEnhancedOutput = selection; notifyEnhancedOutputChange(); } public boolean getEnhancedOutput() { return isEnhancedOutput; } public void useRelvarEditorView(DbConnection connection, String title, int style) { relvarEditor = new RelvarEditorPanel(outputStack, connection, title, style); outputStackLayout.topControl = relvarEditor; outputStack.layout(); changeToolbar(); } public RelvarEditorPanel getRelvarEditorView() { return relvarEditor; } public void removeRelvarEditorView() { setEnhancedOutput(isEnhancedOutput); relvarEditor.dispose(); relvarEditor = null; changeToolbar(); } public void setShowOk(boolean selection) { showOk = selection; } public boolean getShowOk() { return showOk; } public void setHeadingVisible(boolean selection) { isShowHeadings = selection; } public boolean getHeadingVisible() { return isShowHeadings; } public void setHeadingTypesVisible(boolean selection) { isShowHeadingTypes = selection; } public boolean getHeadingTypesVisible() { return isShowHeadingTypes; } public void setAutoclear(boolean selection) { isAutoclear = selection; } public boolean getAutoclear() { return isAutoclear; } public void saveOutputAsHtml() { ensureSaveHtmlDialogExists(); String fname = saveHtmlDialog.open(); if (fname == null) return; try { BufferedWriter f = new BufferedWriter(new FileWriter(fname)); f.write(browser.getText()); f.close(); systemResponse("Saved " + fname); } catch (IOException ioe) { badResponse(ioe.toString()); } } public void saveOutputAsText() { ensureSaveTextDialogExists(); String fname = saveTextDialog.open(); if (fname == null) return; try { BufferedWriter f = new BufferedWriter(new FileWriter(fname)); f.write(styledText.getText()); f.close(); systemResponse("Saved " + fname); } catch (IOException ioe) { badResponse(ioe.toString()); } } public void dispose() { Preferences.removePreferenceChangeListener(PreferencePageCmd.CMD_BROWSER_SWING, browserPreferenceChangeListener); Preferences.removePreferenceChangeListener(PreferencePageCmd.CMD_FONT, fontPreferenceChangeListener); connection.close(); clearOutput(); red.dispose(); green.dispose(); blue.dispose(); black.dispose(); grey.dispose(); yellow.dispose(); super.dispose(); } private void ensureSaveHtmlDialogExists() { if (saveHtmlDialog == null) { saveHtmlDialog = new FileDialog(getShell(), SWT.SAVE); saveHtmlDialog.setFilterPath(System.getProperty("user.home")); saveHtmlDialog.setFilterExtensions(new String[] {"*.html", "*.*"}); saveHtmlDialog.setFilterNames(new String[] {"HTML", "All Files"}); saveHtmlDialog.setText("Save Output"); saveHtmlDialog.setOverwrite(true); } } private void ensureSaveTextDialogExists() { if (saveTextDialog == null) { saveTextDialog = new FileDialog(getShell(), SWT.SAVE); saveTextDialog.setFilterPath(System.getProperty("user.home")); saveTextDialog.setFilterExtensions(new String[] {"*.txt", "*.*"}); saveTextDialog.setFilterNames(new String[] {"Text", "All Files"}); saveTextDialog.setText("Save Output"); saveTextDialog.setOverwrite(true); } } private void outputPlain(String s, Color color) { StyleRange styleRange = new StyleRange(); styleRange.start = styledText.getCharCount(); styleRange.length = s.length(); styleRange.fontStyle = SWT.NORMAL; styleRange.foreground = color; styledText.append(s); styledText.setStyleRange(styleRange); } private void outputHTML(String s) { browser.appendHtml(s); } /** Get formatted response. */ private String getResponseFormatted(String s, boolean parseResponse) { if (parseResponse) { try { StringBuffer sb = new StringBuffer(); ResponseToHTML response = new ResponseToHTML(s) { public void emitHTML(String generatedHTML) { sb.append(generatedHTML); } public boolean isEmitHeading() { return isShowHeadings; } public boolean isEmitHeadingTypes() { return isShowHeadingTypes; } }; response.parse(); return sb.toString(); } catch (ParseException pe) { return "<br>" + ResponseToHTML.textToHTML(s); } } else { return "<br>" + ResponseToHTML.textToHTML(s); // .replace(" ", " "); } } private void outputTextUpdated() { styledText.setCaretOffset(styledText.getCharCount()); styledText.setSelection(styledText.getCaretOffset(), styledText.getCaretOffset()); } private void outputHtmlUpdated() { browser.scrollToBottom(); } private void outputUpdated() { outputTextUpdated(); outputHtmlUpdated(); } /** Record text responses. */ private void responseText(String s, Color color) { outputPlain(s + '\n', color); } private void response(String msg, String htmlClass, Color colour, boolean bold) { String msgPrefixTag; String msgSuffixTag; if (bold) { msgPrefixTag = "<b>"; msgSuffixTag = "</b>"; } else { msgPrefixTag = ""; msgSuffixTag = ""; } outputHTML("<div class=\"" + htmlClass + "\">" + msgPrefixTag + getResponseFormatted(msg, false) + msgSuffixTag + "</div>"); responseText("\n" + msg, colour); outputUpdated(); } /** Handle a received line of 'good' content. */ public void goodResponse(String s) { response(s, "ok", green, false); } /** Handle a received line of 'warning' content. */ public void warningResponse(String s) { response(s, "warn", yellow, true); } /** Handle user entry. */ public void userResponse(String s) { response(s, "user", grey, true); } /** Handle a received line of system notice. */ public void systemResponse(String s) { response(s, "note", blue, false); } /** Handle a received line of 'bad' content. */ public void badResponse(String s) { response(s, "bad", red, true); } /** Handle a notice. */ public void noticeResponse(String s) { response(s, "notice", black, true); } public String getSelectionText() { return styledText.getSelectionText(); } public String getText() { return styledText.getText(); } public void notifyStop() { connection.reset(); } public void clearReplyBuffer() { reply = new StringBuffer(); } public void sendExecute(String text) { try { clearReplyBuffer(); responseFormatted = false; connection.sendExecute(text); } catch (Throwable ioe) { badResponse(ioe.getMessage()); } } public void sendEvaluate(String text) { try { clearReplyBuffer(); responseFormatted = true; connection.sendEvaluate(text); } catch (Throwable ioe) { badResponse(ioe.getMessage()); } } public void go(String text, boolean copyInputToOutput) { if (getAutoclear()) clearOutput(); if (copyInputToOutput) userResponse(text); if (isLastNonWhitespaceCharacter(text.trim(), ';')) { sendExecute(text); } else { sendEvaluate(text); } } }