From 2f4e9a8fbfce6c7b8943b65dc00f14d90548af4d Mon Sep 17 00:00:00 2001 From: emmanue1 Date: Sat, 20 Jun 2015 21:17:48 +0200 Subject: [PATCH] Adds "Viewer > appearance > Font size" to preferences --- .../ViewerPreferencesProvider.groovy | 92 +++++ .../view/component/AbstractTextPage.groovy | 385 ++++++++++++++++++ .../gui/view/component/ClassFilePage.groovy | 5 +- .../jd/gui/view/component/TextPage.groovy | 344 +--------------- .../services/jd.gui.spi.PreferencesPanel | 1 + 5 files changed, 482 insertions(+), 345 deletions(-) create mode 100644 services/src/main/groovy/jd/gui/service/preferencespanel/ViewerPreferencesProvider.groovy create mode 100644 services/src/main/groovy/jd/gui/view/component/AbstractTextPage.groovy diff --git a/services/src/main/groovy/jd/gui/service/preferencespanel/ViewerPreferencesProvider.groovy b/services/src/main/groovy/jd/gui/service/preferencespanel/ViewerPreferencesProvider.groovy new file mode 100644 index 00000000..5f160924 --- /dev/null +++ b/services/src/main/groovy/jd/gui/service/preferencespanel/ViewerPreferencesProvider.groovy @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2008-2015 Emmanuel Dupuy + * This program is made available under the terms of the GPLv3 License. + */ + +package jd.gui.service.preferencespanel + +import jd.gui.spi.PreferencesPanel +import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea +import org.fife.ui.rsyntaxtextarea.Theme + +import javax.swing.* +import javax.swing.event.DocumentEvent +import javax.swing.event.DocumentListener +import java.awt.* + +class ViewerPreferencesProvider extends JPanel implements PreferencesPanel, DocumentListener { + static final int MIN_VALUE = 2 + static final int MAX_VALUE = 40 + static final String FONT_SIZE_KEY = 'ViewerPreferences.fontSize' + + PreferencesPanel.PreferencesPanelChangeListener listener = null + JTextField fontSizeTextField + Color errorBackgroundColor = Color.RED + Color defaultBackgroundColor + + ViewerPreferencesProvider() { + super(new BorderLayout()) + + add(new JLabel('Font size (' + MIN_VALUE + '..' + MAX_VALUE + '): '), BorderLayout.WEST) + + fontSizeTextField = new JTextField() + fontSizeTextField.document.addDocumentListener(this) + add(fontSizeTextField, BorderLayout.CENTER) + + defaultBackgroundColor = fontSizeTextField.background + } + + // --- PreferencesPanel --- // + String getPreferencesGroupTitle() { 'Viewer' } + String getPreferencesPanelTitle() { 'Appearance' } + + public void init(Color errorBackgroundColor) { + this.errorBackgroundColor = errorBackgroundColor + } + + public boolean isActivated() { true } + + void loadPreferences(Map preferences) { + def fontSize = preferences.get(FONT_SIZE_KEY) + + if (! fontSize) { + // Search default value for the current platform + def textArea = new RSyntaxTextArea() + + def theme = Theme.load(getClass().classLoader.getResourceAsStream('rsyntaxtextarea/themes/eclipse.xml')) + theme.apply(textArea) + + fontSize = textArea.font.size + } + + fontSizeTextField.text = fontSize + fontSizeTextField.setCaretPosition(fontSizeTextField.text.size()) + } + + void savePreferences(Map preferences) { + preferences.put(FONT_SIZE_KEY, fontSizeTextField.text) + } + + boolean arePreferencesValid() { + try { + int i = Integer.valueOf(fontSizeTextField.text) + return (i >= MIN_VALUE) && (i <= MAX_VALUE) + } catch (NumberFormatException ignore) { + return false + } + } + + void addPreferencesChangeListener(PreferencesPanel.PreferencesPanelChangeListener listener) { + this.listener = listener + } + + // --- DocumentListener --- // + void insertUpdate(DocumentEvent e) { onTextChange() } + void removeUpdate(DocumentEvent e) { onTextChange() } + void changedUpdate(DocumentEvent e) { onTextChange() } + + void onTextChange() { + fontSizeTextField.background = arePreferencesValid() ? defaultBackgroundColor : errorBackgroundColor + listener?.preferencesPanelChanged(this) + } +} diff --git a/services/src/main/groovy/jd/gui/view/component/AbstractTextPage.groovy b/services/src/main/groovy/jd/gui/view/component/AbstractTextPage.groovy new file mode 100644 index 00000000..288ed11a --- /dev/null +++ b/services/src/main/groovy/jd/gui/view/component/AbstractTextPage.groovy @@ -0,0 +1,385 @@ +/* + * Copyright (c) 2008-2015 Emmanuel Dupuy + * This program is made available under the terms of the GPLv3 License. + */ + +package jd.gui.view.component + +import groovy.transform.CompileStatic +import jd.gui.api.feature.ContentSearchable +import jd.gui.api.feature.LineNumberNavigable +import jd.gui.api.feature.PreferencesChangeListener +import jd.gui.api.feature.UriOpenable + +import org.fife.ui.rsyntaxtextarea.DocumentRange +import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea +import org.fife.ui.rsyntaxtextarea.RSyntaxTextAreaEditorKit +import org.fife.ui.rsyntaxtextarea.SyntaxConstants +import org.fife.ui.rsyntaxtextarea.Theme +import org.fife.ui.rsyntaxtextarea.folding.FoldManager +import org.fife.ui.rtextarea.RTextScrollPane +import org.fife.ui.rtextarea.SearchContext +import org.fife.ui.rtextarea.SearchEngine + +import javax.swing.* +import javax.swing.text.BadLocationException +import java.awt.* +import java.awt.event.KeyEvent +import java.awt.event.MouseAdapter +import java.awt.event.MouseEvent +import java.awt.event.MouseWheelEvent +import java.awt.event.MouseWheelListener + +/* + * Initially "AbstractTextPage" and "TextPage" were merged, but after a 7th interface has been added, Gradle 2.4/Groovyc 2.3 + * throws "java.lang.OutOfMemoryError: Java heap space". Only valid workaround : split "TextPage" in two files. + */ +@CompileStatic +class AbstractTextPage extends JPanel implements LineNumberNavigable, ContentSearchable, UriOpenable, PreferencesChangeListener { + + protected static final String FONT_SIZE_KEY = 'ViewerPreferences.fontSize' + + protected static final ImageIcon COLLAPSED_ICON = new ImageIcon(AbstractTextPage.class.classLoader.getResource('images/plus.png')) + protected static final ImageIcon EXPANDED_ICON = new ImageIcon(AbstractTextPage.class.classLoader.getResource('images/minus.png')) + + protected static final Color DOUBLE_CLICK_HIGHLIGHT_COLOR = new Color(0x66ff66) + protected static final Color SEARCH_HIGHLIGHT_COLOR = new Color(0xffff66) + protected static final Color SELECT_HIGHLIGHT_COLOR = new Color(0xF49810) + + protected static final RSyntaxTextAreaEditorKit.DecreaseFontSizeAction DECREASE_FONT_SIZE_ACTION = new RSyntaxTextAreaEditorKit.DecreaseFontSizeAction() + protected static final RSyntaxTextAreaEditorKit.IncreaseFontSizeAction INCREASE_FONT_SIZE_ACTION = new RSyntaxTextAreaEditorKit.IncreaseFontSizeAction() + + protected RSyntaxTextArea textArea + protected RTextScrollPane scrollPane + + protected Map preferences + + AbstractTextPage() { + super(new BorderLayout()) + + textArea = newRSyntaxTextArea() + textArea.setSyntaxEditingStyle(getSyntaxStyle()) + textArea.setCodeFoldingEnabled(true); + textArea.setAntiAliasingEnabled(true); + textArea.caretPosition = 0 + textArea.editable = false + textArea.dropTarget = null + textArea.popupMenu = null + textArea.addMouseListener(new MouseAdapter() { + void mouseClicked(MouseEvent e) { + if (e.clickCount == 2) { + textArea.markAllHighlightColor = DOUBLE_CLICK_HIGHLIGHT_COLOR + SearchEngine.markAll(textArea, newSearchContext(textArea.selectedText, true, true, true, false)) + } + } + }) + textArea.addMouseWheelListener(new MouseWheelListener() { + void mouseWheelMoved(MouseWheelEvent e) { + if ((e.modifiers & (Event.META_MASK|Event.CTRL_MASK)) != 0) { + int offset = textArea.viewToModel(new Point(e.x, e.y)) + + // Update font size + if (e.wheelRotation > 0) { + INCREASE_FONT_SIZE_ACTION.actionPerformedImpl(null, textArea) + } else { + DECREASE_FONT_SIZE_ACTION.actionPerformedImpl(null, textArea) + } + + // Save preferences + if (preferences) { + preferences.put(FONT_SIZE_KEY, String.valueOf(textArea.font.size)) + } + + Rectangle newRectangle = textArea.modelToView(offset) + int newY = newRectangle.@y + (newRectangle.@height >> 1) + + // Scroll + Point viewPosition = scrollPane.viewport.viewPosition + viewPosition.@y = Math.max(viewPosition.@y + newY - e.y, 0) + scrollPane.viewport.viewPosition = viewPosition + } + } + }) + + def ctrlA = KeyStroke.getKeyStroke(KeyEvent.VK_A, Toolkit.defaultToolkit.menuShortcutKeyMask) + def ctrlC = KeyStroke.getKeyStroke(KeyEvent.VK_C, Toolkit.defaultToolkit.menuShortcutKeyMask) + def ctrlV = KeyStroke.getKeyStroke(KeyEvent.VK_V, Toolkit.defaultToolkit.menuShortcutKeyMask) + def inputMap = textArea.inputMap + inputMap.put(ctrlA, 'none') + inputMap.put(ctrlC, 'none') + inputMap.put(ctrlV, 'none') + + def theme = Theme.load(getClass().classLoader.getResourceAsStream('rsyntaxtextarea/themes/eclipse.xml')) + theme.apply(textArea) + + scrollPane = new RTextScrollPane(textArea) + scrollPane.foldIndicatorEnabled = true + scrollPane.font = textArea.font + + def gutter = scrollPane.gutter + gutter.setFoldIcons(COLLAPSED_ICON, EXPANDED_ICON) + gutter.foldIndicatorForeground = gutter.borderColor + + add(scrollPane, BorderLayout.CENTER) + add(new ErrorStrip(textArea), BorderLayout.LINE_END) + } + + protected RSyntaxTextArea newRSyntaxTextArea() { new RSyntaxTextArea() } + + String getText() { textArea.text } + + void setText(String text) { + textArea.text = text + textArea.caretPosition = 0 + } + + String getSyntaxStyle() { SyntaxConstants.SYNTAX_STYLE_NONE } + + /** + * @see org.fife.ui.rsyntaxtextarea.RSyntaxUtilities#selectAndPossiblyCenter + * Force center and do not select + */ + void setCaretPositionAndCenter(DocumentRange range) { + int start = range.startOffset + int end = range.endOffset + boolean foldsExpanded = false + FoldManager fm = textArea.foldManager + + if (fm.isCodeFoldingSupportedAndEnabled()) { + foldsExpanded = fm.ensureOffsetNotInClosedFold(start) + foldsExpanded |= fm.ensureOffsetNotInClosedFold(end) + } + + if (foldsExpanded == false) { + try { + Rectangle r = textArea.modelToView(start) + + if (r) { + // Visible + setCaretPositionAndCenter(start, end, r) + } else { + // Not visible yet + SwingUtilities.invokeLater(new Runnable() { + void run() { + r = textArea.modelToView(start) + if (r) { + setCaretPositionAndCenter(start, end, r) + } + } + }) + } + } catch (BadLocationException ignore) { + } + } + } + + protected void setCaretPositionAndCenter(int start, int end, Rectangle r) { + if (end != start) { + r = r.union(textArea.modelToView(end)) + } + + Rectangle visible = textArea.visibleRect + + // visible.@x = r.@x - (visible.@width - r.@width) / 2 as int + visible.@y = r.@y - (visible.@height - r.@height) / 2 as int + + Rectangle bounds = textArea.bounds + Insets i = textArea.insets + //bounds.@x = i.left + bounds.@y = i.top + //bounds.@width -= i.left + i.right + bounds.@height -= i.top + i.bottom + + //if (visible.@x < bounds.@x) { + // visible.@x = bounds.@x + //} + //if (visible.@x + visible.@width > bounds.@x + bounds.@width) { + // visible.@x = bounds.@x + bounds.@width - visible.@width + //} + if (visible.@y < bounds.@y) { + visible.@y = bounds.@y + } + if (visible.@y + visible.@height > bounds.@y + bounds.@height) { + visible.@y = bounds.@y + bounds.@height - visible.@height + } + + textArea.scrollRectToVisible(visible) + textArea.caretPosition = start + } + + // --- LineNumberNavigable --- // + int getMaximumLineNumber() { + return textArea.getLineOfOffset(textArea.document.length) + 1 + } + + void goToLineNumber(int lineNumber) { + textArea.caretPosition = textArea.getLineStartOffset(lineNumber-1) + } + + boolean checkLineNumber(int lineNumber) { true } + + // --- ContentSearchable --- // + boolean highlightText(String text, boolean caseSensitive) { + if (text.length() > 1) { + textArea.markAllHighlightColor = SEARCH_HIGHLIGHT_COLOR + textArea.caretPosition = textArea.selectionStart + + def context = newSearchContext(text, caseSensitive, false, true, false) + def result = SearchEngine.find(textArea, context) + + if (!result.wasFound()) { + textArea.caretPosition = 0 + result = SearchEngine.find(textArea, context) + } + + return result.wasFound() + } else { + return true + } + } + + void findNext(String text, boolean caseSensitive) { + if (text.length() > 1) { + textArea.markAllHighlightColor = SEARCH_HIGHLIGHT_COLOR + + def context = newSearchContext(text, caseSensitive, false, true, false) + def result = SearchEngine.find(textArea, context) + + if (!result.wasFound()) { + textArea.caretPosition = 0 + SearchEngine.find(textArea, context) + } + } + } + + void findPrevious(String text, boolean caseSensitive) { + if (text.length() > 1) { + textArea.markAllHighlightColor = SEARCH_HIGHLIGHT_COLOR + + def context = newSearchContext(text, caseSensitive, false, false, false) + def result = SearchEngine.find(textArea, context) + + if (!result.wasFound()) { + textArea.caretPosition = textArea.document.length + SearchEngine.find(textArea, context) + } + } + } + + protected SearchContext newSearchContext( + String searchFor, boolean matchCase, boolean wholeWord, boolean searchForward, boolean regexp) { + def context = new SearchContext(searchFor, matchCase) + context.markAll = true + context.wholeWord = wholeWord + context.searchForward = searchForward + context.regularExpression = regexp + return context + } + + // --- UriOpenable --- // + boolean openUri(URI uri) { + def query = uri.query + + if (query) { + Map parameters = parseQuery(query) + + if (parameters.containsKey('lineNumber')) { + def lineNumber = parameters.get('lineNumber') + if (lineNumber.isNumber()) { + goToLineNumber(lineNumber.toInteger()) + return true + } + } else if (parameters.containsKey('position')) { + def position = parameters.get('position') + if (position.isNumber()) { + int pos = position.toInteger() + if (textArea.document.length > pos) { + setCaretPositionAndCenter(new DocumentRange(pos, pos)) + return true + } + } + } else if (parameters.containsKey('highlightFlags')) { + def highlightFlags = parameters.get('highlightFlags') + + if ((highlightFlags.indexOf('s') != -1) && parameters.containsKey('highlightPattern')) { + textArea.markAllHighlightColor = SELECT_HIGHLIGHT_COLOR + textArea.caretPosition = 0 + + // Highlight all + def searchFor = createRegExp(parameters.get('highlightPattern')) + def context = newSearchContext(searchFor, true, false, true, true) + def result = SearchEngine.find(textArea, context) + + if (result.matchRange) { + textArea.caretPosition = result.matchRange.startOffset + } + + return true + } + } + } + + return false + } + + protected Map parseQuery(String query) { + Map parameters = [:] + + // Parse parameters + for (def param : query.split('&')) { + int index = param.indexOf('=') + + if (index == -1) { + parameters.put(URLDecoder.decode(param, 'UTF-8'), '') + } else { + def key = param.substring(0, index) + def value = param.substring(index+1) + parameters.put(URLDecoder.decode(key, 'UTF-8'), URLDecoder.decode(value, 'UTF-8')) + } + } + + return parameters + } + + /** + * Create a simple regular expression + * + * Rules: + * '*' matchTypeEntries 0 ou N characters + * '?' matchTypeEntries 1 character + */ + static String createRegExp(String pattern) { + int patternLength = pattern.length() + def sbPattern = new StringBuffer(patternLength * 2) + + for (int i = 0; i < patternLength; i++) { + char c = pattern.charAt(i) + + if (c == '*') { + sbPattern.append('.*') + } else if (c == '?') { + sbPattern.append('.') + } else if (c == '.') { + sbPattern.append('\\.') + } else { + sbPattern.append(c) + } + } + + return sbPattern.toString() + } + + // --- PreferencesChangeListener --- // + void preferencesChanged(Map preferences) { + def fontSize = preferences.get(FONT_SIZE_KEY) + + if (fontSize) { + try { + textArea.font = textArea.font.deriveFont(Float.parseFloat(fontSize)) + } catch (Exception ignore) { + } + } + + this.preferences = preferences + } +} diff --git a/services/src/main/groovy/jd/gui/view/component/ClassFilePage.groovy b/services/src/main/groovy/jd/gui/view/component/ClassFilePage.groovy index 98027169..f8bae2bc 100644 --- a/services/src/main/groovy/jd/gui/view/component/ClassFilePage.groovy +++ b/services/src/main/groovy/jd/gui/view/component/ClassFilePage.groovy @@ -11,7 +11,6 @@ import jd.core.loader.Loader import jd.core.loader.LoaderException import jd.core.process.DecompilerImpl import jd.gui.api.API -import jd.gui.api.feature.* import jd.gui.api.model.Container import jd.gui.util.decompiler.ClassFileSourcePrinter import jd.gui.util.decompiler.ContainerLoader @@ -22,7 +21,7 @@ import org.fife.ui.rsyntaxtextarea.SyntaxConstants import javax.swing.text.DefaultCaret import java.awt.Color -class ClassFilePage extends TypePage implements PreferencesChangeListener { +class ClassFilePage extends TypePage { protected static final String ESCAPE_UNICODE_CHARACTERS = 'ClassFileViewerPreferences.escapeUnicodeCharacters' protected static final String OMIT_THIS_PREFIX = 'ClassFileViewerPreferences.omitThisPrefix' @@ -136,6 +135,8 @@ class ClassFilePage extends TypePage implements PreferencesChangeListener { caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE); decompile(preferences) caret.setUpdatePolicy(updatePolicy) + + super.preferencesChanged(preferences) } @CompileStatic diff --git a/services/src/main/groovy/jd/gui/view/component/TextPage.groovy b/services/src/main/groovy/jd/gui/view/component/TextPage.groovy index 5306afc5..b53c2d6d 100644 --- a/services/src/main/groovy/jd/gui/view/component/TextPage.groovy +++ b/services/src/main/groovy/jd/gui/view/component/TextPage.groovy @@ -9,193 +9,13 @@ import groovy.transform.CompileStatic import jd.gui.api.API import jd.gui.api.feature.ContentCopyable import jd.gui.api.feature.ContentSavable -import jd.gui.api.feature.ContentSearchable import jd.gui.api.feature.ContentSelectable -import jd.gui.api.feature.LineNumberNavigable -import jd.gui.api.feature.UriOpenable import jd.gui.util.io.NewlineOutputStream -import org.fife.ui.rsyntaxtextarea.DocumentRange -import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea -import org.fife.ui.rsyntaxtextarea.RSyntaxTextAreaEditorKit -import org.fife.ui.rsyntaxtextarea.SyntaxConstants -import org.fife.ui.rsyntaxtextarea.Theme -import org.fife.ui.rsyntaxtextarea.folding.FoldManager -import org.fife.ui.rtextarea.RTextScrollPane -import org.fife.ui.rtextarea.SearchContext -import org.fife.ui.rtextarea.SearchEngine -import javax.swing.* -import javax.swing.text.BadLocationException -import java.awt.* import java.awt.datatransfer.StringSelection -import java.awt.event.KeyEvent -import java.awt.event.MouseAdapter -import java.awt.event.MouseEvent -import java.awt.event.MouseWheelEvent -import java.awt.event.MouseWheelListener @CompileStatic -class TextPage extends JPanel implements ContentCopyable, ContentSelectable, LineNumberNavigable, ContentSearchable, UriOpenable, ContentSavable { - protected static final ImageIcon COLLAPSED_ICON = new ImageIcon(TextPage.class.classLoader.getResource('images/plus.png')) - protected static final ImageIcon EXPANDED_ICON = new ImageIcon(TextPage.class.classLoader.getResource('images/minus.png')) - - protected static final Color DOUBLE_CLICK_HIGHLIGHT_COLOR = new Color(0x66ff66) - protected static final Color SEARCH_HIGHLIGHT_COLOR = new Color(0xffff66) - protected static final Color SELECT_HIGHLIGHT_COLOR = new Color(0xF49810) - - protected static final RSyntaxTextAreaEditorKit.DecreaseFontSizeAction DECREASE_FONT_SIZE_ACTION = new RSyntaxTextAreaEditorKit.DecreaseFontSizeAction() - protected static final RSyntaxTextAreaEditorKit.IncreaseFontSizeAction INCREASE_FONT_SIZE_ACTION = new RSyntaxTextAreaEditorKit.IncreaseFontSizeAction() - - protected RSyntaxTextArea textArea - protected RTextScrollPane scrollPane - - TextPage() { - super(new BorderLayout()) - - textArea = newRSyntaxTextArea() - textArea.setSyntaxEditingStyle(getSyntaxStyle()) - textArea.setCodeFoldingEnabled(true); - textArea.setAntiAliasingEnabled(true); - textArea.caretPosition = 0 - textArea.editable = false - textArea.dropTarget = null - textArea.popupMenu = null - textArea.addMouseListener(new MouseAdapter() { - void mouseClicked(MouseEvent e) { - if (e.clickCount == 2) { - textArea.markAllHighlightColor = DOUBLE_CLICK_HIGHLIGHT_COLOR - SearchEngine.markAll(textArea, newSearchContext(textArea.selectedText, true, true, true, false)) - } - } - }) - textArea.addMouseWheelListener(new MouseWheelListener() { - void mouseWheelMoved(MouseWheelEvent e) { - if ((e.modifiers & (Event.META_MASK|Event.CTRL_MASK)) != 0) { - int offset = textArea.viewToModel(new Point(e.x, e.y)) - - // Update font size - if (e.wheelRotation > 0) { - INCREASE_FONT_SIZE_ACTION.actionPerformedImpl(null, textArea) - } else { - DECREASE_FONT_SIZE_ACTION.actionPerformedImpl(null, textArea) - } - - Rectangle newRectangle = textArea.modelToView(offset) - int newY = newRectangle.@y + (newRectangle.@height >> 1) - - // Scroll - Point viewPosition = scrollPane.viewport.viewPosition - viewPosition.translate(0, newY-e.y) - scrollPane.viewport.viewPosition = viewPosition - } - } - }) - - def ctrlA = KeyStroke.getKeyStroke(KeyEvent.VK_A, Toolkit.defaultToolkit.menuShortcutKeyMask) - def ctrlC = KeyStroke.getKeyStroke(KeyEvent.VK_C, Toolkit.defaultToolkit.menuShortcutKeyMask) - def ctrlV = KeyStroke.getKeyStroke(KeyEvent.VK_V, Toolkit.defaultToolkit.menuShortcutKeyMask) - def inputMap = textArea.inputMap - inputMap.put(ctrlA, 'none') - inputMap.put(ctrlC, 'none') - inputMap.put(ctrlV, 'none') - - def theme = Theme.load(getClass().classLoader.getResourceAsStream('rsyntaxtextarea/themes/eclipse.xml')) - theme.apply(textArea) - - scrollPane = new RTextScrollPane(textArea) - scrollPane.foldIndicatorEnabled = true - scrollPane.font = textArea.font - - def gutter = scrollPane.gutter - gutter.setFoldIcons(COLLAPSED_ICON, EXPANDED_ICON) - gutter.foldIndicatorForeground = gutter.borderColor - - add(scrollPane, BorderLayout.CENTER) - add(new ErrorStrip(textArea), BorderLayout.LINE_END) - } - - protected RSyntaxTextArea newRSyntaxTextArea() { new RSyntaxTextArea() } - - String getText() { textArea.text } - - void setText(String text) { - textArea.text = text - textArea.caretPosition = 0 - } - - String getSyntaxStyle() { SyntaxConstants.SYNTAX_STYLE_NONE } - - /** - * @see org.fife.ui.rsyntaxtextarea.RSyntaxUtilities#selectAndPossiblyCenter - * Force center and do not select - */ - void setCaretPositionAndCenter(DocumentRange range) { - int start = range.startOffset - int end = range.endOffset - boolean foldsExpanded = false - FoldManager fm = textArea.foldManager - - if (fm.isCodeFoldingSupportedAndEnabled()) { - foldsExpanded = fm.ensureOffsetNotInClosedFold(start) - foldsExpanded |= fm.ensureOffsetNotInClosedFold(end) - } - - if (foldsExpanded == false) { - try { - Rectangle r = textArea.modelToView(start) - - if (r) { - // Visible - setCaretPositionAndCenter(start, end, r) - } else { - // Not visible yet - SwingUtilities.invokeLater(new Runnable() { - void run() { - r = textArea.modelToView(start) - if (r) { - setCaretPositionAndCenter(start, end, r) - } - } - }) - } - } catch (BadLocationException ignore) { - } - } - } - - protected void setCaretPositionAndCenter(int start, int end, Rectangle r) { - if (end != start) { - r = r.union(textArea.modelToView(end)) - } - - Rectangle visible = textArea.visibleRect - - // visible.@x = r.@x - (visible.@width - r.@width) / 2 as int - visible.@y = r.@y - (visible.@height - r.@height) / 2 as int - - Rectangle bounds = textArea.bounds - Insets i = textArea.insets - //bounds.@x = i.left - bounds.@y = i.top - //bounds.@width -= i.left + i.right - bounds.@height -= i.top + i.bottom - - //if (visible.@x < bounds.@x) { - // visible.@x = bounds.@x - //} - //if (visible.@x + visible.@width > bounds.@x + bounds.@width) { - // visible.@x = bounds.@x + bounds.@width - visible.@width - //} - if (visible.@y < bounds.@y) { - visible.@y = bounds.@y - } - if (visible.@y + visible.@height > bounds.@y + bounds.@height) { - visible.@y = bounds.@y + bounds.@height - visible.@height - } - - textArea.scrollRectToVisible(visible) - textArea.caretPosition = start - } +class TextPage extends AbstractTextPage implements ContentCopyable, ContentSelectable, ContentSavable { // --- ContentCopyable --- // void copy() { @@ -211,168 +31,6 @@ class TextPage extends JPanel implements ContentCopyable, ContentSelectable, Lin textArea.selectAll() } - // --- LineNumberNavigable --- // - int getMaximumLineNumber() { - return textArea.getLineOfOffset(textArea.document.length) + 1 - } - - void goToLineNumber(int lineNumber) { - textArea.caretPosition = textArea.getLineStartOffset(lineNumber-1) - } - - boolean checkLineNumber(int lineNumber) { true } - - // --- ContentSearchable --- // - boolean highlightText(String text, boolean caseSensitive) { - if (text.length() > 1) { - textArea.markAllHighlightColor = SEARCH_HIGHLIGHT_COLOR - textArea.caretPosition = textArea.selectionStart - - def context = newSearchContext(text, caseSensitive, false, true, false) - def result = SearchEngine.find(textArea, context) - - if (!result.wasFound()) { - textArea.caretPosition = 0 - result = SearchEngine.find(textArea, context) - } - - return result.wasFound() - } else { - return true - } - } - - void findNext(String text, boolean caseSensitive) { - if (text.length() > 1) { - textArea.markAllHighlightColor = SEARCH_HIGHLIGHT_COLOR - - def context = newSearchContext(text, caseSensitive, false, true, false) - def result = SearchEngine.find(textArea, context) - - if (!result.wasFound()) { - textArea.caretPosition = 0 - SearchEngine.find(textArea, context) - } - } - } - - void findPrevious(String text, boolean caseSensitive) { - if (text.length() > 1) { - textArea.markAllHighlightColor = SEARCH_HIGHLIGHT_COLOR - - def context = newSearchContext(text, caseSensitive, false, false, false) - def result = SearchEngine.find(textArea, context) - - if (!result.wasFound()) { - textArea.caretPosition = textArea.document.length - SearchEngine.find(textArea, context) - } - } - } - - protected SearchContext newSearchContext( - String searchFor, boolean matchCase, boolean wholeWord, boolean searchForward, boolean regexp) { - def context = new SearchContext(searchFor, matchCase) - context.markAll = true - context.wholeWord = wholeWord - context.searchForward = searchForward - context.regularExpression = regexp - return context - } - - // --- UriOpenable --- // - boolean openUri(URI uri) { - def query = uri.query - - if (query) { - Map parameters = parseQuery(query) - - if (parameters.containsKey('lineNumber')) { - def lineNumber = parameters.get('lineNumber') - if (lineNumber.isNumber()) { - goToLineNumber(lineNumber.toInteger()) - return true - } - } else if (parameters.containsKey('position')) { - def position = parameters.get('position') - if (position.isNumber()) { - int pos = position.toInteger() - if (textArea.document.length > pos) { - setCaretPositionAndCenter(new DocumentRange(pos, pos)) - return true - } - } - } else if (parameters.containsKey('highlightFlags')) { - def highlightFlags = parameters.get('highlightFlags') - - if ((highlightFlags.indexOf('s') != -1) && parameters.containsKey('highlightPattern')) { - textArea.markAllHighlightColor = SELECT_HIGHLIGHT_COLOR - textArea.caretPosition = 0 - - // Highlight all - def searchFor = createRegExp(parameters.get('highlightPattern')) - def context = newSearchContext(searchFor, true, false, true, true) - def result = SearchEngine.find(textArea, context) - - if (result.matchRange) { - textArea.caretPosition = result.matchRange.startOffset - } - - return true - } - } - } - - return false - } - - protected Map parseQuery(String query) { - Map parameters = [:] - - // Parse parameters - for (def param : query.split('&')) { - int index = param.indexOf('=') - - if (index == -1) { - parameters.put(URLDecoder.decode(param, 'UTF-8'), '') - } else { - def key = param.substring(0, index) - def value = param.substring(index+1) - parameters.put(URLDecoder.decode(key, 'UTF-8'), URLDecoder.decode(value, 'UTF-8')) - } - } - - return parameters - } - - /** - * Create a simple regular expression - * - * Rules: - * '*' matchTypeEntries 0 ou N characters - * '?' matchTypeEntries 1 character - */ - static String createRegExp(String pattern) { - int patternLength = pattern.length() - def sbPattern = new StringBuffer(patternLength * 2) - - for (int i = 0; i < patternLength; i++) { - char c = pattern.charAt(i) - - if (c == '*') { - sbPattern.append('.*') - } else if (c == '?') { - sbPattern.append('.') - } else if (c == '.') { - sbPattern.append('\\.') - } else { - sbPattern.append(c) - } - } - - return sbPattern.toString() - } - // --- ContentSavable --- // String getFileName() { 'file.txt' } diff --git a/services/src/main/resources/META-INF/services/jd.gui.spi.PreferencesPanel b/services/src/main/resources/META-INF/services/jd.gui.spi.PreferencesPanel index ab309cae..e6f4a9ed 100644 --- a/services/src/main/resources/META-INF/services/jd.gui.spi.PreferencesPanel +++ b/services/src/main/resources/META-INF/services/jd.gui.spi.PreferencesPanel @@ -1,3 +1,4 @@ jd.gui.service.preferencespanel.DirectoryIndexerPreferencesProvider jd.gui.service.preferencespanel.ClassFileSaverPreferencesProvider jd.gui.service.preferencespanel.ClassFileViewerPreferencesProvider +jd.gui.service.preferencespanel.ViewerPreferencesProvider