/******************************************************************************* * Copyright (c) 2000, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.ui.internal.ide.dialogs; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import javax.xml.parsers.ParserConfigurationException; import org.eclipse.core.resources.IMarker; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.preference.JFacePreferences; import org.eclipse.jface.resource.JFaceColors; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages; import org.eclipse.ui.internal.ide.IDEWorkbenchMessages; import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; import org.eclipse.ui.internal.ide.IIDEHelpContextIds; import org.eclipse.ui.part.EditorPart; import org.xml.sax.SAXException; /** * A "fake" editor to show a welcome page * The contents of this page are supplied in the product configuration * * PRIVATE * This class is internal to the workbench and must not be called outside the workbench */ public class WelcomeEditor extends EditorPart { private final static int HORZ_SCROLL_INCREMENT = 20; private final static int VERT_SCROLL_INCREMENT = 20; // width at which wrapping will stop and a horizontal scroll bar will be // introduced private final static int WRAP_MIN_WIDTH = 150; private Composite editorComposite; private Cursor handCursor; private Cursor busyCursor; private WelcomeParser parser; private ArrayList hyperlinkRanges = new ArrayList(); private ArrayList texts = new ArrayList(); private ScrolledComposite scrolledComposite; private IPropertyChangeListener colorListener; private boolean mouseDown = false; private boolean dragEvent = false; private StyledText firstText, lastText; private StyledText lastNavigatedText, currentText; private boolean nextTabAbortTraversal, previousTabAbortTraversal = false; private WelcomeEditorCopyAction copyAction; /** * Create a new instance of the welcome editor */ public WelcomeEditor() { super(); setPartName(IDEWorkbenchMessages.WelcomeEditor_title); copyAction = new WelcomeEditorCopyAction(this); copyAction.setEnabled(false); } /** * Update the welcome page to start at the * beginning of the text. */ private void focusOn(StyledText newText, int caretOffset) { if (newText == null) { return; } newText.setFocus(); newText.setCaretOffset(caretOffset); scrolledComposite.setOrigin(0, newText.getLocation().y); } /** * Finds the next text */ private StyledText nextText(StyledText text) { int index = 0; if (text == null) { return (StyledText) texts.get(0); } index = texts.indexOf(text); //If we are not at the end.... if (index < texts.size() - 1) { return (StyledText) texts.get(index + 1); } return (StyledText) texts.get(0); } /** * Finds the previous text */ private StyledText previousText(StyledText text) { int index = 0; if (text == null) { return (StyledText) texts.get(0); } index = texts.indexOf(text); //If we are at the beginning.... if (index == 0) { return (StyledText) texts.get(texts.size() - 1); } return (StyledText) texts.get(index - 1); } /** * Returns the current text. */ protected StyledText getCurrentText() { return currentText; } /** * Returns the copy action. */ protected WelcomeEditorCopyAction getCopyAction() { return copyAction; } /** * Finds the next link after the current selection. */ private StyleRange findNextLink(StyledText text) { if (text == null) { return null; } WelcomeItem item = (WelcomeItem) text.getData(); int currentSelectionEnd = text.getSelection().y; for (StyleRange range : text.getStyleRanges()) { if (range.start >= currentSelectionEnd) { if (item.isLinkAt(range.start)) { return range; } } } return null; } /** * Finds the previous link before the current selection. */ private StyleRange findPreviousLink(StyledText text) { if (text == null) { return null; } WelcomeItem item = (WelcomeItem) text.getData(); StyleRange[] ranges = text.getStyleRanges(); int currentSelectionStart = text.getSelection().x; for (int i = ranges.length - 1; i > -1; i--) { if ((ranges[i].start + ranges[i].length) < currentSelectionStart) { if (item.isLinkAt(ranges[i].start + ranges[i].length - 1)) { return ranges[i]; } } } return null; } /** * Finds the current link of the current selection. */ protected StyleRange getCurrentLink(StyledText text) { int currentSelectionEnd = text.getSelection().y; int currentSelectionStart = text.getSelection().x; for (StyleRange range : text.getStyleRanges()) { if ((currentSelectionStart >= range.start) && (currentSelectionEnd <= (range.start + range.length))) { return range; } } return null; } /** * Adds listeners to the given styled text */ private void addListeners(StyledText styledText) { styledText.addMouseListener(new MouseAdapter() { @Override public void mouseDown(MouseEvent e) { if (e.button != 1) { return; } mouseDown = true; } @Override public void mouseUp(MouseEvent e) { mouseDown = false; StyledText text = (StyledText) e.widget; WelcomeItem item = (WelcomeItem) e.widget.getData(); int offset = text.getCaretOffset(); if (dragEvent) { dragEvent = false; if (item.isLinkAt(offset)) { text.setCursor(handCursor); } } else if (item.isLinkAt(offset)) { text.setCursor(busyCursor); if (e.button == 1) { item.triggerLinkAt(offset); StyleRange selectionRange = getCurrentLink(text); text.setSelectionRange(selectionRange.start, selectionRange.length); text.setCursor(null); } } } }); styledText.addMouseMoveListener(e -> { // Do not change cursor on drag events if (mouseDown) { if (!dragEvent) { StyledText text1 = (StyledText) e.widget; text1.setCursor(null); } dragEvent = true; return; } StyledText text2 = (StyledText) e.widget; WelcomeItem item = (WelcomeItem) e.widget.getData(); int offset = -1; try { offset = text2.getOffsetAtLocation(new Point(e.x, e.y)); } catch (IllegalArgumentException ex) { // location is not over a character } if (offset == -1) { text2.setCursor(null); } else if (item.isLinkAt(offset)) { text2.setCursor(handCursor); } else { text2.setCursor(null); } }); styledText.addTraverseListener(e -> { StyledText text = (StyledText) e.widget; switch (e.detail) { case SWT.TRAVERSE_ESCAPE: e.doit = true; break; case SWT.TRAVERSE_TAB_NEXT: // Handle Ctrl-Tab if ((e.stateMask & SWT.CTRL) != 0) { if (e.widget == lastText) { return; } e.doit = false; nextTabAbortTraversal = true; lastText.traverse(SWT.TRAVERSE_TAB_NEXT); return; } if (nextTabAbortTraversal) { nextTabAbortTraversal = false; return; } // Find the next link in current widget, if applicable // Stop at top of widget StyleRange nextLink = findNextLink(text); if (nextLink == null) { // go to the next widget, focus at beginning StyledText nextText = nextText(text); nextText.setSelection(0); focusOn(nextText, 0); } else { // focusOn: allow none tab traversals to align focusOn(text, text.getSelection().x); text.setSelectionRange(nextLink.start, nextLink.length); } e.detail = SWT.TRAVERSE_NONE; e.doit = true; break; case SWT.TRAVERSE_TAB_PREVIOUS: // Handle Ctrl-Shift-Tab if ((e.stateMask & SWT.CTRL) != 0) { if (e.widget == firstText) { return; } e.doit = false; previousTabAbortTraversal = true; firstText.traverse(SWT.TRAVERSE_TAB_PREVIOUS); return; } if (previousTabAbortTraversal) { previousTabAbortTraversal = false; return; } // Find the previous link in current widget, if applicable // Stop at top of widget also StyleRange previousLink = findPreviousLink(text); if (previousLink == null) { if (text.getSelection().x == 0) { // go to the previous widget, focus at end StyledText previousText = previousText(text); previousText.setSelection(previousText .getCharCount()); previousLink = findPreviousLink(previousText); if (previousLink == null) { focusOn(previousText, 0); } else { focusOn(previousText, previousText .getSelection().x); previousText .setSelectionRange(previousLink.start, previousLink.length); } } else { // stay at top of this widget focusOn(text, 0); } } else { // focusOn: allow none tab traversals to align focusOn(text, text.getSelection().x); text.setSelectionRange(previousLink.start, previousLink.length); } e.detail = SWT.TRAVERSE_NONE; e.doit = true; break; default: break; } }); styledText.addKeyListener(new KeyListener() { @Override public void keyReleased(KeyEvent e) { //Ignore a key release } @Override public void keyPressed(KeyEvent event) { StyledText text = (StyledText) event.widget; if (event.character == ' ' || event.character == SWT.CR) { if (text != null) { WelcomeItem item = (WelcomeItem) text.getData(); //Be sure we are in the selection int offset = text.getSelection().x + 1; if (item.isLinkAt(offset)) { text.setCursor(busyCursor); item.triggerLinkAt(offset); StyleRange selectionRange = getCurrentLink(text); text.setSelectionRange(selectionRange.start, selectionRange.length); text.setCursor(null); } } return; } // When page down is pressed, move the cursor to the next item in the // welcome page. Note that this operation wraps (pages to the top item // when the last item is reached). if (event.keyCode == SWT.PAGE_DOWN) { focusOn(nextText(text), 0); return; } // When page up is pressed, move the cursor to the previous item in the // welcome page. Note that this operation wraps (pages to the bottom item // when the first item is reached). if (event.keyCode == SWT.PAGE_UP) { focusOn(previousText(text), 0); return; } } }); styledText.addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent e) { // Remember current text widget lastNavigatedText = (StyledText) e.widget; } @Override public void focusGained(FocusEvent e) { currentText = (StyledText) e.widget; // Remove highlighted selection if text widget has changed if ((currentText != lastNavigatedText) && (lastNavigatedText != null)) { lastNavigatedText.setSelection(lastNavigatedText .getSelection().x); } // enable/disable copy action copyAction.setEnabled(currentText.isTextSelected()); } }); styledText.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { // enable/disable copy action StyledText text = (StyledText) e.widget; copyAction.setEnabled(text.isTextSelected()); } }); } /** * Creates the wizard's title area. * * @param parent the SWT parent for the title area composite * @return the created info area composite */ private Composite createInfoArea(Composite parent) { // Create the title area which will contain // a title, message, and image. this.scrolledComposite = new ScrolledComposite(parent, SWT.V_SCROLL | SWT.H_SCROLL); this.scrolledComposite.setLayoutData(new GridData(GridData.FILL_BOTH)); final Composite infoArea = new Composite(this.scrolledComposite, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginHeight = 10; layout.verticalSpacing = 5; layout.numColumns = 2; infoArea.setLayout(layout); GridData data = new GridData(GridData.FILL_BOTH); infoArea.setLayoutData(data); boolean wrapped = parser.isFormatWrapped(); int HINDENT = 20; // Get the background color for the title area Display display = parent.getDisplay(); Color background = JFaceColors.getBannerBackground(display); Color foreground = JFaceColors.getBannerForeground(display); infoArea.setBackground(background); int textStyle = SWT.MULTI | SWT.READ_ONLY; if (wrapped) { textStyle = textStyle | SWT.WRAP; } StyledText sampleStyledText = null; // Create the intro item WelcomeItem item = getIntroItem(); if (item != null) { StyledText styledText = new StyledText(infoArea, textStyle); this.texts.add(styledText); sampleStyledText = styledText; styledText.setCursor(null); JFaceColors.setColors(styledText, foreground, background); styledText.setText(getIntroItem().getText()); setBoldRanges(styledText, item.getBoldRanges()); setLinkRanges(styledText, item.getActionRanges()); setLinkRanges(styledText, item.getHelpRanges()); GridData gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalSpan = 2; gd.horizontalIndent = HINDENT; gd.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING; styledText.setLayoutData(gd); styledText.setData(item); addListeners(styledText); Label spacer = new Label(infoArea, SWT.NONE); spacer.setBackground(background); gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); gd.horizontalSpan = 2; spacer.setLayoutData(gd); } firstText = sampleStyledText; // Create the welcome items Label imageLabel = null; for (WelcomeItem welcomeItem : getItems()) { Label label = new Label(infoArea, SWT.NONE); label.setBackground(background); label.setImage(PlatformUI.getWorkbench().getSharedImages() .getImage(IDEInternalWorkbenchImages.IMG_OBJS_WELCOME_ITEM)); GridData gd = new GridData(); gd.horizontalIndent = HINDENT; gd.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING; label.setLayoutData(gd); if (imageLabel == null) { imageLabel = label; } StyledText styledText = new StyledText(infoArea, textStyle); this.texts.add(styledText); sampleStyledText = styledText; styledText.setCursor(null); JFaceColors.setColors(styledText, foreground, background); styledText.setText(welcomeItem.getText()); setBoldRanges(styledText, welcomeItem.getBoldRanges()); setLinkRanges(styledText, welcomeItem.getActionRanges()); setLinkRanges(styledText, welcomeItem.getHelpRanges()); gd = new GridData(GridData.FILL_HORIZONTAL); gd.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING; gd.verticalSpan = 2; styledText.setLayoutData(gd); styledText.setData(welcomeItem); addListeners(styledText); Label spacer = new Label(infoArea, SWT.NONE); spacer.setBackground(background); gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); gd.horizontalSpan = 2; spacer.setLayoutData(gd); // create context menu MenuManager menuMgr = new MenuManager("#PopUp"); //$NON-NLS-1$ menuMgr.add(copyAction); styledText.setMenu(menuMgr.createContextMenu(styledText)); } lastText = sampleStyledText; this.scrolledComposite.setContent(infoArea); Point p = infoArea.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); this.scrolledComposite.setMinHeight(p.y); if (wrapped) { // introduce a horizontal scroll bar after a minimum width is reached this.scrolledComposite.setMinWidth(WRAP_MIN_WIDTH); } else { this.scrolledComposite.setMinWidth(p.x); } this.scrolledComposite.setExpandHorizontal(true); this.scrolledComposite.setExpandVertical(true); // When the welcome editor is resized, we need to set the width hint for // wrapped StyledText widgets so that the wrapped height will be recalculated. if (wrapped && (imageLabel != null)) { // figure out how wide the StyledText widgets should be, do this by first // calculating the width of the area not used by styled text widgets Rectangle bounds = imageLabel.getBounds(); final int adjust = HINDENT + bounds.width + layout.verticalSpacing + (layout.marginWidth * 2); final int adjustFirst = HINDENT + (layout.marginWidth * 2); infoArea.addListener(SWT.Resize, event -> { int w = scrolledComposite.getClientArea().width; // if the horizontal scroll bar exists, we want to wrap to the // minimum wrap width if (w < WRAP_MIN_WIDTH) { w = WRAP_MIN_WIDTH; } for (int i = 0; i < texts.size(); i++) { int extent; if (i == 0) { extent = w - adjustFirst; } else { extent = w - adjust; } StyledText text = (StyledText) texts.get(i); Point p1 = text.computeSize(extent, SWT.DEFAULT, false); ((GridData) text.getLayoutData()).widthHint = p1.x; } // reset the scrolled composite height since the height of the // styled text widgets have changed Point p2 = infoArea.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); scrolledComposite.setMinHeight(p2.y); }); } // Adjust the scrollbar increments if (sampleStyledText == null) { this.scrolledComposite.getHorizontalBar().setIncrement( HORZ_SCROLL_INCREMENT); this.scrolledComposite.getVerticalBar().setIncrement( VERT_SCROLL_INCREMENT); } else { GC gc = new GC(sampleStyledText); int width = gc.getFontMetrics().getAverageCharWidth(); gc.dispose(); this.scrolledComposite.getHorizontalBar().setIncrement(width); this.scrolledComposite.getVerticalBar().setIncrement( sampleStyledText.getLineHeight()); } return infoArea; } /** * Creates the SWT controls for this workbench part. * <p> * Clients should not call this method (the workbench calls this method at * appropriate times). * </p> * <p> * For implementors this is a multi-step process: * <ol> * <li>Create one or more controls within the parent.</li> * <li>Set the parent layout as needed.</li> * <li>Register any global actions with the <code>IActionService</code>.</li> * <li>Register any popup menus with the <code>IActionService</code>.</li> * <li>Register a selection provider with the <code>ISelectionService</code> * (optional). </li> * </ol> * </p> * * @param parent the parent control */ @Override public void createPartControl(Composite parent) { // read our contents readFile(); if (parser == null) { return; } handCursor = new Cursor(parent.getDisplay(), SWT.CURSOR_HAND); busyCursor = new Cursor(parent.getDisplay(), SWT.CURSOR_WAIT); editorComposite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.verticalSpacing = 0; layout.horizontalSpacing = 0; editorComposite.setLayout(layout); createTitleArea(editorComposite); Label titleBarSeparator = new Label(editorComposite, SWT.HORIZONTAL | SWT.SEPARATOR); GridData gd = new GridData(GridData.FILL_HORIZONTAL); titleBarSeparator.setLayoutData(gd); createInfoArea(editorComposite); getSite().getWorkbenchWindow().getWorkbench().getHelpSystem().setHelp( editorComposite, IIDEHelpContextIds.WELCOME_EDITOR); this.colorListener = event -> { if (event.getProperty() .equals(JFacePreferences.HYPERLINK_COLOR)) { Color fg = JFaceColors.getHyperlinkText(editorComposite .getDisplay()); Iterator links = hyperlinkRanges.iterator(); while (links.hasNext()) { StyleRange range = (StyleRange) links.next(); range.foreground = fg; } } }; JFacePreferences.getPreferenceStore().addPropertyChangeListener( this.colorListener); } /** * Creates the wizard's title area. * * @param parent the SWT parent for the title area composite * @return the created title area composite */ private Composite createTitleArea(Composite parent) { // Get the background color for the title area Display display = parent.getDisplay(); Color background = JFaceColors.getBannerBackground(display); Color foreground = JFaceColors.getBannerForeground(display); // Create the title area which will contain // a title, message, and image. Composite titleArea = new Composite(parent, SWT.NONE | SWT.NO_FOCUS); GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.verticalSpacing = 0; layout.horizontalSpacing = 0; layout.numColumns = 2; titleArea.setLayout(layout); titleArea.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); titleArea.setBackground(background); // Message label final CLabel messageLabel = new CLabel(titleArea, SWT.LEFT) { @Override protected String shortenText(GC gc, String text, int width) { if (gc.textExtent(text, SWT.DRAW_MNEMONIC).x <= width) { return text; } final String ellipsis = "..."; //$NON-NLS-1$ int ellipseWidth = gc.textExtent(ellipsis, SWT.DRAW_MNEMONIC).x; int length = text.length(); int end = length - 1; while (end > 0) { text = text.substring(0, end); int l1 = gc.textExtent(text, SWT.DRAW_MNEMONIC).x; if (l1 + ellipseWidth <= width) { return text + ellipsis; } end--; } return text + ellipsis; } }; JFaceColors.setColors(messageLabel, foreground, background); messageLabel.setText(getBannerTitle()); messageLabel.setFont(JFaceResources.getHeaderFont()); final IPropertyChangeListener fontListener = event -> { if (JFaceResources.HEADER_FONT.equals(event.getProperty())) { messageLabel.setFont(JFaceResources.getHeaderFont()); } }; messageLabel.addDisposeListener(event -> JFaceResources.getFontRegistry().removeListener(fontListener)); JFaceResources.getFontRegistry().addListener(fontListener); GridData gd = new GridData(GridData.FILL_BOTH); messageLabel.setLayoutData(gd); // Title image Label titleImage = new Label(titleArea, SWT.LEFT); titleImage.setBackground(background); titleImage.setImage(PlatformUI.getWorkbench().getSharedImages() .getImage(IDEInternalWorkbenchImages.IMG_OBJS_WELCOME_BANNER)); gd = new GridData(); gd.horizontalAlignment = GridData.END; titleImage.setLayoutData(gd); return titleArea; } /** * The <code>WorkbenchPart</code> implementation of this * <code>IWorkbenchPart</code> method disposes the title image * loaded by <code>setInitializationData</code>. Subclasses may extend. */ @Override public void dispose() { super.dispose(); if (busyCursor != null) { busyCursor.dispose(); } if (handCursor != null) { handCursor.dispose(); } if (this.colorListener != null) { JFacePreferences.getPreferenceStore().removePropertyChangeListener( this.colorListener); } } /** * Saves the contents of this editor. * <p> * Subclasses must override this method to implement the open-save-close lifecycle * for an editor. For greater details, see <code>IEditorPart</code> * </p> * * @see IEditorPart */ @Override public void doSave(IProgressMonitor monitor) { // do nothing } /** * Saves the contents of this editor to another object. * <p> * Subclasses must override this method to implement the open-save-close lifecycle * for an editor. For greater details, see <code>IEditorPart</code> * </p> * * @see IEditorPart */ @Override public void doSaveAs() { // do nothing } /** * Returns the title obtained from the parser */ private String getBannerTitle() { if (parser.getTitle() == null) { return ""; //$NON-NLS-1$ } return parser.getTitle(); } /** * Returns the intro item or <code>null</code> */ private WelcomeItem getIntroItem() { return parser.getIntroItem(); } /** * Returns the welcome items */ private WelcomeItem[] getItems() { return parser.getItems(); } /** * Sets the cursor and selection state for this editor to the passage defined * by the given marker. * <p> * Subclasses may override. For greater details, see <code>IEditorPart</code> * </p> * * @see IEditorPart */ public void gotoMarker(IMarker marker) { // do nothing } /** * Initializes the editor part with a site and input. * <p> * Subclasses of <code>EditorPart</code> must implement this method. Within * the implementation subclasses should verify that the input type is acceptable * and then save the site and input. Here is sample code: * </p> * <pre> * if (!(input instanceof IFileEditorInput)) * throw new PartInitException("Invalid Input: Must be IFileEditorInput"); * setSite(site); * setInput(editorInput); * </pre> */ @Override public void init(IEditorSite site, IEditorInput input) throws PartInitException { if (!(input instanceof WelcomeEditorInput)) { throw new PartInitException( "Invalid Input: Must be WelcomeEditorInput"); //$NON-NLS-1$ } setSite(site); setInput(input); } /** * Returns whether the contents of this editor have changed since the last save * operation. * <p> * Subclasses must override this method to implement the open-save-close lifecycle * for an editor. For greater details, see <code>IEditorPart</code> * </p> * * @see IEditorPart */ @Override public boolean isDirty() { return false; } /** * Returns whether the "save as" operation is supported by this editor. * <p> * Subclasses must override this method to implement the open-save-close lifecycle * for an editor. For greater details, see <code>IEditorPart</code> * </p> * * @see IEditorPart */ @Override public boolean isSaveAsAllowed() { return false; } /** * Read the contents of the welcome page * * @param is the <code>InputStream</code> to parse * @throws IOException if there is a problem parsing the stream. */ public void read(InputStream is) throws IOException { try { parser = new WelcomeParser(); } catch (ParserConfigurationException e) { throw (IOException) (new IOException().initCause(e)); } catch (SAXException e) { throw (IOException) (new IOException().initCause(e)); } parser.parse(is); } /** * Reads the welcome file */ public void readFile() { URL url = ((WelcomeEditorInput) getEditorInput()).getAboutInfo() .getWelcomePageURL(); if (url == null) { // should not happen return; } InputStream is = null; try { is = url.openStream(); read(is); } catch (IOException e) { IStatus status = new Status(IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH, 1, IDEWorkbenchMessages.WelcomeEditor_accessException, e); IDEWorkbenchPlugin.log(IDEWorkbenchMessages.WelcomeEditor_readFileError, status); } finally { try { if (is != null) { is.close(); } } catch (IOException e) { } } } /** * Sets the styled text's bold ranges */ private void setBoldRanges(StyledText styledText, int[][] boldRanges) { for (int[] boldRange : boldRanges) { StyleRange r = new StyleRange(boldRange[0], boldRange[1], null, null, SWT.BOLD); styledText.setStyleRange(r); } } /** * Asks this part to take focus within the workbench. * <p> * Clients should not call this method (the workbench calls this method at * appropriate times). * </p> */ @Override public void setFocus() { if ((editorComposite != null) && (lastNavigatedText == null) && (currentText == null)) { editorComposite.setFocus(); } } /** * Sets the styled text's link (blue) ranges */ private void setLinkRanges(StyledText styledText, int[][] linkRanges) { //Color fg = styledText.getDisplay().getSystemColor(SWT.COLOR_BLUE); Color fg = JFaceColors.getHyperlinkText(styledText.getShell() .getDisplay()); for (int[] linkRange : linkRanges) { StyleRange r = new StyleRange(linkRange[0], linkRange[1], fg, null); styledText.setStyleRange(r); hyperlinkRanges.add(r); } } }