JEditorPane, HTML und LineWrap Problem mit NON BREAKING SPACE

mike0007

Grünschnabel
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
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:
So bin etwas weiter. Neuer Ansatz neues Glück, aber mir fehlt noch eine Bedingung in der Abfrage. In der Klasse WrapLabelView wird an zwei stellen der Index von NBS und Space abgefragt, das führt jetzt dazu, dass nach jedem Wort umgebrochen wird, mir fehlt an dieser Stelle nun die Bedingung, dass es nur dann umgebrochen wird, wenn es über den Rand der JEditorPane hinausgeht, hat da jmd eine Idee wie man das realisieren könnte?


MyEditorKit

Java:
package de.ext;

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 WrapLabelView(elem);
					}
					// else
					// if (kind.equals(AbstractDocument.ParagraphElementName))
					// {
					// return new NoWrapParagraphView(elem);// 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;
	// }

}

TestMain
Java:
package de.ext;

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, 700);
		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>Break --- 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>No Break --- 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>";

		// lala2 =
		// "<p>So konkret waren die Spekulationen über einen \u00A0 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>" + lala + lala2 + "</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));

		split.setDividerLocation(350);

		f.add(split, BorderLayout.CENTER);

		f.setVisible(true);

	}

}

WrapLabelView
Java:
package de.ext;

import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.GlyphView;
import javax.swing.text.LabelView;
import javax.swing.text.View;

public class WrapLabelView extends LabelView
{
	public WrapLabelView(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;
			}
			try
			{
				// if the view contains line break char return forced break
				if (getDocument().getText(p0, p1 - p0).indexOf("\u00A0") >= 0)
				{
					return View.ForcedBreakWeight;
				}

				if (getDocument().getText(p0, p1 - p0).indexOf(" ") >= 0)
				{
					return View.ForcedBreakWeight;
				}

			}
			catch (BadLocationException ex)
			{
				// should never happen
			}
		}
		return super.getBreakWeight(axis, pos, len);
	}

	public View breakView(int axis, int p0, float pos, float len)
	{
		if (axis == View.X_AXIS)
		{
			checkPainter();
			int p1 = getGlyphPainter().getBoundedPosition(this, p0, pos, len);
			try
			{
				// if the view contains line break char break the view
				int index = getDocument().getText(p0, p1 - p0).indexOf("\u00A0");
				if (index >= 0)
				{
					GlyphView v = (GlyphView) createFragment(p0, p0 + index + 1);
					return v;
				}

				index = getDocument().getText(p0, p1 - p0).indexOf(" ");
				if (index >= 0)
				{
					GlyphView v = (GlyphView) createFragment(p0, p0 + index + 1);
					return v;
				}

			}
			catch (BadLocationException ex)
			{
				// should never happen
			}
		}
		return super.breakView(axis, p0, pos, len);
	}
}


UPDATE
Bin jetzt dazu übergegangen Space einzufügen, aber das Sonderzeihcen von HTML & #32; das funktioniert soweit, aber nur , wenn es vorher schon im HTML per setText() gesetzt wurde. Möchte ich das über Document oder andere insert Funktionen einfügen wird & #32; immer als Text maskiert in HTML eingetragen und ich sehe & #32; als Text in der view, anstatt das darzustellende zeichen. Mach ich das ganze mit \u00A0 (also NBS-   ) wird es im Quelltext durch   ersetzt und in der View dann wirklich als NBS interpretiert und nicht als String  

Füge ich \u0020 ein wird es nicht gewandelt, sondern wird als space zeichen interpretiert, hier würde ich gerne anstzen und & #32; anstatt des ascii space zeichens in den Quelltext einfügen, weiß jmd wie ich das machen kann?
 
Zuletzt bearbeitet:
Ich will den Thread nicht pushen, aber gibt es denn wirklich keinen, der auch nur eine Vermutung oder einen noch so kleinen Hinweis hat, der mich in eine andere Richtung denken lassen könnte?

Bin wirklich verzweifelt.
 
Moin,

nicht, das ich mir jetzt den gesamten Code angetan habe :rolleyes::D, aber hat Du es schon mal mit der HTML-Schreibweise "&nbsp" versucht ?

Gruß
Klaus
 
Moin,

nicht, das ich mir jetzt den gesamten Code angetan habe :rolleyes::D, aber hat Du es schon mal mit der HTML-Schreibweise "&nbsp" versucht ?

Gruß
Klaus

Hallo,

das würde nicht zum gewünschten Ergebnis führen, da das non breaking space den Umbruch des line wrap verhindert. Aber wir haben jetzt eine Lösung ersonnen. Dazu muss man böse Dinge mit dem HTMLWriter von Swing machen. Das hier verhindert, dass Space Space bleibt, sondern durch & #32; ersetzt wird, was dem editor so auch nichts ausmacht, die Formatierung muss noch abgestellt werden, was die Klasse automatisch in der init() Methode macht. Das ganze muss mannd ann in einem Eigenen HTMLDocument umsetzen und dann hat man Leerzeichen in der JEditorPane. Will man dann im Browser ebenso diese Leerzeichen beachtet haben muss man im HTML noch zusätzlich im CSS das hier einbauen:

Code:
<style type="text/css">
body {white-space: pre-wrap;}
</style>

Java:
package de.gui.editor;

import java.io.*;
import java.lang.reflect.Field;

import javax.swing.text.html.*;


public class CustomHTMLWriter extends HTMLWriter
{

	private char[] tempChars = null;


	public CustomHTMLWriter(Writer w, HTMLDocument doc)
	{
		super(w, doc);
		init();
	}


	public CustomHTMLWriter(Writer w, HTMLDocument doc, int pos, int len)
	{
		super(w, doc, pos, len);
		init();
	}


	private void init()
	{
		setLineLength(Integer.MAX_VALUE);
		setIndentSpace(0);
	}


	protected boolean getReplaceEntities()
	{
		try
		{
			Field replaceEntitiesField = HTMLWriter.class.getDeclaredField("replaceEntities");
			replaceEntitiesField.setAccessible(true);
			Boolean replaceEntitiesValue = (Boolean) replaceEntitiesField.get((HTMLWriter) this);

			return replaceEntitiesValue;
		}
		catch (SecurityException e)
		{
			e.printStackTrace();
		}
		catch (NoSuchFieldException e)
		{
			e.printStackTrace();
		}
		catch (IllegalArgumentException e)
		{
			e.printStackTrace();
		}
		catch (IllegalAccessException e)
		{
			e.printStackTrace();
		}
		return false;
	}


	private void outputGranpda(char[] content, int start, int length) throws IOException
	{
		getWriter().write(content, start, length);
		setCurrentLineLength(getCurrentLineLength() + length);
	}


	protected void output(char[] chars, int start, int length) throws IOException
	{
		if (!getReplaceEntities())
		{
			outputGranpda(chars, start, length);
			return;
		}
		int last = start;
		length += start;
		for (int counter = start; counter < length; counter++)
		{
			// This will change, we need better support character level
			// entities.
			switch (chars[counter])
			{
				// Character level entities.
				case '<':
					if (counter > last)
					{
						outputGranpda(chars, last, counter - last);
					}
					last = counter + 1;
					output("&lt;");
					break;
				case '>':
					if (counter > last)
					{
						outputGranpda(chars, last, counter - last);
					}
					last = counter + 1;
					output("&gt;");
					break;
				case '&':
					if (counter > last)
					{
						outputGranpda(chars, last, counter - last);
					}
					last = counter + 1;
					output("&amp;");
					break;
				case '"':
					if (counter > last)
					{
						outputGranpda(chars, last, counter - last);
					}
					last = counter + 1;
					output("&quot;");
					break;
				// Special characters
				case '\n':
				case '\t':
				case '\r':
					break;
				default:
					if (chars[counter] <= ' ' || chars[counter] > 127)
					{
						if (counter > last)
						{
							outputGranpda(chars, last, counter - last);
						}
						last = counter + 1;
						// If the character is outside of ascii, write the
						// numeric value.
						output("&#");
						output(String.valueOf((int) chars[counter]));
						output(";");
					}
					break;
			}
		}
		if (last < length)
		{
			outputGranpda(chars, last, length - last);
		}
	}


	private void output(String string) throws IOException
	{
		int length = string.length();
		if (tempChars == null || tempChars.length < length)
		{
			tempChars = new char[length];
		}
		string.getChars(0, length, tempChars, 0);
		outputGranpda(tempChars, 0, length);
	}

}


Java:
import java.io.*;

import javax.swing.text.*;
import javax.swing.text.html.*;

@SuppressWarnings("serial")
public class CustomEditorKit extends HTMLEditorKit
{

	public CustomEditorKit()
	{

	}


	@Override
	public void write(Writer out, Document doc, int pos, int len)
		throws IOException, BadLocationException
	{

		if (doc instanceof CustomHTMLDocument)
		{
			CustomHTMLWriter w = new CustomHTMLWriter(out, (CustomHTMLDocument) doc, pos, len);
			w.write();
		}
		else if (doc instanceof HTMLDocument)
		{
			HTMLWriter w = new HTMLWriter(out, (HTMLDocument) doc, pos, len);
			w.write();
		}
		else if (doc instanceof StyledDocument)
		{
			MinimalHTMLWriter w = new MinimalHTMLWriter(out, (StyledDocument) doc, pos, len);
			w.write();
		}
		else
		{
			super.write(out, doc, pos, len);
		}
	}


	public Document createDefaultDocument()
	{
		StyleSheet styles = getStyleSheet();
		StyleSheet ss = new StyleSheet();

		ss.addStyleSheet(styles);

		CustomHTMLDocument doc = new CustomHTMLDocument(ss);
		doc.setParser(getParser());
		doc.setAsynchronousLoadPriority(4);
		doc.setTokenThreshold(100);
		return doc;
	}


}
 
Zuletzt bearbeitet:
Zurück