Decrypter
Decrypter

Reputation: 3000

Setting a highlight on text removes mouse highlight on that text

I am highlighting some text in a text area:

Highlighter highlighter = getHighlighter();
Highlighter.HighlightPainter painter = new DefaultHighlighter.DefaultHighlightPainter(new Color(201, 197, 198));
highlighter.addHighlight(0,10, painter);

This works fine. However I would like the default highlight colour to be used when I highlight the text using my mouse. When the mouse no longer highlights the text, it will revert back to my chosen highlight colour, new Color(201, 197, 198);

It is possible for the mouse highlight to take priority over my set highlight?

Thanks

Upvotes: 3

Views: 564

Answers (2)

mKorbel
mKorbel

Reputation: 109813

maybe (Stas and Rob) implemented own Highlighter where is required to overrive Rectangle/Shape from API against Mouse_selection

but more confortable would be use JTextPane with AttributeSet, but miss there Highlighter with colored Rectangle

for example

import java.awt.Color;
import javax.swing.*;
import javax.swing.text.*;

public class ColorPane extends JTextPane {

    private static final long serialVersionUID = 1L;

    public void appendNaive(Color c, String s) { // naive implementation
        // bad: instiantiates a new AttributeSet object on each call
        SimpleAttributeSet aset = new SimpleAttributeSet();
        StyleConstants.setForeground(aset, c);
        int len = getText().length();
        setCaretPosition(len); // place caret at the end (with no selection)
        setCharacterAttributes(aset, false);
        replaceSelection(s); // there is no selection, so inserts at caret
    }

    public void append(Color c, String s) { // better implementation--uses       
        StyleContext sc = StyleContext.getDefaultStyleContext(); // StyleContext
        AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY,
                StyleConstants.Foreground, c);
        int len = getDocument().getLength(); // same value as
        //getText().length();
        setCaretPosition(len); // place caret at the end (with no selection)
        setCharacterAttributes(aset, false);
        replaceSelection(s); // there is no selection, so inserts at caret
    }

    public static void main(String argv[]) {
        UIManager.put("TextPane.selectionBackground", Color.yellow);
        UIManager.put("TextPane.selectionForeground", Color.blue);
        ColorPane pane = new ColorPane();
        for (int n = 1; n <= 400; n += 1) {
            if (isPrime(n)) {
                pane.append(Color.red, String.valueOf(n) + ' ');
            } else if (isPerfectSquare(n)) {
                pane.append(Color.blue, String.valueOf(n) + ' ');
            } else {
                pane.append(Color.black, String.valueOf(n) + ' ');
            }
        }
        JFrame f = new JFrame("ColorPane example");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setContentPane(new JScrollPane(pane));
        f.setSize(600, 400);
        f.setVisible(true);
    }

    public static boolean isPrime(int n) {
        if (n < 2) {
            return false;
        }
        double max = Math.sqrt(n);
        for (int j = 2; j <= max; j += 1) {
            if (n % j == 0) {
                return false; // j is a factor
            }
        }
        return true;
    }

    public static boolean isPerfectSquare(int n) {
        int j = 1;
        while (j * j < n && j * j > 0) {
            j += 1;
        }
        return (j * j == n);
    }
}

or convert this code from Caret to the Painter

class HighlightCaret extends DefaultCaret {

    private static final Highlighter.HighlightPainter unfocusedPainter = new DefaultHighlighter.DefaultHighlightPainter(new Color(230, 230, 210));
    private static final long serialVersionUID = 1L;
    private boolean isFocused;

    @Override
    protected Highlighter.HighlightPainter getSelectionPainter() {
        return isFocused ? super.getSelectionPainter() : unfocusedPainter;
    }

    @Override
    public void setSelectionVisible(boolean hasFocus) {
        if (hasFocus != isFocused) {
            isFocused = hasFocus;
            super.setSelectionVisible(false);
            super.setSelectionVisible(true);
        }
    }
} 

Upvotes: 1

StanislavL
StanislavL

Reputation: 57381

You can define your own Highlighter and set to the JTextComponent. See DefaultHighlighter.

The order of paints is defined in the method below but highlights and LayeredHighlightInfo aren't accessible to override (package level)

public void paintLayeredHighlights(Graphics g, int p0, int p1,
                       Shape viewBounds,
                       JTextComponent editor, View view) {
    for (int counter = highlights.size() - 1; counter >= 0; counter--) {
        Object tag = highlights.elementAt(counter);
        if (tag instanceof LayeredHighlightInfo) {
        LayeredHighlightInfo lhi = (LayeredHighlightInfo)tag;
        int start = lhi.getStartOffset();
        int end = lhi.getEndOffset();
        if ((p0 < start && p1 > start) ||
            (p0 >= start && p0 < end)) {
            lhi.paintLayeredHighlights(g, p0, p1, viewBounds,
                           editor, view);
        }
        }
    }
}

Upvotes: 1

Related Questions