0

Below is the answer specific to my original question, but if you're trying to achieve a similar structure in general, it'd probably be more practical follow camickr's method below. To do it the way I originally wanted, you have to override JPanel and implement Scrollable for the outer container. (credit to user Kylar - JTextArea on JPanel inside JScrollPane does not resize properly)

import javax.swing.*;
import java.awt.*;
import javax.swing.text.*;

public class MyEditor extends JTextPane {
    JFrame window;
    JScrollPane editScroll;
    NumberLines numPane;
    HoldMe please;

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

MyEditor() {

    setOpaque(false);
    setEditorKit(new TextWrapKit());

    numPane = new NumberLines();
    numPane.setPreferredSize(new Dimension(50,100));
    please = new HoldMe();

    please.setLayout(new BorderLayout());
    please.add(this,BorderLayout.CENTER);
    please.add(numPane,BorderLayout.WEST);

    editScroll = new JScrollPane(please);
    editScroll.setPreferredSize(new Dimension(500,500));
    editScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
    editScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 

    window = new JFrame();
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.getContentPane().add(editScroll);
    window.pack();
    window.setVisible(true);
}

private class HoldMe extends JPanel implements Scrollable{
    public Dimension getPreferredScrollableViewportSize() {
    return super.getPreferredSize(); //tell the JScrollPane that we want to be our 'preferredSize' - but later, we'll say that vertically, it should scroll.
    }

     public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
    return 16;//set to 16 because that's what you had in your code.
    }

    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
    return 16;//set to 16 because that's what you had set in your code.
    }

    public boolean getScrollableTracksViewportWidth() {
    return true;//track the width, and re-size as needed.
    }

    public boolean getScrollableTracksViewportHeight() {
    return false; //we don't want to track the height, because we want to scroll vertically.
 }   
}


private class NumberLines extends JPanel {
NumberLines() {
        setBackground(new Color(120,120,120));
        setOpaque(false);
        repaint();
    } 
@Override
protected void paintComponent(Graphics g) {
    g.fillRect(0,0,this.getWidth(),this.getHeight());

}

}

private class TextWrapKit extends StyledEditorKit {
    ViewFactory defaultFactory=new TextWrapFactory();
    public ViewFactory getViewFactory() {
        return defaultFactory;
    }
}

private class TextWrapFactory implements ViewFactory {
    public View create(Element elem) {
        String kind = elem.getName();
        if (kind != null) {
            if (kind.equals(AbstractDocument.ContentElementName)) {
                return new TextWrapView(elem);
            } else if (kind.equals(AbstractDocument.ParagraphElementName)) {
                return new ParagraphView(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);
    }
}

private class TextWrapView extends LabelView {
    public TextWrapView(Element elem) {
        super(elem);
    }

    public float getMinimumSpan(int axis) {
        switch (axis) {
            case View.X_AXIS:
                return 0;
            case View.Y_AXIS:
                return super.getMinimumSpan(axis);
            default:
                throw new IllegalArgumentException("Invalid axis: " + axis);
        }
    }

}

}   

EDIT: code replaced with SCCE, sorry for the trouble

Okay, so it's structured like this...

• Top class - extends JTextPane

• Place this JTextPane into a JPanel set to BorderLayout CENTER

• Place another JPanel into the same JPanel set to WEST

• Place the JPanel holding the two into a JScrollPane

• Ready for deployment (nope)

Basically, I can't figure out a way to do this without losing out on something critical. I can get them all together, but I'll lose scrolling. Or I'll get scrolling back, but then lose text wrapping. One time I got wrapping, and technically it scrolled but not as it should have, in otherwords, the scrollpane didn't detect the size of the text. I need the nested JPanel (1st one) to scroll with the JTextPane

The problem area is in the constructor below, sorry it's such a mess but I'm losing it over here trying different things... Probably isn't helping. I'd be so grateful if somebody could help me figure this out.

Thank you for reading.

import javax.swing.*;
import java.awt.*;
import javax.swing.text.*;
import java.awt.BorderLayout;

public class MyEditor extends JTextPane {
JFrame window;
JScrollPane editScroll;


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

MyEditor() {
    setOpaque(false);
    setEditorKit(new TextWrapKit());

    JPanel numPane = new JPanel();
    JPanel packEdit = new JPanel();

    packEdit.setLayout(new BorderLayout());
    packEdit.add(this,BorderLayout.CENTER);
    packEdit.add(numPane,BorderLayout.WEST);

    editScroll = new JScrollPane(packEdit);
    editScroll.setPreferredSize(new Dimension(500,500));        
    editScroll.setViewportView(packEdit);
    editScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
    editScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 

    window = new JFrame();
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.add(editScroll);
    window.pack();
    window.setVisible(true);
}

private class TextWrapKit extends StyledEditorKit {
    ViewFactory defaultFactory=new TextWrapFactory();
    public ViewFactory getViewFactory() {
        return defaultFactory;
    }
}

private class TextWrapFactory implements ViewFactory {
    public View create(Element elem) {
        String kind = elem.getName();
        if (kind != null) {
            if (kind.equals(AbstractDocument.ContentElementName)) {
                return new TextWrapView(elem);
            } else if (kind.equals(AbstractDocument.ParagraphElementName)) {
                return new ParagraphView(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);
    }
}

private class TextWrapView extends LabelView {
    public TextWrapView(Element elem) {
        super(elem);
    }

    public float getMinimumSpan(int axis) {
        switch (axis) {
            case View.X_AXIS:
                return 0;
            case View.Y_AXIS:
                return super.getMinimumSpan(axis);
            default:
                throw new IllegalArgumentException("Invalid axis: " + axis);
        }
    }

}

}

Community
  • 1
  • 1
Dylan
  • 304
  • 1
  • 12
  • this line is suspicious `packEdit.add(this,BorderLayout.CENTER);` you don't need to call `revalidate` after you create an object or add to some component – nachokk Nov 25 '13 at 00:36
  • For better help sooner, post an [SSCCE](http://sscce.org/). – Andrew Thompson Nov 25 '13 at 00:37
  • @nachokk Ditched the revalidates, text scrolls but does not wrap. I tend to get wrapping when I set preferred size on nested elements, but this loses scrolling. When I go the opposite way, I lose wrapping but get scrolling. – Dylan Nov 25 '13 at 00:46
  • @AndrewThompson Not sure how to condense this any further, I've been reading other peoples posts for hours, who I thought had similar problems, but none quite match even as I try to adapt their problems to my own. Hoping for a miracle, I guess. – Dylan Nov 25 '13 at 00:47
  • Dylan, @AndrewThompson says that you make a compilable example where we just have to copy and paste and try your code, you will have better help if you make a well-formed question with a sscce ;) – nachokk Nov 25 '13 at 00:48
  • @nachokk Oh, I see. Should I post it as a reply or make a new post? – Dylan Nov 25 '13 at 00:55
  • edit this actual question – nachokk Nov 25 '13 at 00:56
  • @nachokk Added, does that work for you? – Dylan Nov 25 '13 at 01:22

1 Answers1

1

extends JTextPane

Why?

setEditorKit(new TextWrapKit());

Why?

Get the scroll pane working with the default components. Then if for some reason you still need to customize you make the changes one at a time to make sure it still works. If it doesn't work any more then you know what the problem is.

packEdit.add(numPane,BorderLayout.WEST);

Looks to me like you are trying to add line number. The standard way to do this is to add your component to the row header of the scrollpane, instead of making it part of the panel added to the viewport. See Text Component Line Number for an example of this approach.

In the future a SSCCE should be posted with every question. You get one free (attempted) answer without a SSCCE.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • Why extend JTextPane? I like to override paintComponent. My JTextPane has a custom background. Why the editor kit? http://java-sl.com/tip_letter_wrap_java7.html I'll take a look at Text Component Line Number, thanks. – Dylan Nov 25 '13 at 01:16
  • Replaced old code with SSCCE by the way, sorry for the trouble. – Dylan Nov 25 '13 at 01:27
  • This is the answer: http://stackoverflow.com/questions/15783014/jtextarea-on-jpanel-inside-jscrollpane-does-not-resize-properly – Dylan Nov 25 '13 at 02:47
  • @Dylan, `This is the answer` - I gave you a simpler solution. No need for a custom panel. – camickr Nov 25 '13 at 03:08
  • Fair enough. You gave me a completely viable solution that is less work than the one I prefer. I'd just rather continue my program the way it is, but the answer is yours. – Dylan Nov 25 '13 at 03:32
  • `I'd just rather continue my program the way it is` - what is the point of asking questions if you are not willing to learn? That is why I spend time answering questions and reading other answers, to learn the best approach. – camickr Nov 25 '13 at 03:52
  • Not willing to learn? I think I'd learn more by implementing my own line numbering object from scratch, as opposed to adapting the work of someone else even if it's more efficient and most the of the learning comes from dealing with mistakes. My version does the same stuff, save for adapting to wrapped lines. For the moment, that is. This is a personal project, it's pretty much just about learning. I'm sure I'll do it the way you suggested at some point, and then I'll have knowledge of the differences. Thanks for the help. – Dylan Nov 25 '13 at 15:12
  • @Dylan, My comment was about using the "row header" of the scroll pane. I gave you the link to show you how to add a component to the row header. Then you just add the text pane to the viewport of the scroll pane. I said there was no need for a custom panel. – camickr Nov 25 '13 at 17:27
  • For the record I just did it your way (row header) and it's much more stable. When you're right, you're right, and I was wrong. There's really no advantage to following my original plan. Hope I didn't come across as too stubborn. – Dylan Nov 25 '13 at 18:33
  • @Dylan, No, I just got the impression that you didn't really understand (or try) what I was suggesting. My basic point was to try what people suggest, especially when they recommend the approach more than once :) Then make a decision, but not before. – camickr Nov 25 '13 at 19:11