1

Before I start, similar question (of mine) exists, I'd like that one to be deleted since I didn't explain my point well there, but not this one. Thank you.

First of all, I have no code, this is only a concept that I can't figure out. But it's interesting (at least to me).

You all know how MSWord works. You write stuff. Then, when you fill a page it will create a new page and start writing on that page. If you paste some more text to the first page, everything will be pushed down. If you delete a large chunk of text on a page, it will suck up some of the text on the previous page. If you're dealing with e.g. pictures and you have one on top of a page, reducing it's size my cause it to get sucked up to the previous page, if there is enough room for the reduced version of the picture.

Now that you're thinking this way, I want to transfer that concept into Java Swing. Pages are JPanels, and pictures and chunks (or lines) of text are JPanels fitted onto the page JPanel.

I have come up (okay, I lied, I have some code, but it's a mess and it doesn't work anyway) with a method using a Filler, which doesn't work in all cases. If you want to know why, read between the two lines, otherwise just skip it.


So, the structure itself is easy to replicate, but maintaining it is a pain in the neck. You see, there are two main types of events that can occur:

a) height of the page content has increased
b) height of the page content has decreased

By using a Filler as the last component of a page, and having a componentAdapter (componentResized) attached to it, you can monitor those changes.

These changes can further be dividet into:

a) element is added/removed to/from page
b) height of the element has increased/decreased 

Taking those events into consideration many things can happen. Skipping the simple cases, look at this example:

Page 1:
{element 1
blabla
blabla}
{element 2
blabla}
{element 3}
{element 4
blabla
blabla
blabla
blabla}
{free space
---
---
---}

/

Page 2:
{element 1
blabla
blabla
blabla
blabla}
{element 2
blabla
blabla
blabla
blabla}
{element 3}
{element 4
blabla
blabla
blabla}

/

Page 3:
{element 1}
{element 2}
{element 3}
{element 4}
{element 5}
{free space
---
---
---
---
---
---
---
---
---}

Each page has a height of 15 rows. Look now what happens if you reduce the height of the element 1 of the second page by one row. It will become 4 rows high, making it fit to the previous page, being sucked up. That will create 5(1 deleted row + 4 sucked up rows) rows worth of free space on the second page. That will suck up all the five elements on the third page and leave the third page blank (which should now be deleted).

The reason this wouldn't work is because upon deletion, a listener is triggered for the second page and it has to both push the top element up, and suck up the elements from the previous page. Since it's all done in a listener, I have to wait for it to execute in order to register visual change in my program. Since it has to change two thing on a page, it comes to somekind of listener chaos. Page height is reduced twice but is registered only once and in the end I can fully move only thr top part or the bottom part, or a single component on each side. This isn't really a good explenation, but if you understand how swing works, you should be able to connect the dots yourself.

As I mentioned before, I have written the code for that, but it's long and hard to follow, and I can post it here, if anyone shows the desire to see it. And I'm talking about SSCCE itself. It really can't be shortened into couple of 10s of rows of code.


What I would want is to skip writting an algorithm that would maintain the structure of the "document" and move all the elements around, since it's a really complicated thing to do, taking all the numerous cases.

What I want is an alternative and I'm asking you if you have any ideas. One thing that came to my mind is having a component similar to JPanel. It would have fixed height-parts that can be populated with other components, and between them fixed height-parts that are unpopulable(?) or "solid".

Way it would work would be that everytime you add something to populable(?) parts, they would be automatically rearanged. If something doesn't fit to the current populable part, it's just moved to the next one (similar to how verticall box layout works, adding one thing to a spot pushes all the others down), but skiping the solid part.

Since I would also have to be able to tell in which populable part a certain component is, I don't know if creating a such structure is possible in Java swing.

Well, any advice is welcome, external libaries included.

Just keep in mind that this whole document is document with pages that would be placed one after another in a JScrollPane's viewport, and that is the only limit to what it should look like.

Karlovsky120
  • 6,212
  • 8
  • 41
  • 94
  • 1
    Post some code, post an [SSCCE](http://sscce.org). Describing code with words discourages people from reading your post and can only bring confusion, while showing code will help others understand your issue(s) and remove any possible ambiguities. – Guillaume Polet Jan 25 '13 at 19:45
  • If I post what I have, even with everything unecessary removed, it would still be a lot of code which is on top of that hard to read if you're not familiar with it. – Karlovsky120 Jan 25 '13 at 23:10
  • Yet after 5 hours you have one answer which does not seem to satisfy you (although it is one of my very dear friend @trashgod). I wouldn't worry too much about code complexity: true experts here are quite familiar with that. I don't see how code to reproduce one issue must be long (you can almost always split big problems into smallers ones and fix them one at a time). I leave this up to you..., I am not the one having a question ;-) – Guillaume Polet Jan 26 '13 at 00:26
  • To replicate the problem, I have to move bunch of things following a set of rules. I have to also create that bunch of things, or, due to the nature of the problem, make it possible for you to create/remove bunch of things. And all that code, combined with the complexity of the rules, takes up quite a lot of space. Besides, I know what the problem with my code is and I know how would I go about fixing it, but the solution is a pain in the neck to code (and hard to maintain later), so real question is coming up with an alternative to my filler-listener method. – Karlovsky120 Jan 26 '13 at 00:32
  • It may help to separate model and view more rigorously, as the text components do; remove content from the model and signal the view to update itself accordingly. – trashgod Jan 26 '13 at 00:39
  • Hmmm, that approach could work... – Karlovsky120 Jan 26 '13 at 00:45
  • 2
    Sounds more like you need custom layout manager (or two). One would deal with laying out components on the page, the other out work out on which page components need to be – MadProgrammer Jan 26 '13 at 01:08
  • I'm not trying to fix my code. I know how to fix it, but it's a lot of work I'm trying to avoid. What I'm looking for is an alternative... – Karlovsky120 Jan 26 '13 at 15:18
  • I see... is this for a project or your own? becuase why not use a Styled Text Component which will allow embedded images and components: http://docs.oracle.com/javase/tutorial/uiswing/components/text.html. Even if its the latter you have a look at the components source code illustrated in the link Im sure it will help with the understanding.. – David Kroukamp Jan 26 '13 at 15:42
  • But using styled text components would still leave me with the main issue of managing the content migration from one component to another... P.S. It's my own. – Karlovsky120 Jan 26 '13 at 19:02

1 Answers1

3

Let the layout do the work: add() instances of JPanel, each having its own preferred size based on content, to a Box having a vertical layout. Put the Box in a JScrollPane, optionally implementing Scrolable. Use the scroll pane's row and column headers as needed; JTable is an example. You can remove() a panel from the Box, revalidate() and repaint() as required.

Addendum: The initial answer addressed only the view aspect of the problem. It may help to separate the model and view more rigorously, as the text components do; remove content from the model and signal the view to update itself accordingly. To achieve this, several common approaches to implementing the observer pattern are mentioned here.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • You both missed the point... I don't want to create a nice layout, I have already done that. I can potentialy change the way it's created without really visually changing it, if it helps my problem. What I want is similar to how MS Word manages it's text rows or any other components. If you keep adding to a page, it will push everything down, and if you remove something, it pulls everything up... The problem is is that I don't want that as a one visual entity, but as visualy separated entitites (pages)... – Karlovsky120 Jan 25 '13 at 23:15
  • Like Word's page view? Set the box background to gray and add a border to the panels. – trashgod Jan 26 '13 at 00:27
  • Sorry, I thought you were missing the point again, I down-voted the answer before the addendum was added (or I managed to miss it)... Well, I could redraw everything every time a change is made, but it's really not efficient, and if I try to redraw only when needed, I come to the same problem again... I'll think about it some more, I might come up with a solution using this... – Karlovsky120 Jan 26 '13 at 15:34
  • No problem; I appreciate the feedback. For reference, `JTable` addresses rendering efficiency using the _flyweight pattern_, illustrated [here](http://stackoverflow.com/a/7776211/230513). I haven't examined text components as closely. – trashgod Jan 26 '13 at 15:47