Special JSplitPane behavior?

I am working with a component that is a JSplitPane that contains a JDesktopPane as its bottom component. The JDesktopPane just so happens to have an image painted on its background.

One of the annoying things about this is that when you drag the split bar around, it "nudges" the JDesktop up and down (as you'd expect), but when this occurs, obviously the JDesktopPane's background image moves around as well.

What I'm looking for pointers on how to do is make it so that the split pane appears to (or actually is able to) sit "on top of" the desktop pane. Another feeble attempt at phrasing this would be to say: what if the bottom component of the split pane were "empty", and the JDesktopPane "underneath" the split pane, in such a case, could "leak through"?

Is this something someone has done, or can give me rough pointers on where to head next?

Thanks,

Laird

[905 byte] By [ljnelsona] at [2007-11-27 6:44:53]
# 1

You could put a desktop pane in a JLayeredPane and a split pane on top that is non-opaque. Although that might prove problematic in several regards:

a) The split pane won't control how things are placed in the desktop pane.

b) Anything in the split pane would cover any iframes in the desktop pane and would not be easily movable.

I'm not sure what your actual goal here is.

bsampieria at 2007-7-12 18:16:29 > top of Java-index,Desktop,Core GUI APIs...
# 2

Well, I don't understand the question or problem either. Of course the desktop pane will resize as you move the divider up/down. I don't understand what you mean about the image moving as well. Presumably the image is painted at (0, 0) of the desktop, so what exactly is moving.

If you need further help then you need to create a [url http://homepage1.nifty.com/algafield/sscce.html]Short, Self Contained, Compilable and Executable, Example Program[/url] (SSCCE) that demonstrates the incorrect behaviour, because I can't guess exactly what you are doing based on the information provided.

Don't forget to use the [url http://forum.java.sun.com/help.jspa?sec=formatting]Code Formatting Tags[/url] so the posted code retains its original formatting.

camickra at 2007-7-12 18:16:29 > top of Java-index,Desktop,Core GUI APIs...
# 3

Hmm; I can't really provide code to show what I want to do, because I don't know where to start. That's what I'm asking.

Let me try to describe what I'd like one more time, and I'll see if I can be a bit more articulate. If I fail at this, I'll take it as an indication that I'm doing something stupid, and I'll stop asking. :-)

Suppose we have an imaginary JSplitPane subclass that behaved exactly like a JSplitPane, but you could leave one of its components null. (Yes, yes, I know you can have a regular old JSplitPane with a null left (or right) component, but bear with me for a moment; there are some things that you can't do with a garden variety JSplitPane-with-a-null-child-component that I want to be able to do.)

Suppose further that you could tell this hypothetical JSplitPane class that you nevertheless wanted to be able to move the divider around (something you can't do with a regular JSplitPane when one of its two components is null).

Suppose further that you now move the divider in such a way that shrinks the non-null component, and "widens" the "hole" where the other component would go if it weren't null.

OK, pause there. You have a JSplitPane subclass with a top component and a hole where the bottom component would go.

Holding that in mind for a moment, suppose further that off to the side you have a JLayeredPane, and on a bottom/back layer of that pane you put a JDesktopPane.

Suppose you now add this hypothetical JSplitPane into a slightly higher (more forward) layer of the JLayeredPane. Recall that we've mentally moved its divider so that its top component has shrunk somewhat, and its bottom component "hole" is now visible.

What I'd like is for the lower layers (in this example, the JDesktopPane) to be visible through the "hole", and for all events (and focus transfers and the like) that would otherwise occur on the JSplitPane's bottom component to get redispatched to the JDesktopPane.

I suspect I could do this with a recipe something like this:

// not real code; just to illustrate the idea

JSplitPane pane = new JSplitPane();

pane.setTopComponent(something);

pane.setBottomComponent(new GlasspaneLikePanel());

JLayeredPane layerPane = new JLayeredPane();

layerPane.addToTheBottomLayer(new JDesktopPane());

layerPane.addToTheTopLayer(pane);

The trick in this pseudocode is, I guess, the building of the GlasspaneLikePanel, i.e. a component that is focusable, is visible, is not opaque, and dispatches all events through to whatever is "underneath" it. I haven't yet looked, but I have to imagine this is the sort of thing that non-null glasspane implementations must do.

So, that's what came to mind. The net behavior would be that you would move the divider and see what is underneath the split pane "reveal itself". Clicking around in that "hole" would actually cause clicks to occur on whatever is "through"/"under" the hole.

I hope that's more of an articulate statement of what I'm trying to accomplish.

Thanks,

Laird

ljnelsona at 2007-7-12 18:16:29 > top of Java-index,Desktop,Core GUI APIs...
# 4

> Suppose we have an imaginary JSplitPane subclass that behaved

> exactly like a JSplitPane, but you could leave one of its components null.

> ...

> Suppose further that you now move the divider in such a way that

> shrinks the non-null component, and "widens" the "hole" where

> the other component would go if it weren't null.

You mean like if you put a non-opaque, empty JPanel into the "null" side?

Presumably you can make the splitpane non-opaque, and I think this would solve your see-thru issue.

The event problem is (maybe?) a different matter, I guess, but if you look at Sun's source for BasicInternalFrameUI (I think) there's some code that demonstrates event redirection for underlying components.

bsampieria at 2007-7-12 18:16:29 > top of Java-index,Desktop,Core GUI APIs...
# 5

> You mean like if you put a non-opaque, empty JPanel into the "null" side?

> Presumably you can make the splitpane non-opaque, and I think this would solve your see-thru issue.

Yes, that would work.

> The event problem is (maybe?) a different matter

Yes, when I tried the above it was a problem. You can also take a look at the Swing tutorial on [url http://java.sun.com/docs/books/tutorial/uiswing/components/rootpane.html]How to Use Root Panes[/url]. It shows how to intercept events on a components and forward them.

Still not sure I understand your full requirement. Maybe you could use a panel with a BorderLayout. Add one component to the North and one to the Center. Then on one of the components you add a custom Border that can do the resizing of the component.

camickra at 2007-7-12 18:16:29 > top of Java-index,Desktop,Core GUI APIs...
# 6

Thanks, guys; I almost have it working, and when I do, I'll post the code.

The gist: I put a "glasspane" of sorts in as the second SplitPane component. The glasspane forwards events on to the deepest component beneath it.

I use a JLayeredPane with an OverlayLayout as the base.

I add a JDesktopPane as the bottommost component. I add a JSplitPane in the PALETTE_LAYER on top of it, with the glasspane component.

Eventwise, mouse events are actually intercepted by the JSplitPane, because its "glasspane" is just a regular old JComponent. So I overrode the processMouseEvent and processMouseMotionEvent in JSplitPane to see if the mouse event it intercepted was actually "over" the glasspane. If so, then I redispatch the event to the deepest component underneath the glasspane, which is either going to be a JInternalFrame or a JDesktopPane.

So the "hole" in the JSplitPane becomes a window of sorts onto the underlying component.

This way will work; I have a few glitches to get out of the system.

Thanks for your input.

Laird

ljnelsona at 2007-7-12 18:16:29 > top of Java-index,Desktop,Core GUI APIs...
# 7

As I suspected, there's a much simpler way. The following is unproofed and needs cleanup, but you should get the gist.

package ellington;

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import javax.swing.event.*;

public class SplitDesktop2 extends JSplitPane {

private JDesktopPane desktopPane;

private JViewport viewport;

public SplitDesktop2() {

super();

this.setOneTouchExpandable(true);

this.viewport = this.createViewport();

this.setBottomComponent(this.viewport);

this.setOrientation(JSplitPane.VERTICAL_SPLIT);

this.setDesktopPane(new JDesktopPane());

}

protected JViewport createViewport() {

final JViewport viewport = new JViewport();

viewport.setLayout(new ViewportLayout() {

public final void layoutContainer(final Container container) {

if (container == viewport) {

viewport.setViewPosition(viewport.getLocation());

viewport.setViewSize(SplitDesktop2.this.getSize());

}

}

});

return viewport;

}

public JDesktopPane getDesktopPane() {

return this.desktopPane;

}

public void setDesktopPane(final JDesktopPane pane) {

this.viewport.setView(pane);

this.desktopPane = pane;

}

}

Sample usage:

final SplitDesktop2 sd = new SplitDesktop2();

final JDesktopPane p = sd.getDesktopPane();

assert p != null;

//...put some internal frames or whatever in there

sd.setTopComponent(somePanelWithSomeWidgetsToControlWhatsOnTheDesktop);

// add the sd to a frame and go

Thanks,

Laird

ljnelsona at 2007-7-12 18:16:29 > top of Java-index,Desktop,Core GUI APIs...