CaRMtl/rene/viewer/TextDisplay.java

576 lines
12 KiB
Java

/*
Copyright 2006 Rene Grothmann, modified by Eric Hakenholz
This file is part of C.a.R. software.
C.a.R. is a free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 3 of the License.
C.a.R. is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package rene.viewer;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.SystemColor;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.io.PrintWriter;
import rene.gui.Global;
import rene.util.list.ListClass;
import rene.util.list.ListElement;
class ClipboardCopy extends Thread {
String S;
ClipboardOwner C;
Canvas Cv;
public ClipboardCopy(final ClipboardOwner c, final Canvas cv, final String s) {
S = s;
C = c;
Cv = cv;
start();
}
@Override
public void run() {
final Clipboard clip = Cv.getToolkit().getSystemClipboard();
final StringSelection cont = new StringSelection(S);
clip.setContents(cont, C);
}
}
public class TextDisplay extends Canvas implements ClipboardOwner,
ComponentListener {
/**
*
*/
private static final long serialVersionUID = 1L;
ListClass L;
Font F = null;
FontMetrics FM;
Viewer V;
int Leading, Height, Ascent, Descent;
int LineCount, TopLineCount;
int PageSize;
ListElement TopLine;
Image I;
Graphics IG;
int W, H;
public int Tabsize = 4;
public int Offset;
boolean LineFinished = true;
int Widths[], HW[];
long LastScrollTime;
Color Background;
int TabWidth = 0;
public TextDisplay(final Viewer v) {
L = new ListClass();
F = null;
V = v;
LineCount = 0;
TopLineCount = 0;
TopLine = null;
I = null;
W = H = 0;
PageSize = 10;
HW = new int[1024];
addKeyListener(v);
addComponentListener(this);
}
void init(final Font f) {
F = f;
FM = getFontMetrics(F);
Leading = FM.getLeading()
+ Global.getParameter("fixedfont.spacing", -1);
Height = FM.getHeight();
Ascent = FM.getAscent();
Descent = FM.getDescent();
Widths = FM.getWidths();
}
@Override
public Color getBackground() {
return SystemColor.window;
}
int[] getwidth(final char a[]) {
try {
for (int i = 0; i < a.length; i++) {
if (a[i] < 256)
HW[i] = Widths[a[i]];
else
HW[i] = FM.charWidth(a[i]);
}
} catch (final Exception e) {
return HW;
}
return HW;
}
public synchronized void appendLine0(final String S) {
appendLine0(S, Color.black);
}
public synchronized void appendLine0(final String S, final Color c) {
Line l;
L.append(new ListElement(l = new Line(S, this, c)));
LineCount++;
if (LineCount == 1)
TopLine = L.first();
LineFinished = true;
if (TabWidth > 0)
l.expandTabs(TabWidth);
}
public synchronized void appendLine(final String s) {
appendLine0(s);
V.setVerticalScrollbar();
}
public void append(final String S, final Color c) {
append(S, c, true);
}
public void append(String S, final Color c, final boolean suddenupdate) {
while (true) {
final int p = S.indexOf('\n');
if (p < 0) {
appendlast(S, c);
LineFinished = false;
break;
}
appendlast(S.substring(0, p), c);
LineFinished = true;
S = S.substring(p + 1);
if (S.equals("")) {
break;
}
}
if (suddenupdate)
doUpdate(true);
repaint();
}
public void doUpdate(final boolean showlast) {
if (showlast) {
final long m = System.currentTimeMillis();
if (m - LastScrollTime > 10000)
showlast();
}
repaint();
V.setVerticalScrollbar();
}
public void setText(final String s) {
TopLine = null;
TopLineCount = 0;
LineCount = 0;
L = new ListClass();
if (!s.equals(""))
append(s, Color.black);
repaint();
}
public synchronized void appendlast(final String s, final Color c) {
if (LineFinished || L.last() == null) {
Line l;
L.append(new ListElement(l = new Line(s, this, c)));
LineCount++;
if (LineCount == 1)
TopLine = L.first();
if (TabWidth > 0)
l.expandTabs(TabWidth);
} else {
((Line) L.last().content()).append(s);
}
}
public void showlast() {
ListElement e = L.last();
if (e == null)
return;
TopLineCount = LineCount;
for (int i = 0; i < PageSize - 1; i++) {
if (e.previous() == null)
break;
e = e.previous();
TopLineCount--;
}
TopLine = e;
repaint();
}
public void makeimage() {
final Dimension D = getSize();
if (I == null || D.width != W || D.height != H) {
try {
I = createImage(W = D.width, H = D.height);
IG = I.getGraphics();
} catch (final Exception e) {
}
}
IG.setColor(Color.black);
IG.clearRect(0, 0, W, H);
IG.setFont(F);
try {
PageSize = H / (Height + Leading);
} catch (final Exception e) {
}
}
@Override
public synchronized void paint(final Graphics g) {
if (F == null)
init(getFont());
makeimage();
ListElement e = TopLine;
antialias(true);
int h = Leading + Ascent;
if (Background == null)
Background = getBackground();
IG.setColor(Background);
IG.fillRect(0, 0, W, H);
int lines = 0;
while (lines < PageSize && e != null) {
final Line l = (Line) e.content();
l.draw(IG, 2, h);
h += Leading + Height;
e = e.next();
lines++;
}
g.drawImage(I, 0, 0, this);
}
/**
* Set Anti-Aliasing on or off, if in Java 1.2 or better and the Parameter
* "font.smooth" is switched on.
*
* @param flag
*/
public void antialias(final boolean flag) {
if (Global.getParameter("font.smooth", true)) {
IG = (Graphics2D) IG;
((Graphics2D) IG).setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
flag ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON
: RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
}
}
public void showLine(final ListElement line) {
ListElement e = TopLine;
int h = Leading + Ascent;
if (Background == null)
Background = getBackground();
int lines = 0;
while (lines < PageSize && e != null) {
if (e == line)
return;
h += Leading + Height;
e = e.next();
lines++;
}
if (e == line && TopLine.next() != null)
TopLine = TopLine.next();
else
TopLine = line;
}
public ListElement getline(final int y) {
if (TopLine == null)
return null;
ListElement e = TopLine;
int h = Leading + Height;
if (h == 0)
return null;
h = y / h;
for (int i = 0; i < h; i++) {
if (e.next() == null)
return e;
e = e.next();
}
return e;
}
@Override
public void update(final Graphics g) {
paint(g);
}
int computeVertical() {
if (LineCount > 0)
return TopLineCount * 1000 / LineCount;
else
return 0;
}
public int setVertical(final int v) {
if (TopLine == null)
return 0;
final int NewTop = LineCount * v / 1000;
if (NewTop > TopLineCount) {
for (int i = TopLineCount; i < NewTop; i++) {
if (TopLine.next() == null)
break;
TopLine = TopLine.next();
TopLineCount++;
}
repaint();
} else if (NewTop < TopLineCount) {
for (int i = TopLineCount; i > NewTop; i--) {
if (TopLine.previous() == null)
break;
TopLine = TopLine.previous();
TopLineCount--;
}
repaint();
}
LastScrollTime = System.currentTimeMillis();
return v;
}
public void verticalUp() {
if (TopLine == null)
return;
if (TopLine.next() == null)
return;
TopLine = TopLine.next();
TopLineCount++;
repaint();
LastScrollTime = System.currentTimeMillis();
}
public void verticalDown() {
if (TopLine == null)
return;
if (TopLine.previous() == null)
return;
TopLine = TopLine.previous();
TopLineCount--;
repaint();
LastScrollTime = System.currentTimeMillis();
}
public void verticalPageUp() {
if (TopLine == null)
return;
for (int i = 0; i < PageSize - 1; i++) {
if (TopLine.next() == null)
break;
TopLine = TopLine.next();
TopLineCount++;
}
repaint();
LastScrollTime = System.currentTimeMillis();
}
public void verticalPageDown() {
if (TopLine == null)
return;
for (int i = 0; i < PageSize - 1; i++) {
if (TopLine.previous() == null)
break;
TopLine = TopLine.previous();
TopLineCount--;
}
repaint();
LastScrollTime = System.currentTimeMillis();
}
int computeVerticalSize() {
if (LineCount == 0)
return 100;
int h = PageSize * 2000 / LineCount;
if (h < 10)
h = 10;
return h;
}
public int setHorizontal(final int v) {
Offset = v / 5;
repaint();
return v;
}
public void save(final PrintWriter fo) {
ListElement e = L.first();
while (e != null) {
fo.println(new String(((Line) e.content()).a));
e = e.next();
}
}
public TextPosition getposition(final int x, final int y) {
if (L.first() == null)
return null;
if (y < 0)
return new TextPosition(TopLine, TopLineCount, 0);
if (TopLine == null)
return null;
ListElement e = TopLine;
int h = Leading + Height;
if (h == 0)
return null;
h = y / h;
int i;
for (i = 0; i < h; i++) {
if (e.next() == null || i == PageSize - 1)
return new TextPosition(e, TopLineCount + i, ((Line) e
.content()).length());
e = e.next();
}
return new TextPosition(e, TopLineCount + i, ((Line) e.content())
.getpos(x, 2));
}
public void unmark() {
ListElement e = L.first();
while (e != null) {
((Line) e.content()).block(0, Line.NONE);
e = e.next();
}
repaint();
}
public void unmark(final TextPosition Start, final TextPosition End) {
if (Start == null || End == null)
return;
TextPosition P1, P2;
if (Start.before(End)) {
P1 = Start;
P2 = End;
} else if (End.before(Start)) {
P1 = End;
P2 = Start;
} else
return;
ListElement e = P1.L;
while (e != null && e != P2.L) {
((Line) e.content()).block(0, Line.NONE);
e = e.next();
}
if (e != null)
((Line) e.content()).block(0, Line.NONE);
repaint();
}
public void mark(final TextPosition Start, final TextPosition End) {
if (Start == null || End == null)
return;
TextPosition P1, P2;
if (Start.before(End)) {
P1 = Start;
P2 = End;
} else if (End.before(Start)) {
P1 = End;
P2 = Start;
} else
return;
ListElement e = P1.L;
((Line) e.content()).block(P1.LPos, Line.START);
if (e != P2.L)
e = e.next();
while (e != null && e != P2.L) {
((Line) e.content()).block(0, Line.FULL);
e = e.next();
}
if (e != null)
((Line) e.content()).block(P2.LPos, Line.END);
repaint();
requestFocus();
}
void copy(final TextPosition Start, final TextPosition End) {
if (Start == null || End == null)
return;
TextPosition P1, P2;
if (Start.before(End)) {
P1 = Start;
P2 = End;
} else if (End.before(Start)) {
P1 = End;
P2 = Start;
} else
return;
String s = "";
ListElement e = P1.L;
while (e != null && e != P2.L) {
s = s + ((Line) e.content()).getblock() + "\n";
e = e.next();
}
if (e != null)
s = s + ((Line) e.content()).getblock();
new ClipboardCopy(this, this, s);
}
public void showFirst() {
TopLine = L.first();
}
public void lostOwnership(final Clipboard clip, final Transferable cont) {
}
TextPosition lastpos() {
final ListElement e = L.last();
if (e == null)
return null;
final Line l = (Line) e.content();
return new TextPosition(e, LineCount, l.length());
}
public void setTabWidth(final int t) {
TabWidth = t;
}
@Override
public boolean hasFocus() {
return V.hasFocus();
}
@Override
public void setBackground(final Color c) {
Background = c;
super.setBackground(c);
}
public void componentHidden(final ComponentEvent e) {
}
public void componentMoved(final ComponentEvent e) {
}
public void componentResized(final ComponentEvent e) {
V.resized();
}
public void componentShown(final ComponentEvent e) {
}
}