Bug 65431 - Main NetBeans frame remains undecorated under custom LAF
Main NetBeans frame remains undecorated under custom LAF
Status: VERIFIED WORKSFORME
Product: platform
Classification: Unclassified
Component: Window System
5.x
All All
: P3 (vote)
: 5.x
Assigned To: David Simonek
issues@platform
: API, API_REVIEW_FAST, L&F
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2005-09-29 21:08 UTC by kirillcool
Modified: 2008-12-22 20:57 UTC (History)
8 users (show)

See Also:
Issue Type: DEFECT
:


Attachments
API change in openide/windows and changes in javacore and autoupdate (24.29 KB, text/plain)
2005-10-19 11:24 UTC, Jaroslav Tulach
Details

Note You need to log in before you can comment on or make changes to this bug.
Description kirillcool 2005-09-29 21:08:03 UTC
When NetBeans is run with custom LAF (using -laf setting) and the LAF's
constructor calls
  JFrame.setDefaultLookAndFeelDecorated(true);
  JDialog.setDefaultLookAndFeelDecorated(true);
All the NetBeans frames / dialogs use custom decorations except the main window.

In order to reproduce, use Substance LAF from https://substance.dev.java.net and 
-J-Dsubstancelaf.useDecorations
setting (no value needed). You will notice that main frame remains undecorated,
while all other dialogs / frames pick the custom title pane.
Comment 1 David Simonek 2005-10-14 14:28:20 UTC
I found what is going on:

Main window is created far sooner during startup of netbeans then custom LF is
set. This is wrong order and the result is, that main window doesn't know about
Substance LF decorations, because Substance LF isn't set at this moment yet.

I tried to reset decorations to the main window later, but it breaks whole
painting and other behaviour of main window, so apparently Swing doesn't allow this.

I fixed part of the problem:
/cvs/core/windows/src/org/netbeans/core/windows/view/ViewHierarchy.java,v  <-- 
ViewHierarchy.java
new revision: 1.40; previous revision: 1.39

But the real order needs to be fixed in startup code:
        at java.lang.Thread.dumpStack(Thread.java:1158)
        at org.netbeans.swing.plaf.Startup.run(Startup.java:363)
        at org.netbeans.core.CoreBridgeImpl.initializePlaf(CoreBridgeImpl.java:9
2)
        at org.netbeans.core.startup.Main.initUICustomizations(Main.java:172)
        at org.netbeans.core.startup.Main.start(Main.java:366)

must be called before any call like below:
        at org.netbeans.core.windows.view.ui.MainWindow.<init>(MainWindow.java:9
9)
        at org.netbeans.core.windows.view.ViewHierarchy.getMainWindow(ViewHierar
chy.java:90)
        at org.netbeans.core.windows.view.DefaultView.getMainWindow(DefaultView.
java:86)
        at org.netbeans.core.windows.ViewRequestor.getMainWindow(ViewRequestor.j
ava:74)
        at org.netbeans.core.windows.Central.getMainWindow(Central.java:1400)
        at org.netbeans.core.windows.WindowManagerImpl.getMainWindow(WindowManag
erImpl.java:127)
        at org.netbeans.modules.autoupdate.Autoupdater$2.run(Autoupdater.java:87
)
        at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:461)
        at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchTh
read.java:242)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThre
ad.java:163)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)

        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)

        at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)
Turning on modules:
        org.openide.util [6.5 051011]
        org.openide.modules [6.4 051011]

As you can see, MainWindow is created even during modules restoring, and I found
several such places. Because we don't have proper API for modules to know when
GUI is ready, such calls are inevitable.

To conclude: 
        at org.netbeans.core.startup.Main.initUICustomizations(Main.java:172)
should be moved before modules loading, to have Swing UI properly set before
modules may touch it.

I'm not familiar with startup code and I'm not sure if I woudl do it right, so
passing to Jesse, kindly asking for help. At the same time I'm raising priority,
because it looks like major startup flaw for me when we are constructing main
window with not-yet-set look and feel. Many other issues like wrong fonts etc
may be connected to this.

Jesse please, do you agree with the change and can you do it? Thanks.
Comment 2 Jesse Glick 2005-10-14 19:15:51 UTC
I don't know anything about this area of code. Maybe Yarda does? I don't
remember who works on this.
Comment 3 Jaroslav Tulach 2005-10-15 07:40:22 UTC
I'll register the UI before ModuleInstalls are called. Probably I introduce PreInstall   
interface which instances will be found in lookup as soon as classloaders are   
ready, but before layers are constructed and  ModuleInstalls called. 
Comment 4 Jesse Glick 2005-10-18 00:29:42 UTC
Or simply add to ModuleInstall:

/**
 * Called as early as possible, before layers and so on are ready.
 * Normally better to use {@link #restored}.
 */
public void prerestored() {}

?
Comment 5 _ rkubacki 2005-10-18 13:51:13 UTC
We're about to introduce new API. 

IMO the suggested way is not the right one. I think that noone should use winsys
during module system loading. Load modules first then init and show winsys (with
UI init at the beggining) and finally run other codes that can be queued into
end of startup sequence like AU client, resolve broken refs dialog and many similar.

PreInstall/prerestored() adds yet another layer/level into a place that seems to
be well structured in current startup although we cannot be convinced that there
are too many use cases to justify this.
Comment 6 Jaroslav Tulach 2005-10-18 18:18:15 UTC
Do that mean that we should resuscitate the old idea of   
  
void WindowManager.runExclusive(Runnable r);  
  
with the semantic being that only one of these runnables can run at one time  
and all of them are executed only when window system is ready? If so, I can 
provide such patch and also fix autoupdate to behave "in the right way" 
Comment 7 Jaroslav Tulach 2005-10-19 11:24:06 UTC
Created attachment 26122 [details]
API change in openide/windows and changes in javacore and autoupdate
Comment 8 Jaroslav Tulach 2005-10-19 11:29:54 UTC
I'd like to add new method  
 
void WindowManager.invokeExclusively(Runnable) 
 
that could be used to run code as soon as window system is "ready". That is 
going to fix our infamous getMainWindow().addWindowListener trick. 
 
I've attached the patch which in my opinion solves everything and also this 
problem. It contains new TCK in openide/windows and test that verifies that 
core/windows correctly implement that.  
 
As author of the change I've 'selected' Dafe, as he will know much better when 
the window system is "ready". For now I put the code into 
WindowManagerImpl.setVisible, but maybe there is better place for it. That is 
why I am reassigning to him. 
Comment 9 _ rkubacki 2005-10-19 12:30:07 UTC
I like this much more than previous idea. 

The only remaining comment from me is priority of these tasks. Is it important
or not? If it is it would be better to register either some runnable in XML
layer or service in META-INF/services.
Comment 10 David Simonek 2005-10-20 10:33:18 UTC
Wellm I hoped for different solution, simply moving init of LF and netbeans LF
initialization to earlier place of startup process.
Remember we are trying to solve the problem, that UI is initialized too late. We
are *not* solving the problem that window system is accessed too early.
IMO it is wrong to tie LF initialization and winsys together. No, LF init should
be already done when modules can do anything with Swing, open their frame or
dialog. I know two such cases - updater and licence check (correct me if I'm wrong).

My conclusion: Suggested solution is a solution for another problem, not this
one, so I can't finish it and commit. Please consider and try to implement (or
advice me) my idea from above, if you agree.

However I agree that solution suggested by jtulach can be useful and we can
finetune it in separate enhancement.
Comment 11 Jaroslav Tulach 2005-10-20 12:43:07 UTC
"priority of these tasks" - or just have invokeExclusively(Runnable, int        
priority), if really needed, which I do not think.  
        
"Remember we are trying to solve the problem" - We are solving the problem of 
main window  without correct UI - as far as I can tell my patch solves it.      
      
Moreover I would argue that the reason for all these problems is that people      
are using WindowListener for showing a UI at reasonable time after the startup      
as there is nothing better to use. The invokeExclusively solves the problem      
for one and all.      
      
"updater and licence check" - they form a separate issue, they are run before  
the module system is initialized and at such early time there is no way to  
call the CoreBridgeImpl.initializePlaf    
    
"LF init should be already done when modules can do anything with Swing, open   
their frame or dialog" - I fully agree. That is why I suggest that we tell   
module writers to not touch swing in ModuleInstall.restored, but instead call  
invokeExclusively and handle the rest of the stuff there.  
  
Comment 12 David Simonek 2005-10-20 13:17:31 UTC
Yes, your solution fixes the problem for now in our own modules. Generally, any
module (our, 3rd party, point products) can freely call
WindowSystem.getMainWindow() (with no warning sign that they do smt wrong) and
break things again. And so they will for sure, not good. Perhaps jarda's
solution can be improved by adding a check in WindowSystem.getMainWindow that
would scream on console if called too early. Hmm although implementation of this
won't be that straighforward.

"That is why I suggest that we tell module writers to not touch swing in
ModuleInstall.restored" - you mean we will tell them in documentation. Fine, but
again nothing stops modules to break things accidentally at any time.

"updater and licence check are different issue" - yes, and I hoped for solution
that would fix this problem as well. I remember Marek having significant
troubles when coding licence check. Isn't it really possible to turn our PLAF
module into somewhat else that would be called right at the time when system
realizes that it's going to use same GUI (Swing)? I can understand that this can
be overly complicated and not doable for this release, but this is the only way
how to fix UI startup correctly IMO.

Comment 13 mslama 2005-10-20 13:33:46 UTC
For those 'too early' dialogs we now use 'default' system L&F which is the same
as IDE L&F provided user does not change IDE L&F using --laf or otherwise. Not
difficult but not necessary the same as actual IDE L&F.
Comment 14 Jan Lahoda 2005-10-20 13:42:06 UTC
Along the same lines as Dafe's comment:
1. IMO, the patch itself does not solve this problem. It would only allow us to
solve the problem. All modules that do getMainWindow().addWindowListener() has
to be rewritten to fix this problem (java/project is not fixed by your patch).
2. I do not know about any reason for calling getMainWindow except adding the
listener. Is there any other valid reason? If no and this patch is applied, I
think we should issue a warning each time it is called.
3. IMO, the priorities (or some kind of order) may prove to be necessary.

It seems to me too that this patch solves a different problem and solves this
problem only as a side-effect (and does not enforce correct approach from the
modules).

(This does not mean that I think that invokeExclusively is very usefull, but
should be fine-tuned. BTW: maybe using it for autoupdate is not the correct
thing to do.)
Comment 15 Jan Becicka 2005-10-20 13:56:27 UTC
Adding java module to cc list. We register WindowListener in
JavaCoreModule.restored().
Comment 16 Jan Chalupa 2005-10-20 14:00:40 UTC
Interesting discussion, but please don't forget that it has been triggered by a
report of a problem encountered when using an *unsupported* LAF (sorry). If
anyone can reproduce a similar problem with any of the standard LAFs, that would
be a P2 bug. Until then -> P3.

I think we should definitely improve the NetBeans startup procedure, possibly by
introducing a new API, but not for NB 5.0, because the potential clients won't
be able to migrate to it anyway.
Comment 17 kirillcool 2005-10-20 14:09:15 UTC
About the "unsupported" - i have seen quite a few mentions of running NetBeans
under custom LAF (mainly JGoodies) over the past two years. As NetBeans *is* a
Swing application, there shouldn't be a distancing from them. Of course, this is
a question of priorities, but still. Continuing declarations of official lack of
support for third-party LAFs are not good. Why allow third-party plugins and not
third-party LAFs?
Comment 18 Jan Chalupa 2005-10-20 14:53:56 UTC
As you say, this is a matter of priority. Currently, the priority for the
NetBeans UI is to look as "native" as possible on all target platforms.
Third-party LAFs definitely aren't disallowed, we just don't put much effort
into testing they actually work. If bugs are filed and are easy to fix, they get
fixed. More complicated bug fixes may get postponed.

It's probably worth noting that NetBeans uses a couple of custom components that
are designed for the standard LAFs, but are likely to look a little out-of-place
with some 3rd-party LAFs.
Comment 19 kirillcool 2005-10-20 14:57:39 UTC
About custom components - it takes a little time, but it's quite possible to
provide consistent UI delegates for those ones. See [1]

[1] https://substance-netbeans.dev.java.net/
Comment 20 Jan Chalupa 2005-10-20 15:03:50 UTC
Very nice!
Comment 21 David Simonek 2005-11-01 16:33:10 UTC
Problem was fixed by Yarda (I don't know exact bug number) and I verified that
it works in todays build with Substance LF.

I also created new enhancement 67934 with a link to patch that Yarda wrote, to
not waste the work, because the idea of mentioned API is good and should be
integrated in future release. 
Comment 22 Marian Mirilovic 2006-01-17 15:26:26 UTC
without additional comments for long time - verified


By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo