Created
April 18, 2018 03:27
-
-
Save apocalyptech/3c79f9ab0397bc7e2830b31b62aeb912 to your computer and use it in GitHub Desktop.
Problem with text formatting in JTextPane/DefaultStyledDocument using setCharacterAttributes()
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package testing; | |
import testing.ObjectExplorer; | |
import java.awt.Font; | |
import java.awt.event.MouseAdapter; | |
import java.awt.event.MouseEvent; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Collections; | |
import java.util.logging.Level; | |
import java.util.logging.Logger; | |
import javax.swing.JTextPane; | |
import javax.swing.text.BadLocationException; | |
import javax.swing.text.Element; | |
public final class HighlightedTextArea extends JTextPane { | |
private final List<Object> highlights = new ArrayList<>(); | |
private Logger logger; | |
public HighlightedTextArea() { | |
super(); | |
logger = Logger.getLogger(HighlightedTextArea.class.getName()); | |
setFont(new Font("Courier New", Font.PLAIN, 12)); | |
setDocument(new myStylizedDocument());//Syntax highlighting | |
addLink(); | |
} | |
@Override | |
public String getText() { | |
try { | |
return getDocument().getText(0, getDocument().getLength()); | |
} catch (BadLocationException ex) { | |
Logger.getLogger(HighlightedTextArea.class.getName()).log(Level.SEVERE, null, ex); | |
} | |
return null; | |
} | |
@Override | |
public void setText(String t) { | |
logger.log(Level.INFO, | |
"Setting text (to a new document)"); | |
try { | |
logger.log(Level.INFO, | |
"Old contents: " + getDocument().getText(0, getDocument().getLength())); | |
} catch (Exception e) { | |
logger.log(Level.INFO, | |
"Couldn't get contents!"); | |
} | |
setDocument(new myStylizedDocument()); | |
try { | |
logger.log(Level.INFO, | |
"New contents: " + getDocument().getText(0, getDocument().getLength())); | |
} catch (Exception e) { | |
logger.log(Level.INFO, | |
"Couldn't get contents!"); | |
} | |
super.setText(t); | |
logger.log(Level.INFO, | |
"Text has been set."); | |
} | |
private void addLink() { | |
MouseAdapter adapter = new MouseAdapter() { | |
@Override | |
public void mousePressed(MouseEvent e) { | |
if (e.getClickCount() == 2) { | |
logger.log(Level.INFO, | |
"Received mouse click for URL"); | |
ObjectExplorer.INSTANCE.update(); | |
} | |
} | |
}; | |
this.addMouseListener(adapter); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package testing; | |
import java.awt.Color; | |
import javax.swing.text.AttributeSet; | |
import javax.swing.text.BadLocationException; | |
import javax.swing.text.DefaultStyledDocument; | |
import javax.swing.text.MutableAttributeSet; | |
import javax.swing.text.SimpleAttributeSet; | |
import javax.swing.text.StyleConstants; | |
import java.util.logging.Logger; | |
import java.util.logging.Level; | |
public class myStylizedDocument extends DefaultStyledDocument { | |
private final MutableAttributeSet normal; | |
private final MutableAttributeSet quote; | |
private Logger logger; | |
public myStylizedDocument() { | |
logger = Logger.getLogger(myStylizedDocument.class.getName()); | |
normal = new SimpleAttributeSet(); | |
StyleConstants.setForeground(normal, Color.BLACK); | |
quote = new SimpleAttributeSet(); | |
StyleConstants.setForeground(quote, Color.RED); | |
} | |
/* | |
* Override to apply syntax highlighting after the document has been updated | |
*/ | |
@Override | |
public void insertString(int offset, String str, AttributeSet a) throws BadLocationException { | |
super.insertString(offset, str, a); | |
Logger.getLogger(myStylizedDocument.class.getName()).log( | |
Level.INFO, | |
"In insertString, about to apply highlighting"); | |
// Hardcoding this syntax highlight for simplicity's sake | |
String content = getText(0, getLength()); | |
int firstIdx = content.indexOf("'"); | |
int secondIdx = content.lastIndexOf("'"); | |
if (firstIdx != -1 && secondIdx != -1) { | |
setCharacterAttributes(firstIdx, secondIdx-firstIdx, quote, false); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package testing; | |
import testing.HighlightedTextArea; | |
import java.awt.BorderLayout; | |
public final class ObjectExplorer extends javax.swing.JFrame { | |
public static ObjectExplorer INSTANCE = null; | |
private final HighlightedTextArea textElement; | |
private int counter; | |
/** | |
* Creates new form DumpFrame | |
*/ | |
public ObjectExplorer() { | |
initComponents(); | |
INSTANCE = this; | |
counter = 0; | |
textElement = new HighlightedTextArea(); | |
textElement.setEditable(false); | |
jPanel1.setLayout(new BorderLayout()); | |
jPanel1.add(textElement); | |
// Pretend to have some data. | |
setText("(\n ALinkToSee = AttributeType'GD_Foo_Bar.Baz.Frotz'\n)\n"); | |
} | |
/** | |
* @param args the command line arguments | |
*/ | |
public static void main(String args[]) { | |
/* Create and display the form */ | |
new ObjectExplorer().setVisible(true); | |
} | |
public void update() { | |
counter++; | |
setText(String.format( | |
"(\n NewFakeData = AnotherAttribute'GD_Omg_Wtf.NotReal.Stuff%d'\n)\n", | |
counter)); | |
} | |
private void setText(String text) { | |
textElement.setText(text); | |
} | |
@Override | |
public void dispose() { | |
INSTANCE = null; | |
super.dispose(); | |
System.exit(0); | |
} | |
/** | |
* This method is called from within the constructor to initialize the form. | |
* WARNING: Do NOT modify this code. The content of this method is always | |
* regenerated by the Form Editor. | |
*/ | |
@SuppressWarnings("unchecked") | |
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents | |
private void initComponents() { | |
jPanel1 = new javax.swing.JPanel(); | |
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); | |
setTitle("Object Explorer"); | |
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); | |
jPanel1.setLayout(jPanel1Layout); | |
jPanel1Layout.setHorizontalGroup( | |
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) | |
.addGap(0, 977, Short.MAX_VALUE) | |
); | |
jPanel1Layout.setVerticalGroup( | |
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) | |
.addGap(0, 537, Short.MAX_VALUE) | |
); | |
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); | |
getContentPane().setLayout(layout); | |
layout.setHorizontalGroup( | |
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) | |
.addGroup(layout.createSequentialGroup() | |
.addContainerGap() | |
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) | |
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) | |
); | |
layout.setVerticalGroup( | |
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) | |
.addGroup(layout.createSequentialGroup() | |
.addContainerGap() | |
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) | |
.addContainerGap(13, Short.MAX_VALUE)) | |
); | |
pack(); | |
}// </editor-fold>//GEN-END:initComponents | |
// Variables declaration - do not modify//GEN-BEGIN:variables | |
private javax.swing.JPanel jPanel1; | |
// End of variables declaration//GEN-END:variables | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment