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)
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):
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
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…
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 );
}
}
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.
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 :).
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.
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;
}
} );```
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
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