Skip to content

Instantly share code, notes, and snippets.

@apocalyptech
Created April 18, 2018 03:27
Show Gist options
  • Save apocalyptech/3c79f9ab0397bc7e2830b31b62aeb912 to your computer and use it in GitHub Desktop.
Save apocalyptech/3c79f9ab0397bc7e2830b31b62aeb912 to your computer and use it in GitHub Desktop.
Problem with text formatting in JTextPane/DefaultStyledDocument using setCharacterAttributes()
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);
}
}
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);
}
}
}
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