Articles Projects Tips Downloads Contacts About

Tab char measuring in paragraph with right or center alignment.

When paragraph's alignment isn't left (e.g. right or center) tab char is represented as fixed width space rather than normal insets.

The class below illustrates the problem

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.JButton;
import javax.swing.JFrame;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Element;

import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
 
public class RTFAlignmentStyle extends JFrame
{
	private static String message = ""; 
	private JButton center = null;
	private JButton left = null;
	private JButton right = null;
	JPanel jp = null;
	StyleContext context = null;
	DefaultStyledDocument document = null;
	Style style = null;
	JTextPane textPane = null;
	JScrollPane scrollPane = null;

 
	RTFAlignmentStyle()
	{
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
		context = new StyleContext();
		document = new DefaultStyledDocument(context);
 

		style = context.getStyle(StyleContext.DEFAULT_STYLE);
		StyleConstants.setAlignment(style, StyleConstants.ALIGN_LEFT); // decomment for left alignmnent
		StyleConstants.setFontSize(style, 24);
		StyleConstants.setSpaceAbove(style, 4);
		StyleConstants.setSpaceBelow(style, 4);
 
		try {
			document.insertString(document.getLength(), message, style);
		} catch (BadLocationException badLocationException) {

			badLocationException.printStackTrace();
		}
		textPane = new JTextPane(document);
		scrollPane = new JScrollPane(textPane);
		center = new JButton("Center");
		left = new JButton("Left");
		right = new JButton("Right");

 
		jp = new JPanel();
		jp.add(left);
		jp.add(center);
		jp.add(right);
 
		add(scrollPane, BorderLayout.CENTER);
		add(jp, BorderLayout.SOUTH );
 
		setSize(500, 150);
		setVisible(true);
 
		ActionListener al = new ActionListener()
		{

			Element el = null;
			public void actionPerformed(ActionEvent ae)
			{
				Style sty = null;
				if(ae.getActionCommand().equalsIgnoreCase("Center"))
				{

					StyleConstants.setAlignment(style,StyleConstants.ALIGN_CENTER);
					el = document.getParagraphElement(textPane.getCaretPosition());
					document.setParagraphAttributes(el.getStartOffset(),el.getEndOffset()-el.getStartOffset(),style,false);
				}else if(ae.getActionCommand().equalsIgnoreCase("Right"))
				{
					StyleConstants.setAlignment(style,StyleConstants.ALIGN_RIGHT);
					el = document.getParagraphElement(textPane.getCaretPosition());
					document.setParagraphAttributes(el.getStartOffset(),el.getEndOffset()-el.getStartOffset(),style,false);
				}else if(ae.getActionCommand().equalsIgnoreCase("Left"))
				{

					StyleConstants.setAlignment(style,StyleConstants.ALIGN_LEFT);
					el = document.getParagraphElement(textPane.getCaretPosition());
					document.setParagraphAttributes(el.getStartOffset(),el.getEndOffset()-el.getStartOffset(),style,true);
				}
				textPane.grabFocus();
			}
		};
 
		center.addActionListener(al);
		right.addActionListener(al);
		left.addActionListener(al);
	}

 
	public static void main(String args[]) {
		new RTFAlignmentStyle();
	}

}

The problem is the 2 lines in ParagraphView
if(justification != StyleConstants.ALIGN_LEFT)
return x + 10.0f

and one more class with fixed behavior

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.*;

 
public class RTFAlignmentStyle extends JFrame
{
    private static String message = "";
    private JButton center = null;
    private JButton left = null;
    private JButton right = null;
    JPanel jp = null;
    StyleContext context = null;
    DefaultStyledDocument document = null;
    Style style = null;
    JTextPane textPane = null;
    JScrollPane scrollPane = null;

 
    RTFAlignmentStyle()
    {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
        context = new StyleContext();
        document = new DefaultStyledDocument(context);
 

        style = context.getStyle(StyleContext.DEFAULT_STYLE);
        StyleConstants.setAlignment(style, StyleConstants.ALIGN_LEFT); // decomment for left alignmnent
        StyleConstants.setFontSize(style, 24);
        StyleConstants.setSpaceAbove(style, 4);
        StyleConstants.setSpaceBelow(style, 4);
 
        try {
            document.insertString(document.getLength(), message, style);
        } catch (BadLocationException badLocationException) {

            badLocationException.printStackTrace();
        }
        textPane = new JTextPane();
        textPane.setEditorKit( new MyEditorKit());
        textPane.setDocument(document);
        scrollPane = new JScrollPane(textPane);
        center = new JButton("Center");
        left = new JButton("Left");
        right = new JButton("Right");

 
        jp = new JPanel();
        jp.add(left);
        jp.add(center);
        jp.add(right);
 
        add(scrollPane, BorderLayout.CENTER);
        add(jp, BorderLayout.SOUTH );
 
        setSize(500, 150);
        setVisible(true);
 
        ActionListener al = new ActionListener()
        {

            Element el = null;
            public void actionPerformed(ActionEvent ae)
            {
                Style sty = null;
                if(ae.getActionCommand().equalsIgnoreCase("Center"))
                {

                    StyleConstants.setAlignment(style,StyleConstants.ALIGN_CENTER);
                    el = document.getParagraphElement(textPane.getCaretPosition());
                    document.setParagraphAttributes(el.getStartOffset(),el.getEndOffset()-el.getStartOffset(),style,false);
                }else if(ae.getActionCommand().equalsIgnoreCase("Right"))
                {
                    StyleConstants.setAlignment(style,StyleConstants.ALIGN_RIGHT);
                    el = document.getParagraphElement(textPane.getCaretPosition());
                    document.setParagraphAttributes(el.getStartOffset(),el.getEndOffset()-el.getStartOffset(),style,false);
                }else if(ae.getActionCommand().equalsIgnoreCase("Left"))
                {

                    StyleConstants.setAlignment(style,StyleConstants.ALIGN_LEFT);
                    el = document.getParagraphElement(textPane.getCaretPosition());
                    document.setParagraphAttributes(el.getStartOffset(),el.getEndOffset()-el.getStartOffset(),style,true);
                }
                textPane.grabFocus();
            }
        };
 
        center.addActionListener(al);
        right.addActionListener(al);
        left.addActionListener(al);
    }

 
    public static void main(String args[]) {
        new RTFAlignmentStyle();
    }

 
}
class MyEditorKit extends StyledEditorKit {
    static char[] tabChars;
    /** Used for searching for a tab or decimal character. */

    static char[] tabDecimalChars;
 
    static {
        tabChars = new char[1];
        tabChars[0] = '\t';
        tabDecimalChars = new char[2];
        tabDecimalChars[0] = '\t';
        tabDecimalChars[1] = '.';
    }

 
    
    public ViewFactory getViewFactory() {
        return new StyledViewFactory();
    }
 
    class StyledViewFactory implements ViewFactory {

 
        public View create(Element elem) {
            String kind = elem.getName();
            if (kind != null) {
                if (kind.equals(AbstractDocument.ContentElementName)) {

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

    class MyParagraphView extends ParagraphView {
 
        public MyParagraphView(Element elem) {
            super(elem);
        }

        public float nextTabStop(float x, int tabOffset) {
            float tabBase=getTabBase();
        // If the text isn't left justified, offset by 10 pixels!

//        if(justification != StyleConstants.ALIGN_LEFT)
//                return x + 10.0f;
            x -= tabBase;
            TabSet tabs = getTabSet();
            if(tabs == null) {
                // a tab every 72 pixels.
                return (float)(tabBase + (((int)x / 72 + 1) * 72));
            }

            return super.nextTabStop(x, tabOffset);
        }
    }
}