diff --git a/AutoComplete/src/main/java/org/fife/ui/autocomplete/AbstractDescriptionWindow.java b/AutoComplete/src/main/java/org/fife/ui/autocomplete/AbstractDescriptionWindow.java new file mode 100644 index 0000000..ee0868e --- /dev/null +++ b/AutoComplete/src/main/java/org/fife/ui/autocomplete/AbstractDescriptionWindow.java @@ -0,0 +1,64 @@ +package org.fife.ui.autocomplete; + +import org.fife.ui.rsyntaxtextarea.PopupWindowDecorator; + +import javax.swing.*; +import java.awt.*; + +public abstract class AbstractDescriptionWindow extends JWindow { + + public AbstractDescriptionWindow(Window owner) { + super(owner); + + assert owner instanceof AutoCompletePopupWindow; + + setFocusableWindowState(false); + + if (Util.getShouldAllowDecoratingMainAutoCompleteWindows()) { + PopupWindowDecorator decorator = PopupWindowDecorator.get(); + if (decorator != null) { + decorator.decorate(this); + } + } + } + + /** + * Creates the {@link SizeGrip} with the background specified in the {@link AutoCompletion} + * @return A new {@link SizeGrip} + */ + public JPanel createSizeGrip() { + SizeGrip rp = new SizeGrip(); + rp.setBackground(getAutoCompletion().getDescWindowColor()); + return rp; + } + + public AutoCompletion getAutoCompletion() { + if (getOwner() instanceof AutoCompletePopupWindow) { + AutoCompletePopupWindow popupWindow = (AutoCompletePopupWindow) getOwner(); + return popupWindow.getAutoCompletion(); + } else { + throw new IllegalStateException("The owner is not a AutoCompletePopupWindow"); + } + } + + /** + * Called by the parent completion popup window the {@link LookAndFeel} is updated. + */ + public void updateUI() { + SwingUtilities.updateComponentTreeUI(this); + } + + /** + * Copies from the description text area, if it is visible and there is a selection. + * + * @return Whether a copy occurred. + */ + public abstract boolean copy(); + + /** + * Sets the description displayed in this window. + * + * @param item The item whose description you want to display. + */ + public abstract void setDescriptionFor(Completion item); +} diff --git a/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompleteDescWindow.java b/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompleteDescWindow.java index 620a213..2d0f504 100644 --- a/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompleteDescWindow.java +++ b/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompleteDescWindow.java @@ -9,6 +9,13 @@ */ package org.fife.ui.autocomplete; +import org.fife.ui.rsyntaxtextarea.PopupWindowDecorator; + +import javax.swing.*; +import javax.swing.border.AbstractBorder; +import javax.swing.border.Border; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; import java.awt.*; import java.awt.event.ActionEvent; import java.lang.reflect.InvocationTargetException; @@ -19,26 +26,6 @@ import java.util.ArrayList; import java.util.List; import java.util.ResourceBundle; -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JEditorPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JToolBar; -import javax.swing.JWindow; -import javax.swing.SwingUtilities; -import javax.swing.Timer; -import javax.swing.UIManager; -import javax.swing.border.AbstractBorder; -import javax.swing.border.Border; -import javax.swing.event.HyperlinkEvent; -import javax.swing.event.HyperlinkListener; - -import org.fife.ui.rsyntaxtextarea.PopupWindowDecorator; /** @@ -48,13 +35,13 @@ * @author Robert Futrell * @version 1.0 */ -class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, - DescWindowCallback { +class AutoCompleteDescWindow extends AbstractDescriptionWindow + implements HyperlinkListener, DescWindowCallback { /** * The parent AutoCompletion instance. */ - private AutoCompletion ac; + private final AutoCompletion ac; /** * Renders the HTML description. @@ -97,12 +84,12 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, * completions, those with slow-to-calculate summaries won't bog down the * scrolling. */ - private Timer timer; + private final Timer timer; /** * The action that listens for the timer to fire. */ - private TimerAction timerAction; + private final TimerAction timerAction; /** * The resource bundle for this window. @@ -115,13 +102,12 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, * performance for {@link Completion}s that may be slow to compute their * summary text. */ - private static final int INITIAL_TIMER_DELAY = 120; + private static final int INITIAL_TIMER_DELAY = 120; /** * The resource bundle name. */ - private static final String MSG = - "org.fife.ui.autocomplete.AutoCompleteDescWindow"; + private static final String MSG = "org.fife.ui.autocomplete.AutoCompleteDescWindow"; private static final String FLAT_LAF_BORDER_PREFIX = "com.formdev.flatlaf.ui.Flat"; @@ -177,10 +163,8 @@ public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { }; bottomPanel.setBorder(b); bottomPanel.setBackground(ac.getDescWindowColor()); - SizeGrip rp = new SizeGrip(); bottomPanel.add(descWindowNavBar, BorderLayout.LINE_START); - bottomPanel.add(rp, BorderLayout.LINE_END); - rp.setBackground(ac.getDescWindowColor()); + bottomPanel.add(createSizeGrip(), BorderLayout.LINE_END); cp.add(bottomPanel, BorderLayout.SOUTH); setContentPane(cp); @@ -205,6 +189,32 @@ public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { } + /** + * Append the {@code action} at the end of the bottom nav-bar of the window. + * + * @param action The {@link Action} to add + * @return The new button which dispatches the action + */ + public JButton addToNavBar(Action action) { + return addToNavBar(action, false); + } + + + /** + * Append the {@code action} at the end of the bottom nav-bar of the window. + * + * @param action The {@link Action} to add + * @param addSeparatorBefore If {@code true}, add a {@link JSeparator} before the {@code action} + * @return The new button which dispatches the action + */ + public JButton addToNavBar(Action action, boolean addSeparatorBefore) { + if (addSeparatorBefore) { + descWindowNavBar.addSeparator(); + } + return descWindowNavBar.add(action); + } + + /** * Sets the currently displayed description and updates the history. * @@ -246,6 +256,7 @@ private void clearHistoryAfterCurrentPos() { * * @return Whether a copy occurred. */ + @Override public boolean copy() { if (isVisible() && descArea.getSelectionStart()!=descArea.getSelectionEnd()) { @@ -427,6 +438,7 @@ private void setActionStates() { * * @param item The item whose description you want to display. */ + @Override public void setDescriptionFor(Completion item) { setDescriptionFor(item, false); } @@ -510,6 +522,7 @@ public void showSummaryFor(Completion completion, String anchor) { /** * Called by the parent completion popup window the LookAndFeel is updated. */ + @Override public void updateUI() { SwingUtilities.updateComponentTreeUI(this); // Update editor pane for new font, bg, selection colors, etc. @@ -525,12 +538,11 @@ public void updateUI() { */ private static class HistoryEntry { - private Completion completion; - private String summary; - private String anchor; + private final Completion completion; + private final String summary; + private final String anchor; - HistoryEntry(Completion completion, String summary, - String anchor) { + HistoryEntry(Completion completion, String summary, String anchor) { this.completion = completion; this.summary = summary; this.anchor = anchor; @@ -567,8 +579,7 @@ public void actionPerformed(ActionEvent e) { setDisplayedDesc(completion, anchor, addToHistory); } - void setCompletion(Completion c, String anchor, - boolean addToHistory) { + void setCompletion(Completion c, String anchor, boolean addToHistory) { this.completion = c; this.anchor = anchor; this.addToHistory = addToHistory; diff --git a/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompletePopupWindow.java b/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompletePopupWindow.java index 14ad7f8..eec12b3 100644 --- a/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompletePopupWindow.java +++ b/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompletePopupWindow.java @@ -9,23 +9,9 @@ */ package org.fife.ui.autocomplete; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.util.List; -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.ActionMap; -import javax.swing.InputMap; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JWindow; -import javax.swing.KeyStroke; -import javax.swing.ListCellRenderer; -import javax.swing.SwingUtilities; +import org.fife.ui.rsyntaxtextarea.PopupWindowDecorator; + +import javax.swing.*; import javax.swing.event.CaretEvent; import javax.swing.event.CaretListener; import javax.swing.event.ListSelectionEvent; @@ -33,8 +19,12 @@ import javax.swing.plaf.ListUI; import javax.swing.text.Caret; import javax.swing.text.JTextComponent; - -import org.fife.ui.rsyntaxtextarea.PopupWindowDecorator; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.List; /** @@ -49,22 +39,22 @@ */ @SuppressWarnings("checkstyle:MultipleVariableDeclarations") class AutoCompletePopupWindow extends JWindow implements CaretListener, - ListSelectionListener, MouseListener { + ListSelectionListener, MouseListener { /** * The parent AutoCompletion instance. */ - private AutoCompletion ac; + private final AutoCompletion ac; /** * The list of completion choices. */ - private PopupList list; + private final PopupList list; /** * The contents of {@link #list()}. */ - private CompletionListModel model; + private final CompletionListModel model; /** * A hack to work around the fact that we clear our completion model (and @@ -77,7 +67,7 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, * Optional popup window containing a description of the currently * selected completion. */ - private AutoCompleteDescWindow descWindow; + private AbstractDescriptionWindow descWindow; /** * The preferred size of the optional description window. This field @@ -211,23 +201,28 @@ else if (AutoCompletion.getDebug()) { * * @return The description window. */ - private AutoCompleteDescWindow createDescriptionWindow() { + private AbstractDescriptionWindow createDescriptionWindow() { + + AbstractDescriptionWindow dw; - AutoCompleteDescWindow dw = new AutoCompleteDescWindow(this, ac); + if (ac.getDescriptionWindowFactory() == null) { + dw = new AutoCompleteDescWindow(this, ac); + } else { + dw = ac.getDescriptionWindowFactory().apply(this); + } dw.applyComponentOrientation(ac.getTextComponentOrientation()); Dimension size = preferredDescWindowSize; - if (size==null) { + if (size == null) { size = getSize(); } dw.setSize(size); - if (descWindowColor != null) { - dw.setBackground(descWindowColor); - } - else { - descWindowColor = dw.getBackground(); - } + if (descWindowColor != null) { + dw.setBackground(descWindowColor); + } else { + descWindowColor = dw.getBackground(); + } return dw; } @@ -276,6 +271,13 @@ protected void doAutocomplete() { } + /** + * @return The {@link AutoCompletion} object + */ + AutoCompletion getAutoCompletion() { + return ac; + } + /** * Returns the copy keystroke to use for this platform. * @@ -308,9 +310,8 @@ public Color getDescriptionWindowColor() { * @return The default list cell renderer. * @see #setListCellRenderer(ListCellRenderer) */ - public ListCellRenderer getListCellRenderer() { - DelegatingCellRenderer dcr = (DelegatingCellRenderer)list. - getCellRenderer(); + public ListCellRenderer getListCellRenderer() { + DelegatingCellRenderer dcr = (DelegatingCellRenderer) list.getCellRenderer(); return dcr.getFallbackCellRenderer(); } diff --git a/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompletion.java b/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompletion.java index 5653c82..819458c 100644 --- a/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompletion.java +++ b/AutoComplete/src/main/java/org/fife/ui/autocomplete/AutoCompletion.java @@ -12,6 +12,8 @@ import java.awt.event.*; import java.beans.*; import java.util.List; +import java.util.concurrent.Callable; +import java.util.function.Function; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; @@ -90,6 +92,11 @@ public class AutoCompletion { */ private CompletionProvider provider; + /** + * If set, provides a description window different from the default {@link AutoCompleteDescWindow}. + */ + private Function descriptionWindowFactory; + /** * The renderer to use for the completion choices. If this is * null, then a default renderer is used. @@ -385,6 +392,9 @@ public static KeyStroke getDefaultTriggerKey() { return KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, mask); } + Function getDescriptionWindowFactory() { + return descriptionWindowFactory; + } /** * Returns the handler to use when an external URL is clicked in the @@ -857,8 +867,7 @@ protected int refreshPopupWindow() { popupWindow.setSize(preferredChoicesWindowSize); } if (preferredDescWindowSize != null) { - popupWindow - .setDescriptionWindowSize(preferredDescWindowSize); + popupWindow.setDescriptionWindowSize(preferredDescWindowSize); } } @@ -867,8 +876,7 @@ protected int refreshPopupWindow() { if (!popupWindow.isVisible()) { Rectangle r; try { - r = textComponent.modelToView(textComponent - .getCaretPosition()); + r = textComponent.modelToView(textComponent.getCaretPosition()); } catch (BadLocationException ble) { ble.printStackTrace(); return -1; @@ -988,6 +996,13 @@ public void setCompletionProvider(CompletionProvider provider) { } } + /** + * Set a {@link AbstractDescriptionWindow} provider. By default, a {@link AutoCompleteDescWindow} is used. + * @param descriptionWindowFactory A {@link Callable} returning an instance of a {@link AbstractDescriptionWindow} + */ + public void setDescriptionWindowFactory(Function descriptionWindowFactory) { + this.descriptionWindowFactory = descriptionWindowFactory; + } /** * Sets the size of the completion choices window.