Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing color of selected text in jTextPane

I am creating a text editor using a JTextPane that allows the user to change the color of selected text. But when the user selects the text, then chooses the option to change the color (say, to red) the text does not appear as red until the text is unselected. I tried using setSelectedTextColor to change the color of the selected text, but that doesn't work since that changes the text to red anytime text is selected afterwards. Is there a way to have selected text show up as it's actual color? Or like the way it works in Word where it's not the actual color of the text, but when text of different colors are selected they show up as different colors even when selected.

I use the following code to set up the JTextPane and button that changes the selected text to red:

JButton redButton = new JButton(new StyledEditorKit.ForegroundAction("red", Color.RED));
redButton.setFocusable(false);
buttonPanel.add(redButton);

The JTextPane is set up as with content type HTML and uses the HTMLEditorKit:

p=new JTextPane();
p.setSize(300, 300);
kit = new HTMLEditorKit();
p.setEditorKit(kit);
p.setDocument(kit.createDefaultDocument());

p.setContentType("text/html");
p.setEditable(true);

Let me know if you need more source code to understand the question. Thank You!

like image 310
smith8ar Avatar asked Sep 30 '13 16:09

smith8ar


1 Answers

Take a look at the DefaultHighlightPainter inner class of DefaultHighlighter.

The method

    public void paint(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c) {
        Rectangle alloc = bounds.getBounds();
        try {
            // --- determine locations ---
            TextUI mapper = c.getUI();
            Rectangle p0 = mapper.modelToView(c, offs0);
            Rectangle p1 = mapper.modelToView(c, offs1);

            // --- render ---
            Color color = getColor();

            if (color == null) {
                g.setColor(c.getSelectionColor());
            }
            else {
                g.setColor(color);
            }

As you can see it uses either getColor() or getSelectionColor(). You can extend the class and adapt the highlight painting.

Or use a simpler approach to override your JTextPane's getSelectionColor(). In the method just check whether text is selected and use attributes of selected elements to get desired ccolor. If nothing is selected just return super.getSelectedColor()

UPDATE: Actually applying colors for selection is used on low level GlyphView's public void paint(Graphics g, Shape a) { ... JTextComponent tc = (JTextComponent) c; Color selFG = tc.getSelectedTextColor();

        if (// there's a highlighter (bug 4532590), and
            (tc.getHighlighter() != null) &&
            // selected text color is different from regular foreground
            (selFG != null) && !selFG.equals(fg)) {

            Highlighter.Highlight[] h = tc.getHighlighter().getHighlights();
            if(h.length != 0) {
                boolean initialized = false;
                int viewSelectionCount = 0;
                for (int i = 0; i < h.length; i++) {
                    Highlighter.Highlight highlight = h[i];
                    int hStart = highlight.getStartOffset();
                    int hEnd = highlight.getEndOffset();
                    if (hStart > p1 || hEnd < p0) {
                        // the selection is out of this view
                        continue;
                    }
                    if (!SwingUtilities2.useSelectedTextColor(highlight, tc)) {
                        continue;
                    }

...

As you can see applying selection color vs default color of the view is defined in the SwingUtilities2.useSelectedTextColor(highlight, tc)

In the sources http://kickjava.com/src/com/sun/java/swing/SwingUtilities2.java.htm

 public static boolean useSelectedTextColor(Highlighter.Highlight  JavaDoc h, JTextComponent  JavaDoc c) {
     Highlighter.HighlightPainter  JavaDoc painter = h.getPainter();
     String  JavaDoc painterClass = painter.getClass().getName();
     if (painterClass.indexOf("javax.swing.text.DefaultHighlighter") != 0 &&
             painterClass.indexOf("com.sun.java.swing.plaf.windows.WindowsTextUI") != 0) {
         return false;
     }
     try {
         DefaultHighlighter.DefaultHighlightPainter  JavaDoc defPainter =
                 (DefaultHighlighter.DefaultHighlightPainter  JavaDoc) painter;
         if (defPainter.getColor() != null &&
                 !defPainter.getColor().equals(c.getSelectionColor())) {
             return false;
         }
     } catch (ClassCastException  JavaDoc e) {
         return false;
     }
     return true;
 }

So using the color depends on L&F and painter. If you define your onw painter the color won't be used.

like image 53
StanislavL Avatar answered Oct 02 '22 19:10

StanislavL