I'm trying to imitate a similar code seen here http://www.openprocessing.org/sketch/7050 but I seem to have gotten a little mixed up with the code. I'm trying to get the effect of the letters essentially drawing the posterized image of the picture. But I have getting a NullPointException and assume is has to do with how I'm initializing the string variables but i can't seem to find what I'm doing wrong.
The Error
Exception in thread "Animation Thread" java.lang.NullPointerException
at processing.opengl.PGL.getString(PGL.java:1029)
at processing.opengl.PGraphicsOpenGL.getGLParameters(PGraphicsOpenGL.java:6076)
at processing.opengl.PGraphicsOpenGL.beginDraw(PGraphicsOpenGL.java:1547)
at MLKpractice.letterfit(MLKpractice.java:147)
at MLKpractice.draw(MLKpractice.java:98)
at processing.core.PApplet.handleDraw(PApplet.java:2120)
at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:197)
at processing.core.PApplet.run(PApplet.java:1998)
at java.lang.Thread.run(Thread.java:680)
The program says the error is on line 127
lettersquare.beginDraw();
But I believe the error is somewhere above
PFont font;
String fontpath = "ArialMT-200.vlw";
int fontstart = 300;
int fontend = 8;
float fontsize = fontstart;
float fontsizedecrease = 0.97;
PImage bg;
PImage australia;
PImage austria;
String country1 = "australia.jpg";
String country2 = "austria.jpg";
String letters = "Australia";
char[] chars = new char[52];
int nchars = 0;
int iterations = 500;
int c = 0;
PGraphics letter,lettersquare,drawing;
void setup(){
//initialize the sketch
size(900,600);
//background(255);
//initialize the font
//font = loadFont(fontpath);
///*
for(int i=0;i<letters.length();i++){
boolean found = false;
char lc = letters.charAt(i);
for(int j=0;j<nchars;j++){
if(chars[j]==lc){
found = true;
break;
}
}
if(!found) chars[nchars++] = lc;
}
chars = (char[]) subset(chars,0,nchars);
font = createFont("Arial",200,true,chars);
//*/
textAlign(CENTER,CENTER);
//load the image that will be filled with letters
australia = loadImage(country1);
austria = loadImage(country2);
bg = loadImage("background.jpg");
//posterize the image
australia.filter(THRESHOLD,0.4);
australia.filter(BLUR,3);
australia.filter(THRESHOLD,0.6);
//initialize the drawing buffers
letter = createGraphics((int)fontsize,(int)fontsize,JAVA2D);
lettersquare = createGraphics((int)fontsize,(int)fontsize,P2D);
drawing = createGraphics(width,height,JAVA2D);
drawing.beginDraw();
drawing.background(255);
// THIS STUPID THING NEEDS TO GO HERE!!!!
drawing.image(bg,0,0);
drawing.endDraw();
}
void draw(){
if(floor(fontsize)>fontend&&c<letters.length()-1){
if(!letterfit()){
fontsize *= fontsizedecrease;
}else{
c++;
if(c==11){
fontsize *= 0.75;
}
}
tint(255);
image(drawing,0,0);
if (keyCode == LEFT) {
image(austria,0,0);
}
// if (keyCode == RIGHT) {
// frog1.frogx = frog1.frogx + 1;
// }
if(mousePressed){
tint(255,100);
image(australia,0,0);
}
}else{
tint(255);
image(drawing,0,0);
println(c+" "+letters.length());
/*
save("mlk-"+hour()+""+minute()+""+second()+".tif");
exit();
*/
noLoop();
}
}
boolean letterfit(){
letter.beginDraw();
letter.background(255,0);
letter.fill(0);
letter.textAlign(CENTER,CENTER);
letter.translate(fontsize/2,fontsize/2);
letter.rotate(random(TWO_PI));
letter.scale(fontsize/fontstart);
letter.textFont(font);
letter.smooth();
letter.text(letters.charAt(c),0,0);
letter.endDraw();
lettersquare.beginDraw();
You've most likely been hit by issue 1217, which prevents you from using an OpenGL PGraphics renderer if the main renderer is Java2D.
The link has a workaround, which basically involves changing the main renderer to OpenGL.
A newer version of PGraphics should give you a more detailed exception.
Related
It seems like the for loop in my code is not stopping after it iterated througt the counter. it seems to restart, checked with the print function and the length of the directory list seems to be recognized but then it restarts from 0 and so on. First time coding with java and in general i do not have much experience in coding, logic experience comes from visual coding and little bit of python. if somebody can help it would be great.
here is the code,
to run it you need will need processing (https://processing.org/download) and some images in the input folder. thougth this is an easy problem, thats why i still post it here.
I know its not pretty so pls dont hate on it
int dim = 1024;
PImage img;
String inDir;
import java.util.*;
import java.text.DecimalFormat;
String outDir;
String nameSpace;
String nameSpaceOut;
PGraphics pg;
void setup() {
size(1024, 1024);
inDir = "C:/Users/Fynn/Desktop/processing-3.5.4/Resizematte/data/Input 1/";
outDir = "C:/Users/Fynn/Desktop/processing-3.5.4/Resizematte/data/Output 3/";
nameSpace = "ImageToResize";
pg = createGraphics(dim, dim);
nameSpaceOut = "Resized";
}
void draw () {
background(0);
pg.beginDraw();
File dir = new File(inDir);
String[] filenames = dir.list();
for (int i = 0; i < filenames.length; i++) {
background(255, 255, 255);
String fName = inDir + filenames[i];
img = loadImage(fName);
if (img != null) {
float w = img.width;
float h = img.height;
float m = w;
float f = h;
if (h > w) { //change to < for crop > for matte
m = h;
f = w;
}
float factor = (dim/m);
if(h > w){
img.resize(int(f*factor), int(m*factor));
}
else {
img.resize(int(m*factor), int(f*factor));
}
image(img, width/2-img.width/2, height/2-img.height/2);
String outName1 = outDir + nameSpaceOut + "_" + i +".png";
save(outName1);
}
}
}
i try to format pictures which i want to use as a data set input for a GAN machine learnign algorithm.
I've been wanting to design a generator for dragon curves.
(If you want info on that check this out, but it doesn't really matter for the issue)
A dragon curve is a repeating mathematical construct.
I've already written a generator for what the canvas should draw, it works by returning a char array consisting of 'r' or 'l', saying whether the line has to turn left or right next. In the code here, it's the method input(). This part works perfectly.
The problem is that whenever I want to draw it on the canvas (using drawLine), it only draws the first two lines as actual lines, the rest are just dots.
The dots are on the right positions and if you make the thing really big, you can't tell the difference anymore, but nevertheless, there are supposed to be lines there.
Image:
This is the code I used:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
/**
*
* Description
*
* #version 1.0 from 4/20/2016
* #author
*/
public class CurveGen extends JFrame {
// start attributes
private Canvas display = new Canvas();
private JButton startButton = new JButton();
private JLabel jLabel1 = new JLabel();
private JTextArea outText = new JTextArea("");
private JScrollPane outTextScrollPane = new JScrollPane(outText);
private JLabel jLabel2 = new JLabel();
private JSlider xSlider = new JSlider();
private JSlider ySlider = new JSlider();
private JNumberField iterationsNF = new JNumberField();
private JNumberField sizeNF = new JNumberField();
// end attributes
public CurveGen(String title) {
// Frame-Init
super(title);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
int frameWidth = 1022;
int frameHeight = 731;
setSize(frameWidth, frameHeight);
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int x = (d.width - getSize().width) / 2;
int y = (d.height - getSize().height) / 2;
setLocation(x, y);
setResizable(false);
Container cp = getContentPane();
cp.setLayout(null);
// start components
display.setBounds(16, 64, 601, 601);
cp.add(display);
startButton.setBounds(736, 464, 241, 129);
startButton.setText("START!");
startButton.setMargin(new Insets(2, 2, 2, 2));
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
startButton_ActionPerformed(evt);
}
});
startButton.setFont(new Font("Dialog", Font.BOLD, 36));
cp.add(startButton);
jLabel1.setBounds(760, 96, 75, 41);
jLabel1.setText("Iterations:");
cp.add(jLabel1);
outTextScrollPane.setBounds(728, 392, 257, 57);
cp.add(outTextScrollPane);
jLabel2.setBounds(768, 144, 67, 41);
jLabel2.setText("Size:");
cp.add(jLabel2);
xSlider.setBounds(0, 8, 633, 49);
xSlider.setMinorTickSpacing(25);
xSlider.setMajorTickSpacing(100);
xSlider.setPaintTicks(true);
xSlider.setPaintLabels(true);
xSlider.setToolTipText("Starting point y-coordinate");
xSlider.setMaximum(600);
xSlider.setValue(300);
cp.add(xSlider);
ySlider.setBounds(624, 56, 65, 625);
ySlider.setMinorTickSpacing(25);
ySlider.setMajorTickSpacing(100);
ySlider.setPaintTicks(true);
ySlider.setPaintLabels(true);
ySlider.setOrientation(SwingConstants.VERTICAL);
ySlider.setMaximum(600);
ySlider.setInverted(true);
ySlider.setValue(300);
ySlider.setToolTipText("Starting point x-coordinate");
cp.add(ySlider);
iterationsNF.setBounds(856, 96, 81, 41);
iterationsNF.setText("");
cp.add(iterationsNF);
sizeNF.setBounds(856, 144, 81, 41);
sizeNF.setText("");
cp.add(sizeNF);
// end components
setVisible(true);
} // end of public CurveGen
// start methods
public static void main(String[] args) {
new CurveGen("CurveGen");
} // end of main
public char[] input(int iter) {
char oldOut[] = new char[0];
for (int i=1;i<=iter;i++) {
char newOut[] = new char[((int)Math.pow(2, i))-1];
for (int n=0;n<oldOut.length;n++) {
newOut[n] = oldOut[n];
if (oldOut[n]=='r') {
newOut[newOut.length-n-1] = 'l';
}
if (oldOut[n]=='l') {
newOut[newOut.length-n-1] = 'r';
} // end of if
} // end of for
newOut[oldOut.length]='l';
oldOut = newOut;
} // end of for
return oldOut;
}
public void startButton_ActionPerformed(ActionEvent evt) {
int iterations = iterationsNF.getInt();
int size = sizeNF.getInt();
char com[] = input(iterations);
outText.setText(String.valueOf(com));
int dir = 0;
int newDir = 0;
int lastPos[] = {xSlider.getValue(),ySlider.getValue()-size};
int newPos[] = {0,0};
Graphics g = display.getGraphics();
g.clearRect(0,0,601,601);
g.drawLine(xSlider.getValue(),ySlider.getValue(),xSlider.getValue(),ySlider.getValue()-size);
for (int i=0;i<=com.length-1;i++) {
dir = newDir;
if (dir==0) {
if (com[i]=='l') {
newPos[0] = lastPos[0]-size;
newPos[1] = lastPos[1];
newDir = 3;
}
if (com[i]=='r') {
newPos[0] = lastPos[0]+size;
newPos[1] = lastPos[1];
newDir = 1;
}
}
if (dir==1) {
if (com[i]=='l') {
newPos[0] = lastPos[0];
newPos[1] = lastPos[1]-size;
newDir = 0;
}
if (com[i]=='r') {
newPos[0] = lastPos[0];
newPos[1] = lastPos[1]+size;
newDir = 2;
}
}
if (dir==2) {
if (com[i]=='l') {
newPos[0] = lastPos[0]+size;
newPos[1] = lastPos[1];
newDir = 1;
}
if (com[i]=='r') {
newPos[0] = lastPos[0]-size;
newPos[1] = lastPos[1];
newDir = 3;
}
}
if (dir==3) {
if (com[i]=='l') {
newPos[0] = lastPos[0];
newPos[1] = lastPos[1]+size;
newDir = 2;
}
if (com[i]=='r') {
newPos[0] = lastPos[0];
newPos[1] = lastPos[1]-size;
newDir = 0;
}
}
g.drawLine(lastPos[0],lastPos[1],newPos[0],newPos[1]);
lastPos=newPos;
} // end of for
} // end of startButton_ActionPerformed
// end methods
} // end of class CurveGen
Okay, so I've gone back over the code...
Mixing heavyweight (java.awt.Canvas) and lightweight (Swing) components is unadvisable as they can cause or sorts of painting issues
getGraphics is not how paint should be done. Instead, I'd start with a custom JPanel and override its paintComponent. See Painting in AWT and Swing and Performing Custom Painting for more details
Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify
I believe the problem is associated with this...
lastPos=newPos;
All you are doing is making lastPos point to the same place in memory as newPos, so when you assign values to newPos, lastPos will have the same values, hence the reason you're seeing dots.
What I would do first, is separate the responsible for the generation of the data from the display.
I'd start with some kind of model (note, you could create a model which took iterations instead and which generated the data itself, but I was focusing on solving the initial problem)
public class DragonModel {
private Point startPoint;
private int size;
private char[] values;
public DragonModel(Point startPoint, int size, char[] values) {
this.startPoint = startPoint;
this.size = size;
this.values = values;
}
public Point getStartPoint() {
return startPoint;
}
public int getSize() {
return size;
}
public char[] getValues() {
return values;
}
}
and then the display...
public class DragonPane extends JPanel {
private DragonModel model;
public void setModel(DragonModel model) {
this.model = model;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (model != null) {
Graphics2D g2d = (Graphics2D) g.create();
int size = model.getSize();
int dir = 0;
int newDir = 0;
Point lastPos = model.getStartPoint();
Point newPos = new Point(0, 0);
for (char value : model.values) {
if (dir == 0) {
if (value == 'l') {
newPos.x = lastPos.x - size;
newPos.y = lastPos.y;
newDir = 3;
}
if (value == 'r') {
newPos.x = lastPos.x + size;
newPos.y = lastPos.y;
newDir = 1;
}
}
if (dir == 1) {
if (value == 'l') {
newPos.x = lastPos.x;
newPos.y = lastPos.y - size;
newDir = 0;
}
if (value == 'r') {
newPos.x = lastPos.x;
newPos.y = lastPos.y + size;
newDir = 2;
}
}
if (dir == 2) {
if (value == 'l') {
newPos.x = lastPos.x + size;
newPos.y = lastPos.y;
newDir = 1;
}
if (value == 'r') {
newPos.x = lastPos.x - size;
newPos.y = lastPos.y;
newDir = 3;
}
}
if (dir == 3) {
if (value == 'l') {
newPos.x = lastPos.x;
newPos.y = lastPos.y + size;
newDir = 2;
}
if (value == 'r') {
newPos.x = lastPos.x;
newPos.y = lastPos.y - size;
newDir = 0;
}
}
g.drawLine(lastPos.x, lastPos.y, newPos.x, newPos.y);
dir = newDir;
lastPos = new Point(newPos);
}
}
}
}
The idea here is to try and decouple of the responsibility a little, the responsibility for the generation and displaying of the data sit firmly in two different areas.
Then in your actionPerformed method you could simply do...
public void startButton_ActionPerformed(ActionEvent evt) {
int iterations = Integer.parseInt(iterationsNF.getText());
int size = Integer.parseInt(sizeNF.getText());
char com[] = input(iterations);
outText.setText(String.valueOf(com));
DragonModel model = new DragonModel(new Point(xSlider.getValue(), ySlider.getValue()), size, com);
display.setModel(model);
} // end of startButton_ActionPerformed
which could result in something like...
The drawing code should be inside the paint(Graphics) method to synchronize with the rendering loop properly. In an event handler, update the data model of the component (calculate the lines and keep them in a data structure inside the component), then call the method repaint() to trigger the event rendering loop, which will call your paint method.
There are some other variations of this, but the general idea is that you change the data and then request rendering. The rendering engine may call your paint method in other cases as well, not only when you change the data, so ideally paint() has all the data it needs to render fast, meaning it should not do calculations or heavy operations other than rendering on the Graphics object.
This means that you have to subclass JComponent in a new class, and implement paint inside it. This class should have an internal data structure with the lines ready to render at any point in time. Then use your new class in the JFrame.
I'm trying to highlight the bullet background of the currently active line but if I just set the background color of the bullet it only highlights the number portion. I would like all the space occupied by the bullet to highlighted.
I would like all the space to the left of the 9 to be highlighted as well and probably a bit to the right too.
The code I'm using to get what I have so far is
#Override
public void lineGetStyle(LineStyleEvent event) {
// Set the line number
int activeLine = styledText.getLineAtOffset(styledText.getCaretOffset());
int currentLine = styledText.getLineAtOffset(event.lineOffset);
event.bulletIndex = currentLine;
int width = 36;
if (styledText.getLineCount() > 999)
width = (int) ((Math.floor(Math.log10(styledText.getLineCount()))+1) * 12);
// Set the style, 12 pixles wide for each digit
StyleRange style = new StyleRange();
style.metrics = new GlyphMetrics(0, 0, width);
if (activeLine == currentLine) {
style.background = highlightedLine;
}
style.foreground = mainBackground;
// Create and set the bullet
event.bullet = new Bullet(ST.BULLET_NUMBER, style);
event.styles = matchKeywords(event);
}
Is this possible?
You can do this with custom painting. First, change the bullet type to ST.BULLET_CUSTOM. Then add a PaintObjectListener:
styledText.addPaintObjectListener(new PaintObjectListener() {
public void paintObject(PaintObjectEvent event) {
drawBullet(event.bullet, event.gc, event.x, event.y, event.bulletIndex, event.ascent, event.descent);
}
});
There is a standard implementation of drawBullet in StyledTextRenderer. I've changed this to accept custom bullets as numbered bullets, and to draw an extra rectangle in the background:
void drawBullet(Bullet bullet, GC gc, int paintX, int paintY, int index, int lineAscent, int lineDescent) {
StyleRange style = bullet.style;
GlyphMetrics metrics = style.metrics;
Color color = style.foreground;
if (color != null) gc.setForeground(color);
Font font = style.font;
if (font != null) gc.setFont(font);
String string = "";
int type = bullet.type & (ST.BULLET_DOT|ST.BULLET_CUSTOM|ST.BULLET_NUMBER|ST.BULLET_LETTER_LOWER|ST.BULLET_LETTER_UPPER);
switch (type) {
case ST.BULLET_DOT: string = "\u2022"; break;
case ST.BULLET_CUSTOM: string = String.valueOf(index + 1); break;
case ST.BULLET_NUMBER: string = String.valueOf(index + 1); break;
case ST.BULLET_LETTER_LOWER: string = String.valueOf((char) (index % 26 + 97)); break;
case ST.BULLET_LETTER_UPPER: string = String.valueOf((char) (index % 26 + 65)); break;
}
if ((bullet.type & ST.BULLET_TEXT) != 0) string += bullet.text;
gc.setBackground(style.background);
gc.fillRectangle(paintX, paintY, metrics.width, styledText.getLineHeight());
Display display = styledText.getDisplay();
TextLayout layout = new TextLayout(display);
layout.setText(string);
layout.setAscent(lineAscent);
layout.setDescent(lineDescent);
style = (StyleRange)style.clone();
style.metrics = null;
if (style.font == null) style.font = styledText.getFont();
layout.setStyle(style, 0, string.length());
int x = paintX + Math.max(0, metrics.width - layout.getBounds().width - 8);
layout.draw(gc, x, paintY);
layout.dispose();
}
I want to make the text show on screen when mousePressed() is false every 3 seconds, I set a boolean "whether" in mousePressed() function and when it quals false I get strings from a text file. But it seems like my logic is wrong. DO anyone know the problem?
Zoog[]zoog = new Zoog[1];
float count=0;
int xpos =0;
int ypos =0;
String message="haha";
String newone="";
String t="\n";
int ntextsize = 20;
int nopacity =200;
int thistime = 0;
int thiscount = 0;
String[]lines;
//Zoog zoog;
boolean whether;
void setup() {
size(400, 400);
xpos = int(random(width/2-200, width/2+40));
ypos = int(random(height/2, height/2-40));
zoog[0] = new Zoog(xpos,ypos,message,nopacity);
}
void draw(){
background(255,255,255);
for(int i=0; i<zoog.length; i++){
// if(millis()-thistime>4000){
// zoog[i].disappear();
// }
zoog[i].jiggle();
zoog[i].display();
}
whether = false;
lines = loadStrings("data.txt");
if(whether!=true){
createnew(int(random(width)), int(random(height)), lines[int(random(lines.length))],150);
}
}
void mousePressed(){
whether = true;
count = count + 1;
// int thiscount = 0;
if(count%3 ==0){
xpos=int(random(30, width-30));
ypos=int(random(10, height-10));
}
else{
ypos = ypos+50;
}
nopacity = int(random(100,255));
createnew(xpos,ypos,message,nopacity);
}
void createnew(int xxpos, int yyos, String mmessage, int nnopacity){
Zoog b = new Zoog(xpos,ypos,message,nopacity);
zoog =(Zoog[]) append(zoog,b);
}
The function corresponding to my question is:
lines = loadStrings("data.txt");
if(whether!=true){
createnew(int(random(width)), int(random(height)), lines[int(random(lines.length))],150);
}
}
and
void createnew(int xxpos, int yyos, String mmessage, int nnopacity){
Zoog b = new Zoog(xpos,ypos,message,nopacity);
zoog =(Zoog[]) append(zoog,b);
}
As you call whether = true just before testing for it in if(whether!=true) it will always be true and test is not going to evaluate to true, so code inside block will not run. mousePressed() is called once when mouse is pressed, run this code so understand how it works:
boolean b;
void setup(){frameRate(10);}
void draw(){ b = false; println("in draw " + b);}
void mousePressed(){b = true;println("in mousePressed " + b);}
see? But there is a field (a "default" var) in processing called mousePressed (without parenthesis) that would behave just as you need, just test for it in draw, running the same code added the mousePressed field in draw will show you what i mean:
boolean b;
void setup() {
frameRate(10);
}
void draw() {
b = false;
println("in draw " + b);
if (mousePressed)println("i'm pressed");
}
void mousePressed() {
b = true;
println("im mousePressed " + b);
}
You could also create your own boolean and set it to true in mousePressed() and to false in mouseReleased(). With the same effect.
[EDIT] Just occurred to me, yet another way... if you change the call in draw as follows it should work as well:
lines = loadStrings("data.txt");
if(whether!=true){
createnew(int(random(width)), int(random(height)), lines[int(random(lines.length))],150);
whether = false;// move this here
}
I was wondering if there is a straightforward way to display line numbers with StyledText text field - even if lines are wrapped. I'm using it in my application and if content gets to big, some line numbers would be nice.
Thank you.
The key is org.eclipse.swt.custom.Bullet. It's basically a symbol (or in our case a number) you can add to the beginning of a line.
//text is your StyledText
text.addLineStyleListener(new LineStyleListener()
{
public void lineGetStyle(LineStyleEvent e)
{
//Set the line number
e.bulletIndex = text.getLineAtOffset(e.lineOffset);
//Set the style, 12 pixles wide for each digit
StyleRange style = new StyleRange();
style.metrics = new GlyphMetrics(0, 0, Integer.toString(text.getLineCount()+1).length()*12);
//Create and set the bullet
e.bullet = new Bullet(ST.BULLET_NUMBER,style);
}
});
This is my working implementation.
styledText.addLineStyleListener(new LineStyleListener() {
#Override
public void lineGetStyle(LineStyleEvent event) {
// Using ST.BULLET_NUMBER sometimes results in weird alignment.
//event.bulletIndex = styledText.getLineAtOffset(event.lineOffset);
StyleRange styleRange = new StyleRange();
styleRange.foreground = Display.getCurrent().getSystemColor(SWT.COLOR_GRAY);
int maxLine = styledText.getLineCount();
int bulletLength = Integer.toString(maxLine).length();
// Width of number character is half the height in monospaced font, add 1 character width for right padding.
int bulletWidth = (bulletLength + 1) * styledText.getLineHeight() / 2;
styleRange.metrics = new GlyphMetrics(0, 0, bulletWidth);
event.bullet = new Bullet(ST.BULLET_TEXT, styleRange);
// getLineAtOffset() returns a zero-based line index.
int bulletLine = styledText.getLineAtOffset(event.lineOffset) + 1;
event.bullet.text = String.format("%" + bulletLength + "s", bulletLine);
}
});
styledText.addModifyListener(new ModifyListener() {
#Override
public void modifyText(ModifyEvent e) {
// For line number redrawing.
styledText.redraw();
}
});
Note that the possible overhead of syntax highlighting recalculation when calling redraw() is likely to be acceptable, because lineGetStyle() are only called with lines currently on screen.
I believe that using a LineStyleListener should work. Something along the lines of:
styledText.addLineStyleListener(
new LineStyleListener() {
#Override
public void lineGetStyle(LineStyleEvent event) {
String line = event.lineText;
int lineNumber = event.lineOffset;
// Do stuff to add line numbers
}
}
);
This is a way to use bullets that updates the numbers when the content changes:
text.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent event) {
int maxLine = text.getLineCount();
int lineCountWidth = Math.max(String.valueOf(maxLine).length(), 3);
StyleRange style = new StyleRange();
style.metrics = new GlyphMetrics(0, 0, lineCountWidth * 8 + 5);
Bullet bullet = new Bullet(ST.BULLET_NUMBER, style);
text.setLineBullet(0, text.getLineCount(), null);
text.setLineBullet(0, text.getLineCount(), bullet);
}
});
As a side-note for colouring the line numbers:
Device device = Display.getCurrent();
style.background = new Color(device, LINE_NUMBER_BG);
style.foreground = new Color(device, LINE_NUMBER_FG);
where LINE_NUMBER_BG and LINE_NUMBER_FG might be a RGB object such as:
final RGB LINE_NUMBER_BG = new RBG(160, 80, 0); // brown
final RGB LINE_NUMBER_FG = new RGB(255, 255, 255); // white