No, though I forgot to replace usage of RadialGradientPaint with own implementation on JDK older than 6. I’ll check with JDK 5 all other usages of newer classes/methods and replace them.
My congrats Jazek!
I like your concepts regarding EDT, modal dialogs and AWT.
I’ve looked through the code a bit. I suppose that some other changes could be done like:
- Use Graphics2D instead of Graphics
- Action class could support better methods like e.g. setSmallIcon instead of putValue
Regards,
Maxim
Thanks
Yeah, that’s good idea. The worst case is that some backend implementation won’t implement some drawing methods, such as shapes. In that case, the user will probably create own LAF or use some which looks OK on his implementaton. Even the ModernLookAndFeel which is image-based (generated at runtime) needs some methods from Graphics2D (composite stuff).
Good idea, I’m looking forward to change the API to be more friendly like this or use enums instead of int keys where applicable.
Don’t accept compromises. We have already one toolkit with very long history of backward compatibility
Looks nice, except for the use continuations. I suspect most of you probably disagree, but I am uncomfortable with the concept. I love the readability advantages of of continuations but the resulting implementation is a no-no in my books. Anyway, just my 2 cents.
Thanks for feedback, can you elaborate more on why the resulting implementation is a no-no for you?
I would like more to not have introduce such non-standard concept to Java library, but it really solves a lot (the multiple threads for EDT is just mess in original AWT/Swing), in an ideal way IMHO. Well almost, you have to use bytecode modification library… if continuations would be part of JVM it would be just ideal and fully transparent.
The other way would be to have modal dialogs non-blocking and you would have to register to some event (which happens under the hood with continations usage). This would make the handlers using modal dialogs very fragmented IMHO.
I agree that it’s a good idea, but you keep the event queue right?
Various operations sometimes have to be sure they will be invoked only after the current ones, or need to wait and continue. I think modal dialogs replace the event queue for their effect of blocking, so your implementation doesn’t right?
Also i have a suggestion. For goods sake make the default abstract listeners and abstract actions (AbstractAction how i hate thee), not serializable by default.
Expecially AbstractAction.
I have explicit showModal() method which when called will simply show the modal dialog and suspend caller’s continuation. When the dialog is destroyed/hidden it will resume the continuation. So code contained in the continuation has nice linear structure, where you just show the dialog and then you can process the results. The event queue is the same and the processing of events always go through the main loop (good for single threadeness and especially for game loops).
AWT/Swing creates new EventQueue and pushes it on the stack of EventQueues (the queue on the top is doing the stuff), to stop the execution of code until dialog is destroyed/hidden it just created a new EDT thread and continues dispatching events there. It basically emulates continuations with threads… but that’s ugly and ineffecient and you have to care about EDT threads in your application.
There is another solution: just don’t have ability to wait for modal dialogs and use pure event mechanism. It’s true that other things in Swing are done this way, like doing async stuff. Though SwingWorker nicely wraps it. So the question is more like, should we use more continuation stuff to have nice linear code… or ditch them completely and use purely event based mechanism with fragmented event handlers within the same logical task?
Yeah, serialization ability of most AWT/Swing classes was huge mistake, I’ll recheck all the classes that are currently serializable in PureSwing and remove serialization from them when appropriate.
DP
There is another class of strange things - bugs - (solved?) by the event queue.
By bunny hopping.
This is an example:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4740914
In this case the problem comes from the (wrong?) use of the listener api internally, so the event comes to the user, that selects the text, then to the api, that clears it. The solution is to post a event to the end of the queue.
I’m myself seeing one of these, that the a JTextComponent Highlighter only affects the view the first time. if it is posted to the end of the eventqueue.
(Yes it is in the event queue).
But that is probably because i’m using the highlighter the first time while isShowing for the text component returns false (but isVisible and isValid return true).
You can try to use swingx as a baseline. The main maintainers seem to know most of their stuff.
Also can i direct your attention to this JFileChooser File Extension bug? I found the root cause independently myself, since it is very poorly explained.
http://bugs.sun.com/view_bug.do?bug_id=6612928
This is the bug that caused my serialization attempts while shutting down to fail before. JFileChooser uses an internal File subclass that closes it’s disposer (for some operations including writeObject apparently) with a shutdown hook, and i ran a serialization of those files during another shutdown hook -> Race -> exception sometimes.
I don’t know if it is possible or not, but it irritated me sometimes to have to use property change listeners to filter on named events when there was no logical (or just 1) parameter to pass into the listener from the observer controller.
Just a nitpick with the swing event system.
For example, I am told that the code will throw some magical exception that I may not catch or it will break continuations. The whole concept of continuations twisted the accepted workings of Threads. It’s a non-standard concept as you pointed out.
I suggest introducing the usage of Future and CompletionHandler instead. This will allow users to write sequential use-cases as you described without the kind of “magic” introduced by continuations. For code:
Future<?> f = fireSwingEvent();
f.get();
f = fireAnotherSwingEvent();
f.get();
// etc
This is essentially what you’re doing with continuations but it’s a lot more explicit and is still quite readable.
Gili
I’d like if JProgress bar exposed the animation function even if it was a no op some times:
The context is: The default way of painting Lists and Tables in swing is with cellrenderers where you update the way the cellrenderer models and then stamp the cellrenderer into a zone, however this won’t work well for any animations whose properties can’t be exposed, only started. I believe this is the case with JProgressBar. Setting setIndeterminate(true) on repeated passes of the cellrenderer for each model object will only display the first frame of the animation.
Right now i’m hacking a reflection on the JProgressBar ui to see if i can work around it in most look and feels.
Interesting issue. You can also put the JProgressBar directly to JTable and then it should update automatically itself. Though I’m not sure if it can be done official way or through some tracking of cell position and size. I was doing it with another component in past, but I don’t remember how I was exactly doing it (probably the latter method).
I’ll think about both issues and how to resolve them.
This code is running on own thread? Not sure what exactly it’s doing in relation to modal dialogs. Also I see that CompletionHandler is from Java 7, so would have to introduce own similar interface instead.
Anyway I’m not quite satisfied with current state so I will explore the possibilities of event based approach. Would be cleaner as no bytecode library would be required (and for just too little benefit in case of PureSwing) and would be in the same style with SwingWorker and other asynchronous approaches.
BTW i am discussing it here too:
http://forums.java.net/jive/thread.jspa?threadID=69467&tstart=0
Ignore the delegation idea for other lafs. I’m not being able to make it work (because the method i want is protected not default). I can use reflection but i am fighting the idea for now.
I’ve removed usage of continuations. I’ve resolved the modal dialog issue with Runnable callback in JDialog.showModal method. Also I’ve added this small interface:
public interface Receiver<T> {
public void receive(T value);
}
… that is used for returning value from modal dialogs. Here is an example:
JColorChooser.showDialog(button, "Choose a color", getColor(colorType), new Receiver<Color>() {
public void receive(Color c) {
if (c != null) {
setColor(colorType, c);
button.setIcon(new ColorIcon(c));
}
}
});
I think you should have a public accessible svn or git hub or something so people can see the code in their IDE easily.