Problem creating DefaultSingleCDockable with Canvas

Hi Benji,

I am trying to add a DefaultSingleCDockable in a CGrid and I want to initialize the DefaultSingleCDockable with a Canvas.
This is what I did:

final Canvas canvas = new Canvas();
            canvas.setBackground(Color.GREEN);
final DefaultSingleCDockable dockable = new DefaultSingleCDockable(
                    String.valueOf(counter.incrementAndGet()), "Green Canvas", canvas);
grid.add(0, 0, 1, 1, dockable);

Where grid is a CGrid. This does not work (I have a grey area).
When I change the Canvas by a JPanel, it works great.
The problem is that I must really use a Canvas (that is provided by a third-party library). Is this a know bug? Is there a workaround ?

I use docking frame 1.1.1-preview5c (I tried with last one as well without success)

Kind regards,
Ben

It’s probably the glass panes (invisible JComponents) that are put over all other Components. Just like in this thread. What is the name of this third party library?

If there are additional settings required to support invisible glass panes, then they can be included. E.g. for JWebBrowser you need something like this (only works since 1.1.1p6):

  @Override
    public void markAsGlassPane( Component component ){
      UIUtils.setComponentTransparencyHint(component, TransparencyType.NOT_VISIBLE);
    }
});```

The library is VTK (http://www.vtk.org), a native C++ library for displaying 3D objects.

There is a Java wrapping (provided with VTK) that embeds the 3D viewer in a Java Canvas.

I will try your workaround and let you know if it works.

Ben

Ok, I don’t know VTK, nor did I find any hints regarding VTK + glass panes with a quick google search.

P.S. I might need to add, that the workaround above uses code that is only available when using JWebBrowser. The UIUitils do not belong to docking-frames.

[QUOTE=Beni]Ok, I don’t know VTK, nor did I find any hints regarding VTK + glass panes with a quick google search.

P.S. I might need to add, that the workaround above uses code that is only available when using JWebBrowser. The UIUitils do not belong to docking-frames.[/QUOTE]

I realized that :slight_smile:

I looked in VTK source code and did not find any reference to glass panes.

Even if we don’t consider VTK, with a simple Canvas as shown in the code in my first post, it doesn’t seem to work. How would you use your workaround with a standard Java Canvas?

In theory it should… but that may depend on Java Version and OS, what are you using? I’ll have to do some tests before answering that question, could take a day or so…

java version „1.6.0_27“
Java™ SE Runtime Environment (build 1.6.0_27-b07)
Java HotSpot™ 64-Bit Server VM (build 20.2-b06, mixed mode)

Operating System is Fedora 15 64-bits.

Thank you. I will keep you posted if I find the reason of this behaviour

As usual if I try to test something like this, it works flawlessly on my system. This was done with Ubuntu 64 Bit, Java 1.6.0_27.

Which means chances of me being able to help you just decreased drastically.

When implementing the Glass Pane I followed the instructions on mixing components, meaning “setComponentMixingCutoutShape” is called for any Glass Pane. According to Sun/Oracle that should be enough. You might want to try “The mixing feature can be turned off by using the private sun.awt.disableMixing system property.”, I don’t know if it will help.

This is the code I used…


import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JFrame;

import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.theme.ThemeMap;

public class CanvasTest {
	public static void main( String[] args ){
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		
		CControl control = new CControl( frame );
		control.setTheme( ThemeMap.KEY_ECLIPSE_THEME );
		control.getController().setRestrictedEnvironment( true );
		frame.add( control.getContentArea() );
		
		for(int i = 0; i < 2; i++){
			Canvas canvas = new Canvas(){
				@Override
				public void paint( Graphics g ){
					super.paint( g );
					g.setColor( Color.RED );
					int w = getWidth();
					int h = getHeight();
					g.fillRect( 0, 0, w/2, h/2 );
					
					g.setColor( Color.BLUE );
					g.fillRect( w/2, h/2, w/2, h/2 );
				}
			};
			
			DefaultSingleCDockable dockable = new DefaultSingleCDockable( "canvas" + i, "Test", canvas );
			control.addDockable( dockable );
			dockable.setVisible( true );
		}
		
		frame.setBounds( 20, 20, 400, 400 );
		frame.setVisible( true );
	}
}

… and the result is in the attachement.

Thanks Benji,

I tried on Mac OS X and my code worked.

On Linux, I suspect it comes from a multi-thread problem… Moreover, I am running docking frames in an OSGi bundle, which does not simplify the debugging…

I tried a simple example outside the OSGi context and I could add my Canvas without problem.

I am still working on it, I let you know.

Good luck. If you find a solution, or if I can help you in any way, please let me know.

Hi Benj,

After a few month working on other parts of my project, I am back to this particular problem.

I confirm that I encounter it on my Linux machine (Fedora 16 - 64 bits), with either Java 6 or Java 7. I use Docking Frames 1.1.1 preview 6e.

This problem is critical for my project: if I can’t solve it, I will not be able to use Docking Frames at all :(. And I really want to use docking frames :).

So here is a sample project that can reproduce the bug:
http://dev.artenum.com/downloads/docking-canvas-osgi_zip

It is build as a Maven project composed of two modules:

  • docking-canvas-osgi-dock contains a DockingManager class that allows to embed a Component in a CDockable
  • docking-canvas-osgi-frame contains the TestFrame class that initialises the DockingManager and adds a blue and a green canvas to the frame.

It works perfectly with JPanels
It also works when using the main() method to start the application.

But as soon as I am in an OSGi context, the Canvas objects are below the CDockable and you don’t see their colored background at all (sad grey instead).

The only difference I can this of is that in OSGi, the two classes are instantiated by two different class loaders. But I tryied out of the OSGi context to load them with different class loaders and it worked.

To compile the sample project, simply type:
mvn clean install

in the terminal (you need Maven 2.2.1 or above)

To test the bug, go in the felix-framework-4.0.2 directory and execute the run.sh script file. This loads the jar that are in the felix-framework-4.0.2/bundle directory, so if you rebuild the project, you have to move your newly generated jars there for it to work.

Could you please help? I’m a bit lost here :frowning:

Your files helped a lot. There is a hidden exception inside the framework, usually this exception is thrown if the framework started with an old JRE. To be a little bit more exact, the class “Java6Workaround” plays around with reflection, trying to access some of the inner workings of AWT. This is only required and working with some versions of Java 1.6, and until now the equation “exception = the call is not required” always was true, hence the exception is hidden. When using OSGi, the exception is suddenly thrown even in Java 1.6.

java.lang.ClassNotFoundException: com.sun.awt.AWTUtilities not found by docking-canvas-osgi-dock [1]
        at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1460)
        at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:72)
        at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1843)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:169)
        at org.test.canvas.dock.GlassedPane.markAsGlassPane(GlassedPane.java:142)
        at org.test.canvas.dock.GlassedPane.access$000(GlassedPane.java:57)
        at org.test.canvas.dock.GlassedPane$GlassPane.<init>(GlassedPane.java:191)
        at org.test.canvas.dock.GlassedPane.<init>(GlassedPane.java:61)
        at org.test.canvas.dock.DockingManager.<init>(DockingManager.java:38)
        at org.test.canvas.frame.TestFrame.start(TestFrame.java:37)
        at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:641)
        at org.apache.felix.framework.Felix.activateBundle(Felix.java:1977)
        at org.apache.felix.framework.Felix.startBundle(Felix.java:1895)
        at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1191)
        at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:295)
        at java.lang.Thread.run(Thread.java:662)

I do not know how exactly to fix this issue, but I guess you have a lot more experience in this. You could help me a lot If you could tell me how to get this piece of code compiled and running inside the “DockingManager” constructor. There is a good chance that snippet will fix the issue.

			@Override
			public void markAsGlassPane( Component component ){
				AWTUtilities.setComponentMixingCutoutShape( component, new Rectangle() );
			}
			
			@Override
			public boolean makeTransparent( Window window ){
				// not needed (for now?)
				return false;
			}
		} );```

Thanks very much for your quick answer.

I tried your solution and it worked!

Here is the code of the constructor of my DockingManager class:

public DockingManager(final String name) {
        try {
            for (final LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (final Exception e) {
            // If Nimbus is not available, you can set the GUI to another look and feel.
        }

        Workarounds.getDefault().addWorkaround(new Workaround() {
            @SuppressWarnings("restriction")
            @Override
            public void markAsGlassPane(final Component component) {
                com.sun.awt.AWTUtilities.setComponentMixingCutoutShape(component, new Rectangle());
            }
        });

        // Instantiates the frame
        this.frame = new JFrame(name);
        this.frame.getContentPane().setLayout(new BorderLayout());
        this.frame.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);

        // Instantiates the dynamic content controller
        this.control = new CControl(this.frame);
        this.frame.add(this.control.getContentArea(), BorderLayout.CENTER);

        // Setting the docking frames theme
        final ThemeMap theme = this.control.getThemes();
        theme.select(ThemeMap.KEY_ECLIPSE_THEME);

        // Grid layout of the dynamic content
        this.grid = new CGrid(this.control);
    }

I however had to remove the code:

@Override
            public boolean makeTransparent( Window window ){
                // not needed (for now?)
                return false;
            }

Because the method does not appear in the Workaround interface (even in Docking Frames 1.1.1-preview 7a) and though it did not compile.

Then, because com.sun.awt.AWTUtilities is not part of the officially supported API of Java (and may thus not work in future versions of Java), I have to explicitly provide the package to OSGi.

I thus created the dummy OSGi bundle in attachement and added it in the felix/bundle folder.

Thanks again for your very usefull help.

When my project is finished (it’s a spacecraft plasma interactions modelling tool), I will explicitly mention your project and your help on our website :slight_smile:

Kind regards

Ah, you are right, the „makeTransparent“ methode is part of the Toolbar-branch, which is not the one on the website. Well, I’m happy the fix worked, and thanks for telling how you updated the project.

In Java 7 there will already another workaround be needed (can be found in the class „Java7Workaround“). But then at least we will know what to do.

And please send me a screenshot of your finished application :stuck_out_tongue:

You’re welcome

I will

Reviving an old thread.

I just updated to 1.1.2p9c and noticed the Workaround interface has been changed. There are now new methods.

Does the above Workaround still is valid or is there a cleaner way?

Please find attached the promised screenshot.

The application is open source and a new version is coming soon.

The workaround should still work. And no, there is no cleaner way.

*** Edit ***

Is there a webpage of your application? The image looks interesting, unfortunately a little bit small (I cannot read the name of the application).

Yes, there is a website :slight_smile:

But I can’t advertise it yet. Waiting for the client to approve it. Should be done by the end of the year.

The software is a modelling tool for the space industry.

I will update the post as soon as I have the „go“