| /******************************************************************************* |
| * Copyright (c) 2000, 2010 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.ui.texteditor; |
| |
| import java.util.ResourceBundle; |
| |
| import org.osgi.framework.FrameworkUtil; |
| |
| import org.eclipse.swt.custom.StyledText; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Shell; |
| |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| |
| import org.eclipse.jface.dialogs.IDialogSettings; |
| import org.eclipse.jface.dialogs.IInputValidator; |
| import org.eclipse.jface.dialogs.InputDialog; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.window.Window; |
| |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.ITextSelection; |
| |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.internal.texteditor.NLSUtility; |
| import org.eclipse.ui.internal.texteditor.TextEditorPlugin; |
| |
| |
| /** |
| * Action for jumping to a particular line in the editor's text viewer. The user |
| * is requested to enter the line number into an input dialog. The action is |
| * initially associated with a text editor via the constructor, but that can be |
| * subsequently changed using <code>setEditor</code>. |
| * <p> |
| * The following keys, prepended by the given option prefix, are used for |
| * retrieving resources from the given bundle: |
| * </p> |
| * <ul> |
| * <li><code>"dialog.invalid_range"</code> - to indicate an invalid line |
| * number</li> |
| * <li><code>"dialog.invalid_input"</code> - to indicate an invalid line number |
| * format</li> |
| * <li><code>"dialog.title"</code> - the input dialog's title</li> |
| * <li><code>"dialog.message"</code> - the input dialog's message</li> |
| * </ul> |
| * <p> |
| * This class may be instantiated; it is not intended to be subclassed. |
| * </p> |
| * |
| * @noextend This class is not intended to be subclassed by clients. |
| */ |
| public class GotoLineAction extends TextEditorAction { |
| |
| /** |
| * Validates whether the text found in the input field of the dialog forms a valid line number. |
| * A number is valid if it is one to which can be jumped. |
| */ |
| class NumberValidator implements IInputValidator { |
| |
| @Override |
| public String isValid(String input) { |
| |
| if (input == null || input.isEmpty()) |
| return " "; //$NON-NLS-1$ |
| |
| try { |
| int i= Integer.parseInt(input); |
| if (i <= 0 || fLastLine < i) |
| return fBundle.getString(fPrefix + "dialog.invalid_range"); //$NON-NLS-1$ |
| |
| } catch (NumberFormatException x) { |
| return fBundle.getString(fPrefix + "dialog.invalid_input"); //$NON-NLS-1$ |
| } |
| |
| return null; |
| } |
| } |
| |
| /** |
| * Standard input dialog with custom dialog bounds strategy and settings. |
| * |
| * @since 2.0 |
| */ |
| class GotoLineDialog extends InputDialog { |
| |
| public GotoLineDialog(Shell parent, String title, String message, String initialValue, IInputValidator validator) { |
| super(parent, title, message, initialValue, validator); |
| } |
| |
| @Override |
| protected IDialogSettings getDialogBoundsSettings() { |
| String sectionName= getClass().getName() + "_dialogBounds"; //$NON-NLS-1$ |
| IDialogSettings settings = PlatformUI |
| .getDialogSettingsProvider(FrameworkUtil.getBundle(GotoLineAction.class)).getDialogSettings(); |
| IDialogSettings section= settings.getSection(sectionName); |
| if (section == null) |
| section= settings.addNewSection(sectionName); |
| return section; |
| } |
| |
| @Override |
| protected void createButtonsForButtonBar(Composite parent) { |
| super.createButtonsForButtonBar(parent); |
| Button button = getOkButton(); |
| button.setText(GotoLineAction.this.fBundle.getString(fPrefix + "button")); //$NON-NLS-1$ |
| } |
| |
| @Override |
| protected int getDialogBoundsStrategy() { |
| return DIALOG_PERSISTLOCATION; |
| } |
| } |
| |
| /** The biggest valid line number of the presented document */ |
| private int fLastLine; |
| |
| /** This action's resource bundle */ |
| private ResourceBundle fBundle; |
| |
| /** This action's prefix used for accessing the resource bundle */ |
| private String fPrefix; |
| |
| |
| /** |
| * Creates a new action for the given text editor. The action configures its visual |
| * representation from the given resource bundle. |
| * |
| * @param bundle the resource bundle |
| * @param prefix a prefix to be prepended to the various resource keys (described in |
| * <code>ResourceAction</code> constructor), or <code>null</code> if none |
| * @param editor the text editor |
| * @see TextEditorAction#TextEditorAction(ResourceBundle, String, ITextEditor) |
| */ |
| public GotoLineAction(ResourceBundle bundle, String prefix, ITextEditor editor) { |
| super(bundle, prefix, editor); |
| fBundle= bundle; |
| fPrefix= prefix; |
| } |
| |
| /** |
| * Creates a new action for the given text editor. The action configures its visual |
| * representation with default values. |
| * |
| * @param editor the text editor |
| * @see TextEditorAction#TextEditorAction(ResourceBundle, String, ITextEditor) |
| * @since 3.5 |
| */ |
| public GotoLineAction(ITextEditor editor) { |
| super(EditorMessages.getBundleForConstructedKeys(), "Editor.GotoLine.", editor); //$NON-NLS-1$ |
| fBundle= EditorMessages.getBundleForConstructedKeys(); |
| fPrefix= "Editor.GotoLine."; //$NON-NLS-1$ |
| } |
| |
| /** |
| * Jumps to the given line. |
| * |
| * @param line the line to jump to |
| */ |
| private void gotoLine(int line) { |
| |
| ITextEditor editor= getTextEditor(); |
| |
| IDocumentProvider provider= editor.getDocumentProvider(); |
| IDocument document= provider.getDocument(editor.getEditorInput()); |
| try { |
| |
| int start= document.getLineOffset(line); |
| editor.selectAndReveal(start, 0); |
| |
| IWorkbenchPage page= editor.getSite().getPage(); |
| page.activate(editor); |
| |
| } catch (BadLocationException x) { |
| // ignore |
| } |
| } |
| |
| @Override |
| public void run() { |
| ITextEditor editor= getTextEditor(); |
| |
| if (editor == null) |
| return; |
| |
| IDocumentProvider docProvider= editor.getDocumentProvider(); |
| if (docProvider == null) |
| return; |
| |
| IDocument document= docProvider.getDocument(editor.getEditorInput()); |
| if (document == null) |
| return; |
| |
| try { |
| fLastLine= document.getLineOfOffset(document.getLength()) + 1; |
| } catch (BadLocationException ex) { |
| IStatus status= new Status(IStatus.ERROR, TextEditorPlugin.PLUGIN_ID, IStatus.OK, "Go to Line failed", ex); //$NON-NLS-1$ |
| TextEditorPlugin.getDefault().getLog().log(status); |
| return; |
| } |
| |
| String title= fBundle.getString(fPrefix + "dialog.title"); //$NON-NLS-1$ |
| String message= NLSUtility.format(fBundle.getString(fPrefix + "dialog.message"), Integer.valueOf(fLastLine)); //$NON-NLS-1$ |
| |
| String currentLineStr= ""; //$NON-NLS-1$ |
| ISelection selection= editor.getSelectionProvider().getSelection(); |
| if (selection instanceof ITextSelection) { |
| ITextSelection textSelection= (ITextSelection)selection; |
| Control textWidget= editor.getAdapter(Control.class); |
| boolean caretAtStartOfSelection= false; |
| if (textWidget instanceof StyledText) |
| caretAtStartOfSelection= ((StyledText)textWidget).getSelection().x == ((StyledText)textWidget).getCaretOffset(); |
| int currentLine; |
| if (caretAtStartOfSelection) |
| currentLine= textSelection.getStartLine(); |
| else { |
| int endOffset= textSelection.getOffset() + textSelection.getLength(); |
| try { |
| currentLine= document.getLineOfOffset(endOffset); |
| } catch (BadLocationException ex) { |
| currentLine= -1; |
| } |
| } |
| if (currentLine > -1) |
| currentLineStr= Integer.toString(currentLine + 1); |
| } |
| |
| GotoLineDialog d= new GotoLineDialog(editor.getSite().getShell(), title, message, currentLineStr, new NumberValidator()); |
| if (d.open() == Window.OK) { |
| try { |
| int line= Integer.parseInt(d.getValue()); |
| gotoLine(line - 1); |
| } catch (NumberFormatException x) { |
| } |
| } |
| } |
| } |