Hallo,
ich habe einen kleinen Editor gebaut, JEditorPane habe ich Contenttype text/html gesetzt und internes HTML soll quasi gerendertwerden, wie in einem Browser (mit Formatierung und co) dargestellt werden. HTMLEditorKit hat nun eine schöne Funktion eingebaut, dass nämlich Line Wrap aktiviert ist und eingaben nicht auf der X Achse ins nirvana verschwinden. Nun habe ich ein anderes Problem gelöst, dass man mehrere Leerzeichen nebeneinander eingeben kann, habe ganz simple alle Leerzeichen eingaben durch ein \u00A0 (Non-breaking Space) (160) ersetzt.
Jetzt das Problem, seitdem geht der Line wrap nicht mehr und wörter werden nicht mehr umgebrochen, sondern als ein langes wort gesehen.
Ich habe sehr viel probiert, habe ParagraphView und InlineView maltretiert und Berechnungen, die sich darauf beziehen könnten, in denen zB auch Character.isWhiteSpace() vor kommt überschrieben und versucht das Line wrap für dieses NBS zeichen zu aktivieren. leider ohne Erfolg.
Falls da jmd Erfahrung und Kenntnis hat wäre ich über Tipps oder auch Lösungen sehr dankbar ...
Falls weitere Infos nötig sind, schreien.
Aber soviel, ich habe einen eigenen editorKit gebaut, indem ich bestimmte Views austausche:
UPDATE
selbst wenn man <Wort> Space NBS Space <Wort> schreibt, werden beide Worte als eins gesehen. Ich kann leider nirgendwo im Code erkennen wo hier dieser Mechanismus umgesetzt wird
zB
MyEditorKit
Test Programm:
MyLabelView
MyParagraphView
ich habe einen kleinen Editor gebaut, JEditorPane habe ich Contenttype text/html gesetzt und internes HTML soll quasi gerendertwerden, wie in einem Browser (mit Formatierung und co) dargestellt werden. HTMLEditorKit hat nun eine schöne Funktion eingebaut, dass nämlich Line Wrap aktiviert ist und eingaben nicht auf der X Achse ins nirvana verschwinden. Nun habe ich ein anderes Problem gelöst, dass man mehrere Leerzeichen nebeneinander eingeben kann, habe ganz simple alle Leerzeichen eingaben durch ein \u00A0 (Non-breaking Space) (160) ersetzt.
Jetzt das Problem, seitdem geht der Line wrap nicht mehr und wörter werden nicht mehr umgebrochen, sondern als ein langes wort gesehen.
Ich habe sehr viel probiert, habe ParagraphView und InlineView maltretiert und Berechnungen, die sich darauf beziehen könnten, in denen zB auch Character.isWhiteSpace() vor kommt überschrieben und versucht das Line wrap für dieses NBS zeichen zu aktivieren. leider ohne Erfolg.
Falls da jmd Erfahrung und Kenntnis hat wäre ich über Tipps oder auch Lösungen sehr dankbar ...
Falls weitere Infos nötig sind, schreien.
Aber soviel, ich habe einen eigenen editorKit gebaut, indem ich bestimmte Views austausche:
UPDATE
selbst wenn man <Wort> Space NBS Space <Wort> schreibt, werden beide Worte als eins gesehen. Ich kann leider nirgendwo im Code erkennen wo hier dieser Mechanismus umgesetzt wird

zB
MyEditorKit
Java:
package de;
import javax.swing.text.AbstractDocument;
import javax.swing.text.Element;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
import javax.swing.text.html.HTMLEditorKit;
@SuppressWarnings("serial")
public class MyEditorKit extends HTMLEditorKit
{
public MyEditorKit()
{
// TODO Auto-generated constructor stub
}
public ViewFactory getViewFactory()
{
return new HTMLFactory()
{
@Override
public View create(Element elem)
{
String kind = elem.getName();
if (kind != null)
{
if (kind.equals(AbstractDocument.ContentElementName))
{
return new MyLabelView(elem);
}
else if (kind.equals("p"))
{
return new MyParagraphView(elem);
}
// else if (kind.equals(AbstractDocument.SectionElementName))
// {
// return new BoxView(elem, View.Y_AXIS);
// }
// else if (kind.equals(StyleConstants.ComponentElementName))
// {
// return new ComponentView(elem);
// }
// else if (kind.equals(StyleConstants.IconElementName))
// {
// return new IconView(elem);
// }
}
// default to text display
return super.create(elem);
}
};
}
// public MutableAttributeSet getInputAttributes() {
// MutableAttributeSet mAttrs=super.getInputAttributes();
// mAttrs.removeAttribute(WrapApp.LINE_BREAK_ATTRIBUTE_NAME);
// return mAttrs;
// }
}
Test Programm:
Java:
package de;
import java.awt.BorderLayout;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
public class TestMain
{
/**
* @param args
*/
public static void main(String[] args)
{
JFrame f = new JFrame();
f.setSize(500, 400);
f.setLayout(new BorderLayout());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JEditorPane e = new JEditorPane();
e.setContentType("text/html");
e.setEditorKit(new MyEditorKit());
String lala = "<p>So konkret waren die Spekulationen über einen Nachfolger für die Wii nur selten: Angeblich will Nintendo die Konsole schon demnächst vorstellen, sie soll leistungsstärker sein als Xbox 360 und Playstation 3 und auch den Hardcorespielermarkt zurückgewinnen. Gerüchte über einen Nachfolger für die Wii gibt es schon seit langem – insbesondere, weil die Konsole von Nintendo trotz der weiten Verbreitung von HD-Fernsehgeräten keine hochauflösende Grafik beherrscht, sehen viele Marktbeobachter dringenden Nachbesserungsbedarf. Jetzt gibt es in US-Medien - allen voran Game Informer - neue Spekulationen, denen zufolge die kommende Konsole spätestens Anfang Juni 2011 auf der Spielemesse E3 in Los Angeles vorgestellt wird und Ende 2012 erscheint. Angeblich ist das Gerät leistungsfähiger als Xbox 360 und Playstation 3, es trägt vermutlich einen neuen Namen und soll den Hardcorespielermarkt wieder für Nintendo zurückerobern. Eine Webseite will gar wissen, dass ihre Controller über eingebaute HD-Displays verfügen. </p>"
.replace(' ', '\u00A0');
String lala2 = "<p>So konkret waren die Spekulationen über einen Nachfolger für die Wii nur selten: Angeblich will Nintendo die Konsole schon demnächst vorstellen, sie soll leistungsstärker sein als Xbox 360 und Playstation 3 und auch den Hardcorespielermarkt zurückgewinnen. Gerüchte über einen Nachfolger für die Wii gibt es schon seit langem – insbesondere, weil die Konsole von Nintendo trotz der weiten Verbreitung von HD-Fernsehgeräten keine hochauflösende Grafik beherrscht, sehen viele Marktbeobachter dringenden Nachbesserungsbedarf. Jetzt gibt es in US-Medien - allen voran Game Informer - neue Spekulationen, denen zufolge die kommende Konsole spätestens Anfang Juni 2011 auf der Spielemesse E3 in Los Angeles vorgestellt wird und Ende 2012 erscheint. Angeblich ist das Gerät leistungsfähiger als Xbox 360 und Playstation 3, es trägt vermutlich einen neuen Namen und soll den Hardcorespielermarkt wieder für Nintendo zurückerobern. Eine Webseite will gar wissen, dass ihre Controller über eingebaute HD-Displays verfügen. </p>";
e.setText("<html><head></head><body>" + lala2 + lala + "</body></html>");
JSplitPane split = new JSplitPane();
JTextArea tt = new JTextArea();
tt.setText(e.getText());
split.setOrientation(JSplitPane.VERTICAL_SPLIT);
split.setTopComponent(new JScrollPane(e));
split.setBottomComponent(new JScrollPane(tt));
f.add(split, BorderLayout.CENTER);
f.setVisible(true);
}
}
MyLabelView
Java:
package de;
import java.awt.Container;
import java.text.BreakIterator;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.Segment;
import javax.swing.text.View;
import javax.swing.text.html.InlineView;
public class MyLabelView extends InlineView
{
public MyLabelView(Element elem)
{
super(elem);
}
public int getBreakWeight(int axis, float pos, float len)
{
if (axis == View.X_AXIS)
{
checkPainter();
int p0 = getStartOffset();
int p1 = getGlyphPainter().getBoundedPosition(this, p0, pos, len);
if (p1 == p0)
{
// can't even fit a single character
return View.BadBreakWeight;
}
if (getBreakSpot(p0, p1) != -1)
{
return View.ExcellentBreakWeight;
}
// Nothing good to break on.
return View.GoodBreakWeight;
}
return super.getBreakWeight(axis, pos, len);
}
/**
* Returns a location to break at in the passed in region, or -1 if there
* isn't a good location to break at in the specified region.
*/
private int getBreakSpot(int p0, int p1)
{
Document doc = getDocument();
// if (doc != null && Boolean.TRUE.equals(doc.getProperty(
// AbstractDocument.MultiByteProperty))) {
// return getBreakSpotUseBreakIterator(p0, p1);
// }
return getBreakSpotUseWhitespace(p0, p1);
}
/**
* Returns the appropriate place to break based on the last whitespace
* character encountered.
*/
private int getBreakSpotUseWhitespace(int p0, int p1)
{
Segment s = getText(p0, p1);
for (char ch = s.last(); ch != Segment.DONE; ch = s.previous())
{
if (MyParagraphView.isWhitespace(ch))
{
// found whitespace
// SegmentCache.releaseSharedSegment(s);
return s.getIndex() - s.getBeginIndex() + 1 + p0;
}
}
// SegmentCache.releaseSharedSegment(s);
return -1;
}
/**
* Returns the appropriate place to break based on BreakIterator.
*/
private int getBreakSpotUseBreakIterator(int p0, int p1)
{
// Certain regions require context for BreakIterator, start from
// our parents start offset.
Element parent = getElement().getParentElement();
int parent0;
int parent1;
Container c = getContainer();
BreakIterator breaker;
if (parent == null)
{
parent0 = p0;
parent1 = p1;
}
else
{
parent0 = parent.getStartOffset();
parent1 = parent.getEndOffset();
}
if (c != null)
{
breaker = BreakIterator.getLineInstance(c.getLocale());
}
else
{
breaker = BreakIterator.getLineInstance();
}
Segment s = getText(parent0, parent1);
int breakPoint;
// Needed to initialize the Segment.
s.first();
breaker.setText(s);
if (p1 == parent1)
{
// This will most likely return the end, the assumption is
// that if parent1 == p1, then we are the last portion of
// a paragraph
breakPoint = breaker.last();
}
else if (p1 + 1 == parent1)
{
// assert(s.count > 1)
breakPoint = breaker.following(s.offset + s.count - 2);
if (breakPoint >= s.count + s.offset)
{
breakPoint = breaker.preceding(s.offset + s.count - 1);
}
}
else
{
breakPoint = breaker.preceding(p1 - parent0 + s.offset + 1);
}
int retValue = -1;
if (breakPoint != BreakIterator.DONE)
{
breakPoint = breakPoint - s.offset + parent0;
if (breakPoint > p0)
{
if (p0 == parent0 && breakPoint == p0)
{
retValue = -1;
}
else if (breakPoint <= p1)
{
retValue = breakPoint;
}
}
}
// SegmentCache.releaseSharedSegment(s);
return retValue;
}
}
MyParagraphView
Java:
package de;
import java.awt.Container;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Toolkit;
import java.text.BreakIterator;
import javax.swing.SizeRequirements;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.Segment;
import javax.swing.text.StyledDocument;
import javax.swing.text.View;
import javax.swing.text.html.InlineView;
import javax.swing.text.html.ParagraphView;
public class MyParagraphView extends ParagraphView
{
private FontMetrics fontMetrics;
public MyParagraphView(Element elem)
{
super(elem);
}
@Override
protected SizeRequirements calculateMinorAxisRequirements(int axis,
SizeRequirements r)
{
r = super.calculateMinorAxisRequirements(axis, r);
// if (!BlockView.spanSetFromAttributes(axis, r, cssWidth, cssHeight)) {
// PENDING(prinz) Need to make this better so it doesn't require
// InlineView and works with font changes within the word.
// find the longest minimum span.
float min = 0;
int n = getLayoutViewCount();
for (int i = 0; i < n; i++)
{
View v = getLayoutView(i);
if (v instanceof InlineView)
{
Container c = ((InlineView) v).getContainer();
AttributeSet attr = getAttributes();
if (attr != null)
{
Document d = getDocument();
if (d instanceof StyledDocument)
{
StyledDocument doc = (StyledDocument) d;
Font font = doc.getFont(attr);
fontMetrics = (c != null) ? c.getFontMetrics(font) : Toolkit
.getDefaultToolkit().getFontMetrics(font);
}
}
float wordSpan = calculateLongestWordSpan();
min = Math.max(wordSpan, min);
}
else
{
min = Math.max(v.getMinimumSpan(axis), min);
}
}
r.minimum = Math.max(r.minimum, (int) min);
r.preferred = Math.max(r.minimum, r.preferred);
r.maximum = Math.max(r.preferred, r.maximum);
// }
// else {
// // Offset by the margins so that pref/min/max return the
// // right value.
// int margin = (axis == X_AXIS) ? getLeftInset() + getRightInset() :
// getTopInset() + getBottomInset();
// r.minimum -= margin;
// r.preferred -= margin;
// r.maximum -= margin;
// }
return r;
}
float calculateLongestWordSpan()
{
float rv = 0f;
Document doc = getDocument();
// AbstractDocument.MultiByteProperty
final Object MultiByteProperty = "multiByte";
// if (doc != null &&
// Boolean.TRUE.equals(doc.getProperty(MultiByteProperty)))
// {
// rv = calculateLongestWordSpanUseBreakIterator();
// }
// else
// {
rv = calculateLongestWordSpanUseWhitespace();
// }
return rv;
}
float calculateLongestWordSpanUseBreakIterator()
{
float span = 0;
Document doc = getDocument();
int p0 = getStartOffset();
int p1 = getEndOffset();
if (p1 > p0)
{
try
{
FontMetrics metrics = fontMetrics;
Segment segment = new Segment();
doc.getText(p0, p1 - p0, segment);
Container c = getContainer();
BreakIterator line;
if (c != null)
{
line = BreakIterator.getLineInstance(c.getLocale());
}
else
{
line = BreakIterator.getLineInstance();
}
line.setText(segment);
int start = line.first();
for (int end = line.next(); end != BreakIterator.DONE; start = end, end = line
.next())
{
if (end > start)
{
span = Math.max(span,
metrics.charsWidth(segment.array, start, end - start));
}
}
}
catch (BadLocationException ble)
{
// If the text can't be retrieved, it can't influence the size.
}
}
return span;
}
float calculateLongestWordSpanUseWhitespace()
{
float span = 0;
Document doc = getDocument();
int p0 = getStartOffset();
int p1 = getEndOffset();
if (p1 > p0)
{
try
{
Segment segment = new Segment();
doc.getText(p0, p1 - p0, segment);
final int CONTENT = 0;
final int SPACES = 1;
int state = CONTENT;
int start = segment.offset;
int end = start;
FontMetrics metrics = fontMetrics;
final int lastIndex = segment.offset + segment.count - 1;
for (int i = segment.offset; i <= lastIndex; i++)
{
boolean updateSpan = false;
if (isWhitespace(segment.array[i]))
{
if (state == CONTENT)
{
// we got a word
updateSpan = true;
state = SPACES;
}
}
else
{
if (state == SPACES)
{
// first non space
start = i;
end = start;
state = CONTENT;
}
else
{
end = i;
}
// handle last word
if (i == lastIndex)
{
updateSpan = true;
}
}
if (updateSpan)
{
if (end > start)
{
span = Math.max(span,
metrics.charsWidth(segment.array, start, end - start + 1));
}
}
}
}
catch (BadLocationException ble)
{
// If the text can't be retrieved, it can't influence the size.
}
}
return span;
}
public static boolean isWhitespace(int codePoint)
{
boolean bWhiteSpace = false;
bWhiteSpace = Character.isWhitespace(codePoint);
// // int plane = getPlane(codePoint);
//
switch (codePoint)
{
case ('\u00A0'):
bWhiteSpace = true;
break;
}
System.out.print((char) codePoint + " (" + codePoint + "/" + bWhiteSpace
+ ")");
return bWhiteSpace;
}
// private static int getPlane(int ch)
// {
// return (ch >>> 16);
// }
@Override
public int getBreakWeight(int axis, float len)
{
return super.getBreakWeight(axis, len);
}
@Override
public int getBreakWeight(int axis, float pos, float len)
{
return super.getBreakWeight(axis, pos, len);
}
}
Zuletzt bearbeitet: