Skip to main content

Painter Refactoring: Solving the Layering problem

39 replies [Last post]
Anonymous

I've discussed layering issues with Painters before, but we have yet
to actually solve the problem. I think it's time to finally attack
the problem head on. Rich and I have struggled to find what feels
like the *proper* solution and have come up with some ideas. However,
I don't want to put any pre-conceived notions in your heads so I'm
going to state the problem but not describe our solutions. My hope is
that others can provide some fresh insight to the problem.

What is the layering problem?

JXLabel, and other components which support Painters, allow the
developer to draw into the component with one or more Painters. But
where does the drawing go? Is the painter below or above the normal
painting of the component? What if the component has a background
(like JXPanel). Should the painting replace that drawing or augment
it? What if I want to add a painter on top of a component completely
to produce an overlay? What if I want to draw something between the
component's foreground and background? Will that even work on a
component with a native look and feel? And what about combining
painters? Should I be able to replace and/or augment any painters
already on the component, even if I don't know about them? And how
does setOpaque() affect things?

So you can begin to see how layering introduces lots of complicated
questions that don't have good answers. And we must also couple this
with the need to keep the API simple. It's okay to not enable every
possible behavior. If it comes down to it a developer can just
subclass if they want to.

So I think the solution must enable the following behavior. Can we
come up with a solution that does these things while still simple and
performant.

* Replace the background of a panel with custom drawing, allowing
content from below to shine through

* Add a dropshadow to the text of a label

* Change the background of a button to a translucent blue rounded
rectangle

* Add a glow underneath the text of a button when rolled over

* use a stack of painters as the icon for a JLabel

* Add a small translucent icon on top of a textfield to indicate it
is invalid

* Add a translucent red gradient over invalid textfields that already
have the previous effect

I think that's enough to get us started. So what do you think? Is
this all possible?

- Josh

- Blasting forth in three part harmony!

[att1.html]

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Joshua Marinacci

Painters are meant to replace the common practice of overriding the
paintComponent() method on common components. They are not meant to
replace the entire look and feel of an application. For that you
should use the Synth Look and Feel, which does define a painter like
interface for every part of every component, enabling you to create a
completely custom look and feel. Painters are for cases where the
developer just wants to change a few things easily (which it turns
out is far more common than needing an entire look and feel). I like
some of the ideas you have presented, but they should be made as
enhancements to the Synth look and feel, not changes to Painters.

- Josh

On Nov 7, 2006, at 10:48 AM, jdnc-interest@javadesktop.org wrote:

> A heck?
> Let's see practically. I think setting the l&f can be done through
> a static method in an util. For example
> javax.swing.plaf.painter.Util.installPainter( ), which would get
> the name of current l&f, uninstall it, setup the l&f as a sub of
> this one, and finally install itself as a l&f.
> One method.
> Then, to put a painter into the instance of a component,
> myComponentInstance.setClientProperty( myPainterStack ), one method
> also, but this one was also necessary using the proposed
> implementation. So, what's more? An util class with two methods
> (one to install, one to switch the sub l&f). I would certainly not
> call that 'a heck'. Or maybe i overlooked things, in which case i
> would be thankfull for some detailed information.
>
> The advantages are:
> - no need to make any l&f painter aware.
> - nothing to change to platform
> - possibility to create real and complete looks (almost for free,
> code wise) using the exact same methods and tools that are used to
> create painters.
> Those three advantages are, to me, huge drawbacks to current proposal.
>
> The only drawback i see using a painterl&f is that if the coder
> changes the l&f directly, instead of using the util class to change
> the sub-l&f, it will disable painters rendering. Is it that big? i
> don't think so as it can also have advantages. Forcing the default
> l&f for an application will make it painter aware, whatever the
> version of the platform, whatever the version of the program.
> [Message sent by forum member 'pepe' (pepe)]
>
> http://forums.java.net/jive/thread.jspa?messageID=171087
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

- Blasting forth in three part harmony!

[att1.html]

pepe
Offline
Joined: 2003-06-10

>Painters are meant to replace the common practice of >overriding the
>paintComponent() method on common components. They are not >meant to
>replace the entire look and feel of an application.
We agree on that, but it looks that i am not able to express it correctly.
Now that i vented -or at least tried- my thoughts and fears, i will now step aside, not too far, and watch it grow.

--------------------------------------------------------
>Animating swing<
https://swash.dev.java.net

Joshua Marinacci

Hi Pepe. I'm not sure what you are proposing. The L&F does not
contain enough information to allow everything that Painters do
because they are global. In addition, for simple things, they are
complicated to work with and overkill. What would you suggest as an
alternative to Painters?

- Josh

On Nov 4, 2006, at 3:54 PM, jdnc-interest@javadesktop.org wrote:

> Normally, one would not replace a whole painting, but let's face
> it. Most, if not all demonstrations of painters in 'real situation'
> only do one thing: totally replace a look.
> If even the creators of painters do the opposite of what they claim
> to be an extreme use, guiding the programmers to that path will
> lead to the same situation. I believe that doing so will only
> comfort newcomers and unaware people in the idea that painters are
> a valid path to skin an application. This is wrong, unwanted and
> dangerous, but i can't stop thinking that people will screw
> anything they can and i believe this is something that will be used
> in a very bad way. Not only i see that as a very bad middle and
> long term problem to swing, but i think it can also spread on java,
> just like the swing slowness myth still does.
>
> Of course, you could argue that this is an extreme example, and
> that people could be teached not to go there. This is a normal
> argument, but i unfortunatly don't believe it will work: most
> people only mimic what they see.
> On an other hand, we yet have to see use cases where painters are
> used as described, just to change something to some components.
> Even if Romain, Scott and Shannon 's extreme (brilliant) GUI
> makeover 2006 start gently in that field, they end in the l&f rapidly.
>
> Moreover, replacing a look from a feel will lead to
> unsynchronization of both. Applications will not respond
> graphically to the input as they ought to, and will not show what
> they ought to. This not only true for sdk, but also for l&f. You
> will enter the SWT path, holding lists of special cases depending
> on skin, jdk, ...
>
> But, i heard the complaint. One of your most heard argument is that
> l&f are hard to produce and people need an easy way to change
> things in their apps painlessly. If l&f are hard to produce, i
> think it's because of the lack of tools. I would certainly not
> create a jsf website with notepad, why would that be a reason to
> start something else? With proper tool, jsf is a great thing to
> use. L&f must do the same.
> I repeat: all the justifications that are shown for painters are
> instead the work of l&f, even Aerith.
>
> One other thing bothers me a lot with the current path taken. I
> read that JComponent could be changed to enable painters. I believe
> that a l&f is enough to handle them -and should soon try it-
> (crossing fingers here).
>
> Don't misunterpret me, i'm fond of your work and i am looking for
> the same goal as you. I am not questionning on the goal, but the
> mean and the way to use and show it.
> What i read and see are two very different things, which make me
> think that there are two goals being incorrectly matched.
> [Message sent by forum member 'pepe' (pepe)]
>
> http://forums.java.net/jive/thread.jspa?messageID=170333
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

- Blasting forth in three part harmony!

[att1.html]

pepe
Offline
Joined: 2003-06-10

Hello.

I have already explained a bit of my thought in an other thread. As i said, this is something i planned for myself and swash, but i unfortunatly did not have time to implement so there might be a showstopper that i did not see. (although i'm 99% confident it would work, the 1% comes from the fact i did not implement yet)
Let us make assumptions. Let us prepare a l&f and call it painterl&f (now called plf...).
The plf works a bit like the multiplex l&f in the way that it holds a reference to an other look and feel. That sub-l&f could be set through an utility class and changed anytime. Setting the sub-l&f would be done by plf just as the normal installation does, and plf would store the ComponentUIs for each component that needs to have delegation.
While delegates are called globally, calls to delegate paint() also reference the instance of the JComponent to be painted. This gives us a chance to check the instance for special handling. Within the paint() delegate, the role of the plf would be to act before, after or (and i am still against that) in place of the normal sub-paint() delegate.
Now, set the plf as look and feel to your program. Set the plf sub-l&f to metal. Let us take a button, which we want to change painting very locally, that is for an instance only. Add a Painter/PainterHandler/PainterWhatever to the instance (I will not actually describe the storage mechanism, i will discuss this later) and set its parameters so that it does what you want.
When the button has to be painted, the delegate is called, which ought to be the plf. Plf checks the button instance for painter, and finds it. As the painter has been set to replace completely the paint delegation for the sub-l&f, the painter does its job, without the l&f (metal, in our case) being called. If the painter was set to be foreground, it would have been drawn after a call to the metal l&f delegate, thus, over it. Calls to plf for painting other components would paint the metal l&f, as no painter would be found within the JComponent instances.
Theoratically (that is, if i did not omit anything), this system can work to implement painters in every versions of swing without modifying anything. No need to make other l&f painter aware.

I did mention, but not explain, how i would see the painter included in the JComponent. Personally, i would use the set/getClientProperty(). It is done for that, as painting would be a property of the button. One could worry about performance of making a getProperty each time we would draw a component, but i believe that if this ever becomes a bottleneck, we would have other things to worry about. Moreover, we would benefit from the property listeners.

There is, imho a great advantage in going in this direction. Using the same tools -painters and utilities to handle them-, we can also provide easy skinning. Setting a painter stack to the various ComponentUI could anihilate the rendering for sub-l&f for all instances, independently of the instance painters, which could come before/after/in place of that painter stack.

I truely hope i could explain clearly what i have in mind, just as i hope what i thought can be done practically.

I will not propose a replacement for painters. Your sentence is weird and i hope you do not think i am here to bash painters in favor of swash. While the two API are close in their goal, i believe they can feed each other. I do not want to compete, i do not want to waste time and energy. Someone here can confirm this, as i already discussed this point via mail, months ago.
Swash will support display through painters, i would be stupid not to, but for nothing in the world i would want to duplicate your effort. I see no reasons why.

Romain GUY

I must admit that reading this shortly after waking up, I can't see
the advantage over the current Painter proposal. On the contrary I
can see one major drawback: it's a heck more complicated to use.

On 7 nov. 06, at 08:41, jdnc-interest@javadesktop.org wrote:

> Hello.
>
> I have already explained a bit of my thought in an other thread. As
> i said, this is something i planned for myself and swash, but i
> unfortunatly did not have time to implement so there might be a
> showstopper that i did not see. (although i'm 99% confident it
> would work, the 1% comes from the fact i did not implement yet)
> Let us make assumptions. Let us prepare a l&f and call it
> painterl&f (now called plf...).
> The plf works a bit like the multiplex l&f in the way that it holds
> a reference to an other look and feel. That sub-l&f could be set
> through an utility class and changed anytime. Setting the sub-l&f
> would be done by plf just as the normal installation does, and plf
> would store the ComponentUIs for each component that needs to have
> delegation.
> While delegates are called globally, calls to delegate paint() also
> reference the instance of the JComponent to be painted. This gives
> us a chance to check the instance for special handling. Within the
> paint() delegate, the role of the plf would be to act before, after
> or (and i am still against that) in place of the normal sub-paint()
> delegate.
> Now, set the plf as look and feel to your program. Set the plf sub-
> l&f to metal. Let us take a button, which we want to change
> painting very locally, that is for an instance only. Add a Painter/
> PainterHandler/PainterWhatever to the instance (I will not actually
> describe the storage mechanism, i will discuss this later) and set
> its parameters so that it does what you want.
> When the button has to be painted, the delegate is called, which
> ought to be the plf. Plf checks the button instance for painter,
> and finds it. As the painter has been set to replace completely the
> paint delegation for the sub-l&f, the painter does its job, without
> the l&f (metal, in our case) being called. If the painter was set
> to be foreground, it would have been drawn after a call to the
> metal l&f delegate, thus, over it. Calls to plf for painting other
> components would paint the metal l&f, as no painter would be found
> within the JComponent instances.
> Theoratically (that is, if i did not omit anything), this system
> can work to implement painters in every versions of swing without
> modifying anything. No need to make other l&f painter aware.
>
> I did mention, but not explain, how i would see the painter
> included in the JComponent. Personally, i would use the set/
> getClientProperty(). It is done for that, as painting would be a
> property of the button. One could worry about performance of making
> a getProperty each time we would draw a component, but i believe
> that if this ever becomes a bottleneck, we would have other things
> to worry about. Moreover, we would benefit from the property
> listeners.
>
> There is, imho a great advantage in going in this direction. Using
> the same tools -painters and utilities to handle them-, we can also
> provide easy skinning. Setting a painter stack to the various
> ComponentUI could anihilate the rendering for sub-l&f for all
> instances, independently of the instance painters, which could come
> before/after/in place of that painter stack.
>
> I truely hope i could explain clearly what i have in mind, just as
> i hope what i thought can be done practically.
>
> I will not propose a replacement for painters. Your sentence is
> weird and i hope you do not think i am here to bash painters in
> favor of swash. While the two API are close in their goal, i
> believe they can feed each other. I do not want to compete, i do
> not want to waste time and energy. Someone here can confirm this,
> as i already discussed this point via mail, months ago.
> Swash will support display through painters, i would be stupid not
> to, but for nothing in the world i would want to duplicate your
> effort. I see no reasons why.
> [Message sent by forum member 'pepe' (pepe)]
>
> http://forums.java.net/jive/thread.jspa?messageID=171059
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
>

--
Romain GUY
http://jroller.com/page/gfx
http://www.progx.org

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

pepe
Offline
Joined: 2003-06-10

A heck?
Let's see practically. I think setting the l&f can be done through a static method in an util. For example javax.swing.plaf.painter.Util.installPainter( ), which would get the name of current l&f, uninstall it, setup the l&f as a sub of this one, and finally install itself as a l&f.
One method.
Then, to put a painter into the instance of a component, myComponentInstance.setClientProperty( (something to be decided so that painter can be retrieved, like a Painter.ForeGround class), myPainterStack ), one method also, but this one was also necessary using the proposed implementation. So, what's more? An util class with two methods (one to install, one to switch the sub l&f). I would certainly not call that 'a heck'. Or maybe i overlooked things, in which case i would be thankfull for some detailed information.

The advantages are:
- no need to make any l&f painter aware.
- nothing to change to platform
- possibility to create real and complete looks (almost for free, code wise) using the exact same methods and tools that are used to create painters.
Those three advantages are, to me, huge drawbacks to current proposal.

The only drawback i see using a painterl&f is that if the coder changes the l&f directly, instead of using the util class to change the sub-l&f, it will disable painters rendering. Is it that big? i don't think so as it can also have advantages. Forcing the default l&f for an application will make it painter aware, whatever the version of the platform, whatever the version of the program.

Message was edited by: pepe

Romain Guy

>Let's see practically. I think setting the l&f can be done through a static method in an util. For example javax.swing.plaf.painter.Util.installPainter( ), which would get the name of current l&f, uninstall it, setup the l&f as a sub of this one, and finally install itself as a l&f.
>One method.
>Then, to put a painter into the instance of a component, myComponentInstance.setClientProperty( myPainterStack ), one method also, but this one was also necessary using the proposed implementation. So, what's more? An util class with two methods (one to install, one to switch the sub l&f). I would certainly not call that 'a heck'. Or maybe i overlooked things, in which case i would be thankfull for some detailed information.

Setting a client property is to me much more confusing than simply calling setPainter() or addPainter(). Swing is complicated enough already.

>The advantages are:
>- no need to make any l&f painter aware.

Current proposal does not require the look and feel to be painter aware either.

>- nothing to change to platform

That is a good point indeed.

>- possibility to create real and complete looks (almost for free, code wise) using the exact same methods and tools that are used to create painters.

I doubt you could really implement a whole look just with painter. Most components have very complicated painting code paths and require more than a painter to be precisely skinned. Think of a toolbar. You would end up with a painter for the arrow buttons, a painter for the thumb, a painter for the track and the need to check the scrollbar properties at painting time (is the arrow button or the thumb pressed for instance?) And guess what, you just recreated the UI delegates.

>The only drawback i see using a painterl&f is that if the coder changes the l&f directly, instead of using the util class to change the sub-l&f, it will disable painters rendering. Is it that big? i don't think so as it can also have advantages. Forcing the default l&f for an application will make it painter aware, whatever the version of the platform, whatever the version of the program.

You are looking for a solution that painters are not trying to address. As I said, painters are meant to let developers easily assemble building blocks to customize the look one of one component here and there. It does not intend to be as versatile as the UI delegates.

--
Romain Guy
http://www.progx.org
http://jroller.com/page/gfx
http://www.jext.org

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

pepe
Offline
Joined: 2003-06-10

Being able to make looks is a possibility, not a feature. ([edit] i mean, it was not done for that )
Moreover, the complexity is already starting to come over. Josh has already been talking about multiple sets of painters depending on selection state, eventually complexifying the API some more, and here trying to overlap with delegation.

That could be sorted by the properties too. Set a stack for selected painters, set or not one for the unselected/disabled ones. Using the key, you could directly indicate what stack belongs to what state. If the painterl&f finds the stacks related to state, it would use them, otherwise it would use the default one. Less code, less methods, less hassle for the user.
I do not believe going through properties would be messy. It ought to be the most appropriate mechanism, as painters would be properties of the instance. Once the principle is edicted, i think it is fine. I do not see it counter-intuitive.

Message was edited by: pepe

Joshua Marinacci

I must say that I disagree. The whole point of painters is to easily
override the default look of a particular instance of a component. I
want to make a way for the painters to conditionally override just
portions of the look and feel, but that may not be possible. In any
case, this usage is up to the developer of an application which uses
painters. I hope this API will allow developers to make really good
looking applications very quickly.

- Josh

On Nov 3, 2006, at 8:29 AM, jdnc-interest@javadesktop.org wrote:

> Hello
> I have been reading the post many times and in the painters,
> something really chocks me a lot. Totally bypassing the running
> 'look' is something that painters should not be able to do. This
> single point invalidates the whole painter mechanism to me.
> So, my response to your question is 'no, it is certainly not
> reasonnable, even not desirable'.
>
> While the goal of providing pluggable, extendable renderers over
> the components is necessary, i really think that the specification
> is heading a wrong way.
> [Message sent by forum member 'pepe' (pepe)]
>
> http://forums.java.net/jive/thread.jspa?messageID=169966
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

- Blasting forth in three part harmony!

[att1.html]

Romain GUY

Josh explained it very quickly. The whole point of the painters is to
let developers create custom looks without having to sublcass
components and/or create a new look and feel.

Aerith is a good example of application that could have been much
easier to write if we had used only painted instead of subclassing a
bunch of Swing components and creating new UI delegates.

On 4 nov. 06, at 00:11, Joshua Marinacci wrote:

> I must say that I disagree. The whole point of painters is to
> easily override the default look of a particular instance of a
> component. I want to make a way for the painters to conditionally
> override just portions of the look and feel, but that may not be
> possible. In any case, this usage is up to the developer of an
> application which uses painters. I hope this API will allow
> developers to make really good looking applications very quickly.
>
> - Josh
>
>
> On Nov 3, 2006, at 8:29 AM, jdnc-interest@javadesktop.org wrote:
>
>> Hello
>> I have been reading the post many times and in the painters,
>> something really chocks me a lot. Totally bypassing the running
>> 'look' is something that painters should not be able to do. This
>> single point invalidates the whole painter mechanism to me.
>> So, my response to your question is 'no, it is certainly not
>> reasonnable, even not desirable'.
>>
>> While the goal of providing pluggable, extendable renderers over
>> the components is necessary, i really think that the specification
>> is heading a wrong way.
>> [Message sent by forum member 'pepe' (pepe)]
>>
>> http://forums.java.net/jive/thread.jspa?messageID=169966
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
>> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
>
> - Blasting forth in three part harmony!
>
>

--
Romain GUY
http://jroller.com/page/gfx
http://www.progx.org

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Patrick Wright

Hi

Weighing in: I think many of us will be concerned that Painters won't
"play well with" look and feels, or UI delegates, that are not
Painter-aware. But as Josh and Richard have pointed out, Painters
bypass the need, in many cases, to subclass a component for special
paint handling, which is a big plus. I think there's a range of
application behavior with respect to painting and look and feel:

1) Application LnF can be changed at any time, to the user's liking
2) Application LnF can be changed, choosing from a set of LnFs that
have been tested
3) Application controls UI fully, with all sorts of neat graphics
effects, and LnF should not be changed, or only changed via theming,
not via LnF. Think of a music player with a funky UI.

I think we should allow for all these possibilites--I realize some
people will only want (1), but on the other hand, since you can
subclass and change painting behavior anyway (and see Swing Hacks for
cool examples), why not make it easier with Painters?

Regards
Patrick

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

rbair
Offline
Joined: 2003-07-08

Hey Josh-in-prague

> > How is using a LayeredPainter any simpler than
> letting the
> > component manage the layers, from the developer's
> point of view? Or
> > the API?
>
> It is simpler because it pushes the more complex use
> cases out to a
> new object. I'm not sold on this and willing to be
> convinced
> otherwise, however. :)

I don't understand what you mean by "more complex use cases out to a new object"? At times like this, it's nice to have a whiteboard :-)

> >> 2) It minimizes the extra work needed to be done
> by
> >> components which
> >> want to support painters. They can delegate
> >> everything to the
> >> LayerPainter. Think PropertyChangeSupport.
> >
> > That's definitely true, but it doesn't mean you
> can't have a
> > PainterSupport class which does the same. In Swing
> core, this would
> > be rolled into JComponent, so this argument doesn't
> really make
> > sense once dealt with in core.
>
> True. But don't we have too many methods on
> JComponent already? Do
> we want to add more? Is this the same reason we have
> a getUI method
> on JComponent?

I'm not seeing the link between this and the getUI method on JComponent. Yes, you always have to be a bit leery of adding too many new methods anywhere in the API, but I think in this case JComponent is where it belongs.

> In a theoretical future where we can
> actually separate
> the delegate painting into pieces then we could
> either split
> COMPONENT into multiple levels (COMPONENT_BACKGROUND
> &
> COMPONENT_FOREGROUND), or else forward the
> comp.setBackgroundPainter
> () and comp.setForegroundPainter() calls onto the
> delegate and let
> them handle it.

I'd vote for the first approach, because it is the same logic and reasoning that we use currently with the background/foreground color.

Cheers
Richard

PS> Still waiting for the new photos
PPS> Congrats on getting engaged!

joshy
Offline
Joined: 2003-07-02

Gah. Apparently the form-mailinglist link is broken again. That explains why it's been so quiet lately. :) This is what I mailed earlier:

Okay. I'm settled in Prague now and on a decent network connection finally. Much happier!

On Oct 30, 2006, at 6:36 PM, jdnc-interest@javadesktop.org wrote:

Interesting. That does solve the bean problem, but then it's putting
ordering into the painters rather than the thing that contains them.
Should painters even be aware of their order? Or does this int
represent their 'preferred layer', which the container can choose to
ignore if desired?

It feels like I have tricked you into admitting that we need a better JavaBean spec regarding indexed (collection) properties doesn't it? ;)

This solution is a trade of because the lacking spec i guess.

We (in Mig Calendar) actually have both the getter and setter of the index in the interface. This means that the painter is just managing the value of the index, not producing it. It is not the best of solutions but, and sorry for the coming volume, WE NEED COLLECTION PROPERTIES WITH A COLLECTION AWARE STANDARD PROVIDED PROPERTY EDITOR. So there. It's out of my system.

You won't get any disagreement from me. We do need collection properties and property editors. I can build such a thing easily enough to use for our own apps (and in NB) but that doesn't solve the problem that we don't have a collection class which will actually do what we need. It will only work if the store the layer value on the thing to be sorted, rather than on the collection. We can build a custom collection to do this as well, of course, but I fear we are going beyond the scope of this problem.

I have been haunting Richard with this on the JSR-273 expert list as well but it's really hard to convince people without making an enormous effort to explain why and in what situations something is needed. These kind of things are so abstract that if they haven't bitten by it they won't know about them and will have a hard time understanding that they can't be worked around in a good way.

Agreed.

Last night I did more work on painters and I've come up with some new problems. I built a PainterTableCellRenderer that takes four painters. Fore and Back for normal cells and Fore and Back for the selected cells. You can then use a second instance to handle table headers, though it's more cumbersome to install (because of the way tables work, not because of painters). This is the problem I've come up with:

The PainterTableCellRenderer essentially has two stacks of painters. One for normal cells and one for selected cells. If we put the LayeredPainter methods into the renderer itself then it means we now have twice the number of methods than before, which really adds a lot to this renderer. Also, there's no way to make this Iterable aware because we can't have the renderer implement iterable twice.

Working on this renderer has highlighted some possible problems with the way we handle the standard component drawing. If we have fore and back layers around the component layer. Then setting the background layer will behave as expected. However, setting the fore layer will be *on top* of the text. Thus if you set a textpainter for the foreground you get text twice. Sure you could set the component layer directly, but this is becoming very counter-intuitive.

I set up the component layer the way I did because I assumed that we didn't want to change the opacity and that we couldn't split the fore and back layers. In practice, however, we often can. The default renderers are simply labels so we don't need to worry about the background. A panel has no foreground, so there's nothing to split. Buttons have both a fore and background, and setting even the background color is ill-defined in core. However, we can remove the background if we wish to using the contentFilled property. Thus we don't have a solution that works for every component, but we could do something that works for most component. There would be some custom work underneath but I think we could keep that hidden for most cases. For custom components they had to go out of their way to support painters so it can be assumed that they will find a way to support splitting the fore and background.

Thus I wish to amend my proposed solution:

* Change LayeredPainter to PainterSet or something more indicative of the fact that it's not strictly a painter anymore.
* Make LayeredPainter be iterable and fit common collections patterns (make it a real collection if we can, a special list subclass?)
* Build a property editor to support this.
* Make fore and back properties be special cases of the general case
* Remove the component layer. We will have back, fore, and overlay as the standard layers. (Do we need an underlay? Border?)
* Back will replace the standard background on supported components. Whatever changing the foreground color would affect.
* Fore will replace the standard foreground. Usually the text. Whatever changing the foreground color would affect.
* On components where we can't split the fore and back then the fore painter will replace all drawing.

Does this sound reasonable?

- Josh

pepe
Offline
Joined: 2003-06-10

Hello
I have been reading the post many times and in the painters, something really chocks me a lot. Totally bypassing the running 'look' is something that painters should not be able to do. This single point invalidates the whole painter mechanism to me.
So, my response to your question is 'no, it is certainly not reasonnable, even not desirable'.

While the goal of providing pluggable, extendable renderers over the components is necessary, i really think that the specification is heading a wrong way.

mikaelgrev
Offline
Joined: 2006-09-27

> Totally bypassing the running 'look' is something that painters should not be able to do.

Pepe, normally you wouldn't replace the whole painting of the widget but it is nice to be able to. Then you can replace the paintings without sub classing. Also you can do other really neat stuff like caching complex widgets as images, blur them (by rendering to your own back buffer and blur and paint that image) or correct them if they render improperly on a specific paltform or something. It gives very good flexibility.

There is no reason to block this option, though for 99% of the cases you wouldn't replace the original L&F painting.

Cheers,

pepe
Offline
Joined: 2003-06-10

Normally, one would not replace a whole painting, but let's face it. Most, if not all demonstrations of painters in 'real situation' only do one thing: totally replace a look.
If even the creators of painters do the opposite of what they claim to be an extreme use, guiding the programmers to that path will lead to the same situation. I believe that doing so will only comfort newcomers and unaware people in the idea that painters are a valid path to skin an application. This is wrong, unwanted and dangerous, but i can't stop thinking that people will screw anything they can and i believe this is something that will be used in a very bad way. Not only i see that as a very bad middle and long term problem to swing, but i think it can also spread on java, just like the swing slowness myth still does.

Of course, you could argue that this is an extreme example, and that people could be teached not to go there. This is a normal argument, but i unfortunatly don't believe it will work: most people only mimic what they see.
On an other hand, we yet have to see use cases where painters are used as described, just to change something to some components. Even if Romain, Scott and Shannon 's extreme (brilliant) GUI makeover 2006 start gently in that field, they end in the l&f rapidly.

Moreover, replacing a look from a feel will lead to unsynchronization of both. Applications will not respond graphically to the input as they ought to, and will not show what they ought to. This not only true for sdk, but also for l&f. You will enter the SWT path, holding lists of special cases depending on skin, jdk, ...

But, i heard the complaint. One of your most heard argument is that l&f are hard to produce and people need an easy way to change things in their apps painlessly. If l&f are hard to produce, i think it's because of the lack of tools. I would certainly not create a jsf website with notepad, why would that be a reason to start something else? With proper tool, jsf is a great thing to use. L&f must do the same.
I repeat: all the justifications that are shown for painters are instead the work of l&f, even Aerith.

One other thing bothers me a lot with the current path taken. I read that JComponent could be changed to enable painters. I believe that a l&f is enough to handle them -and should soon try it-(crossing fingers here).

Don't misunterpret me, i'm fond of your work and i am looking for the same goal as you. I am not questionning on the goal, but the mean and the way to use and show it.
What i read and see are two very different things, which make me think that there are two goals being incorrectly matched.

Romain GUY

> I believe that doing so will only comfort newcomers and unaware
> people in the idea that painters are a valid path to skin an
> application. This is wrong, unwanted and dangerous

Why is it so? I spend most of my time customizing Swing components
and painters are definitely the cleanest and easiest way I have found
so far.

They not only let you change the painting of existing components but
also easily create brand new components from scratch, without having
to work too much on the logic.

One of the driving forces behind painters was that we wanted to be
able to quickly produce new components without having to write much
code, nor drawing pictures in Photoshop. With painters and a painter
editor, I can create nice-looking, highly customized components in a
matter of minutes. Why would I want to go another way?

Besides, most of the examples shown for painters are extreme because
it's the best way to demonstrate their power. But I can think of
several cases where painters can be useful in a less extreme way. For
instance when you want to add a gradient in a JPanel. Why should I
subclass JPanel and override paintComponent() when I can simply plug
a painter?

It's all about ease of use. Sure, we can do all this in the LaF but
it's too much work and tools would not really help here (aside from
putting painters in the LaF, but then what happens when you use a LaF
that does not support painters?) Painters *are* the tools meant to
make LaF (well, just Look really) easier to write and *reuse*.
Contrary to existing look and feel, painters are meant to be building
blocks that you connect together to achieve the desired effect.

Last but not least, technologies like Microsoft's WPF do let people
do pretty much anything they want (like putting 3D scenes in a popup
menu, or add reflections everywhere in a few seconds.) I am afraid of
what people will do with this but if Java wants to remain relevant,
it has to be on par with other technologies.

--
Romain GUY
http://jroller.com/page/gfx
http://www.progx.org

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Joshua Marinacci

On Oct 25, 2006, at 11:05 PM, jdnc-interest@javadesktop.org wrote:

>> 1) it keeps the new API simple for the simple case.
>> You can set the
>> fore and background painters easily, or replace the
>> entire painter
>> stack easily. The more complicated parts are
>> delgated to a sub-
>> object, much the way Swing components often delegate
>> to a model.
>
> How is using a LayeredPainter any simpler than letting the
> component manage the layers, from the developer's point of view? Or
> the API?

It is simpler because it pushes the more complex use cases out to a
new object. I'm not sold on this and willing to be convinced
otherwise, however. :)

>
>> 2) It minimizes the extra work needed to be done by
>> components which
>> want to support painters. They can delegate
>> everything to the
>> LayerPainter. Think PropertyChangeSupport.
>
> That's definitely true, but it doesn't mean you can't have a
> PainterSupport class which does the same. In Swing core, this would
> be rolled into JComponent, so this argument doesn't really make
> sense once dealt with in core.

True. But don't we have too many methods on JComponent already? Do
we want to add more? Is this the same reason we have a getUI method
on JComponent?

>> 3) Since iterative painting is needed in
>> CompoundPainter anyway, this
>> lets us reduce duplicated code. I think
>> CompoundPainter and
>> LayerPainter should be sub-super classed together, or
>> else just
>> combined into one.
>
> Yes, but truly it isn't much duplicated. We aren't talking 100
> lines of code here, right?

True. Not much.

>
>> Oh, and in your example below you wouldn't have to
>> cast. It would be
>> like this:
>>
>> panel.getLayerPainter().add(otherPainter, 20);
>
> Do we really want the Component level API to be tied to
> LayerPainter as opposed to Painter? How does Layer(ed)Painter mix
> with Swing, when Painters are used as part of the UI delegate (ie:
> when the UI delegates are made aware of Painters and segregate
> their painting into background, foreground, text, etc painting
> layers)?

The dependency on LayerPainter in the component level API is the
sticking point for me. I really don't like it but I don't see any
other way to keep the additional 10 methods or so out of the component.

As far as working with the UI delegate. Right now we can't do it. I'm
assuming that the painter at the COMPONENT level will just call
comp.paintComponent(), which will eventually call the UI delegate's
paint method. In a theoretical future where we can actually separate
the delegate painting into pieces then we could either split
COMPONENT into multiple levels (COMPONENT_BACKGROUND &
COMPONENT_FOREGROUND), or else forward the comp.setBackgroundPainter
() and comp.setForegroundPainter() calls onto the delegate and let
them handle it. Perhaps we should define that the COMPONENT layer
can be preloaded with multiple painters, so developer code shouldn't
assume that there is only one COMPONENT layer.

>
> I think you want to have the layers on the component level.

K. I'm not strong one way or the other. Neither grabs me as
particularly good, so I'm willing to go with whatever the consensus is.

- Josh

>
> Richard
> [Message sent by forum member 'rbair' (rbair)]
>
> http://forums.java.net/jive/thread.jspa?messageID=167131
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

- Blasting forth in three part harmony!

[att1.html]

mikaelgrev
Offline
Joined: 2006-09-27

> It is simpler because it pushes the more complex use
> cases out to a
> new object. I'm not sold on this and willing to be
> convinced
> otherwise, however. :)

Today many (most?) work with API like this:
comp.[CTRL+SPACE]set[choose between the setters] (bs)(bs)(bs)add[choose between the adders]..Ok. Can't be done.

Get what I mean?

> True. But don't we have too many methods on
> JComponent already? Do
> we want to add more? Is this the same reason we have
> a getUI method
> on JComponent?

This is because of an earlier bad call (IMO). That shouldn't make this, as I see it, very important feature lack functionality.

> K. I'm not strong one way or the other. Neither grabs
> me as
> particularly good, so I'm willing to go with whatever
> the consensus is.

Same for me. The only solution that passes my -don't put shit in the core- threshold is to think about how we (as in Sun now) should handle these kind of situations more generally, i.e. fix the JavaBean spec to include this functionality and model the solution around that new spec. (Now I guess this collection property thing from me is border line harassment... ;)

Cheers,
Mikael

rbair
Offline
Joined: 2003-07-08

> 1) it keeps the new API simple for the simple case.
> You can set the
> fore and background painters easily, or replace the
> entire painter
> stack easily. The more complicated parts are
> delgated to a sub-
> object, much the way Swing components often delegate
> to a model.

How is using a LayeredPainter any simpler than letting the component manage the layers, from the developer's point of view? Or the API?

> 2) It minimizes the extra work needed to be done by
> components which
> want to support painters. They can delegate
> everything to the
> LayerPainter. Think PropertyChangeSupport.

That's definitely true, but it doesn't mean you can't have a PainterSupport class which does the same. In Swing core, this would be rolled into JComponent, so this argument doesn't really make sense once dealt with in core.

> 3) Since iterative painting is needed in
> CompoundPainter anyway, this
> lets us reduce duplicated code. I think
> CompoundPainter and
> LayerPainter should be sub-super classed together, or
> else just
> combined into one.

Yes, but truly it isn't much duplicated. We aren't talking 100 lines of code here, right?

> Oh, and in your example below you wouldn't have to
> cast. It would be
> like this:
>
> panel.getLayerPainter().add(otherPainter, 20);

Do we really want the Component level API to be tied to LayerPainter as opposed to Painter? How does Layer(ed)Painter mix with Swing, when Painters are used as part of the UI delegate (ie: when the UI delegates are made aware of Painters and segregate their painting into background, foreground, text, etc painting layers)?

I think you want to have the layers on the component level.

Richard

mikaelgrev
Offline
Joined: 2006-09-27

I'm with Richard here. I think the concept that painters are layerable is easier to to grasp for a newbie than that there are a simple Painter and the use of a special Collection-aware painter to layer painters. IMO.

Also, our painter actually has the a getLayerIndex() its interface. That way they always have a natural ordering and the layer won't be lost of a list of painters is passed around. We even have them implement Comparable so they can be put in a TreeSet directly and the AbstractPainter handles the implementation of that. Not sure if that would fit here though.

Cheers,
Mikael

Joshua Marinacci

On Oct 25, 2006, at 11:40 PM, jdnc-interest@javadesktop.org wrote:

> I'm with Richard here. I think the concept that painters are
> layerable is easier to to grasp for a newbie thatn the simple
> Painter and the use of a special Collection aware painter to layer
> painters. IMO.
>
> Also, our painters actually has the a getLayerIndex() its
> interface. that way they always have a natural ordering and the
> layer won't be lost of a list of painters is passed around. We even
> have them implement Comparable so they can be put in a TreeSet
> directly and the AbstractPainter handles the implementation of
> that. Not sure if that would fit here though.

Interesting. That does solve the bean problem, but then it's putting
ordering into the painters rather than the thing that contains them.
Should painters even be aware of their order? Or does this int
represent their 'preferred layer', which the container can choose to
ignore if desired?

- J

>
> Cheers,
> Mikael
> [Message sent by forum member 'mikaelgrev' (mikaelgrev)]
>
> http://forums.java.net/jive/thread.jspa?messageID=167140
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

- Blasting forth in three part harmony!

[att1.html]

mikaelgrev
Offline
Joined: 2006-09-27

> Interesting. That does solve the bean problem, but then it's putting
>ordering into the painters rather than the thing that contains them.
>Should painters even be aware of their order? Or does this int
>represent their 'preferred layer', which the container can choose to
>ignore if desired?

It feels like I have tricked you into admitting that we need a better JavaBean spec regarding indexed (collection) properties doesn't it? ;)

This solution is a trade of because the lacking spec i guess.

We (in Mig Calendar) actually have both the getter and setter of the index in the interface. This means that the painter is just managing the value of the index, not producing it. It is not the best of solutions but, and sorry for the coming volume, WE NEED COLLECTION PROPERTIES WITH A COLLECTION AWARE STANDARD PROVIDED PROPERTY EDITOR. So there. It's out of my system.

I have been haunting Richard with this on the JSR-273 expert list as well but it's really hard to convince people without making an enormous effort to explain why and in what situations something is needed. These kind of things are so abstract that if they haven't bitten by it they won't know about them and will have a hard time understanding that they can't be worked around in a good way.

Ok, Rant out. :)

Cheers,
Mikael

Joshua Marinacci

Okay. I'm settled in Prague now and on a decent network connection
finally. Much happier!

On Oct 30, 2006, at 6:36 PM, jdnc-interest@javadesktop.org wrote:

>> Interesting. That does solve the bean problem, but then it's putting
>> ordering into the painters rather than the thing that contains them.
>> Should painters even be aware of their order? Or does this int
>> represent their 'preferred layer', which the container can choose to
>> ignore if desired?
>
> It feels like I have tricked you into admitting that we need a
> better JavaBean spec regarding indexed (collection) properties
> doesn't it? ;)
>
> This solution is a trade of because the lacking spec i guess.
>
> We (in Mig Calendar) actually have both the getter and setter of
> the index in the interface. This means that the painter is just
> managing the value of the index, not producing it. It is not the
> best of solutions but, and sorry for the coming volume, WE NEED
> COLLECTION PROPERTIES WITH A COLLECTION AWARE STANDARD PROVIDED
> PROPERTY EDITOR. So there. It's out of my system.

You won't get any disagreement from me. We do need collection
properties and property editors. I can build such a thing easily
enough to use for our own apps (and in NB) but that doesn't solve the
problem that we don't have a collection class which will actually do
what we need. It will only work if the store the layer value on the
thing to be sorted, rather than on the collection. We can build a
custom collection to do this as well, of course, but I fear we are
going beyond the scope of this problem.

> I have been haunting Richard with this on the JSR-273 expert list
> as well but it's really hard to convince people without making an
> enormous effort to explain why and in what situations something is
> needed. These kind of things are so abstract that if they haven't
> bitten by it they won't know about them and will have a hard time
> understanding that they can't be worked around in a good way.

Agreed.

Last night I did more work on painters and I've come up with some new
problems. I built a PainterTableCellRenderer that takes four
painters. Fore and Back for normal cells and Fore and Back for the
selected cells. You can then use a second instance to handle table
headers, though it's more cumbersome to install (because of the way
tables work, not because of painters). This is the problem I've come
up with:

The PainterTableCellRenderer essentially has two stacks of painters.
One for normal cells and one for selected cells. If we put the
LayeredPainter methods into the renderer itself then it means we now
have twice the number of methods than before, which really adds a lot
to this renderer. Also, there's no way to make this Iterable aware
because we can't have the renderer implement iterable twice.

Working on this renderer has highlighted some possible problems with
the way we handle the standard component drawing. If we have fore and
back layers around the component layer. Then setting the background
layer will behave as expected. However, setting the fore layer will
be *on top* of the text. Thus if you set a textpainter for the
foreground you get text twice. Sure you could set the component layer
directly, but this is becoming very counter-intuitive.

I set up the component layer the way I did because I assumed that we
didn't want to change the opacity and that we couldn't split the fore
and back layers. In practice, however, we often can. The default
renderers are simply labels so we don't need to worry about the
background. A panel has no foreground, so there's nothing to split.
Buttons have both a fore and background, and setting even the
background color is ill-defined in core. However, we can remove the
background if we wish to using the contentFilled property. Thus we
don't have a solution that works for every component, but we could do
something that works for most component. There would be some custom
work underneath but I think we could keep that hidden for most
cases. For custom components they had to go out of their way to
support painters so it can be assumed that they will find a way to
support splitting the fore and background.

Thus I wish to amend my proposed solution:

* Change LayeredPainter to PainterSet or something more indicative of
the fact that it's not strictly a painter anymore.
* Make LayeredPainter be iterable and fit common collections patterns
(make it a real collection if we can, a special list subclass?)
* Build a property editor to support this.
* Make fore and back properties be special cases of the general case
* Remove the component layer. We will have back, fore, and overlay as
the standard layers. (Do we need an underlay? Border?)
* Back will replace the standard background on supported components.
Whatever changing the foreground color would affect.
* Fore will replace the standard foreground. Usually the text.
Whatever changing the foreground color would affect.
* On components where we can't split the fore and back then the fore
painter will replace all drawing.

Does this sound reasonable?

- Josh

- Blasting forth in three part harmony!

[att1.html]

Joshua Marinacci

I've gone back and forth on this one. I went with this approach for
three reasons:

1) it keeps the new API simple for the simple case. You can set the
fore and background painters easily, or replace the entire painter
stack easily. The more complicated parts are delgated to a sub-
object, much the way Swing components often delegate to a model.

2) It minimizes the extra work needed to be done by components which
want to support painters. They can delegate everything to the
LayerPainter. Think PropertyChangeSupport.

3) Since iterative painting is needed in CompoundPainter anyway, this
lets us reduce duplicated code. I think CompoundPainter and
LayerPainter should be sub-super classed together, or else just
combined into one.

Oh, and in your example below you wouldn't have to cast. It would be
like this:

panel.getLayerPainter().add(otherPainter, 20);

- J

On Oct 25, 2006, at 10:40 AM, jdnc-interest@javadesktop.org wrote:

> I tried to reply earlier, but the forum kept crashing on me when
> trying to quote the original post!
>
> One thing I'd argue about is whether it makes sense to have a
> LayourPainter, or to build the layers directly into the components.
> Personally, I think the components is where you want the layering,
> not in the painter heirarchy.
>
> Reason:
>
> [code]
> JXPanel panel = new JXPanel();
> panel.setPainter(30, somePainter);
> ...
> panel.setPainter(20, otherPainter);
>
> /* vs. */
>
> JXPanel panel = new JXPanel();
> panel.setPainter(layerPainter);
> ...
> /* either I keep a reference to layerPainter and do: */
> layerPainter.add(30, somePainter);
> /* or I have to */
> ((LayerPainter)panel.getPainter()).add(20, otherPainter);
> [/code]
>
> Or am I missing something here? It seems like layers must be on the
> component level, so are you then suggesting having layers in two
> places? Or always using a LayerPainter for the component (and force
> this via API)?
>
> Richard
> [Message sent by forum member 'rbair' (rbair)]
>
> http://forums.java.net/jive/thread.jspa?messageID=166936
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

- Blasting forth in three part harmony!

[att1.html]

Joshua Marinacci

And I forgot to add. This gives us a single place to turn on
AntiAliasing, set rendering hints, or change the transform if you
want to affect the entire component at once.

- J

On Oct 25, 2006, at 12:10 PM, Joshua Marinacci wrote:

> I've gone back and forth on this one. I went with this approach
> for three reasons:
>
> 1) it keeps the new API simple for the simple case. You can set the
> fore and background painters easily, or replace the entire painter
> stack easily. The more complicated parts are delgated to a sub-
> object, much the way Swing components often delegate to a model.
>
> 2) It minimizes the extra work needed to be done by components
> which want to support painters. They can delegate everything to the
> LayerPainter. Think PropertyChangeSupport.
>
> 3) Since iterative painting is needed in CompoundPainter anyway,
> this lets us reduce duplicated code. I think CompoundPainter and
> LayerPainter should be sub-super classed together, or else just
> combined into one.
>
> Oh, and in your example below you wouldn't have to cast. It would
> be like this:
>
> panel.getLayerPainter().add(otherPainter, 20);
>
> - J
>
>
> On Oct 25, 2006, at 10:40 AM, jdnc-interest@javadesktop.org wrote:
>
>> I tried to reply earlier, but the forum kept crashing on me when
>> trying to quote the original post!
>>
>> One thing I'd argue about is whether it makes sense to have a
>> LayourPainter, or to build the layers directly into the
>> components. Personally, I think the components is where you want
>> the layering, not in the painter heirarchy.
>>
>> Reason:
>>
>> [code]
>> JXPanel panel = new JXPanel();
>> panel.setPainter(30, somePainter);
>> ...
>> panel.setPainter(20, otherPainter);
>>
>> /* vs. */
>>
>> JXPanel panel = new JXPanel();
>> panel.setPainter(layerPainter);
>> ...
>> /* either I keep a reference to layerPainter and do: */
>> layerPainter.add(30, somePainter);
>> /* or I have to */
>> ((LayerPainter)panel.getPainter()).add(20, otherPainter);
>> [/code]
>>
>> Or am I missing something here? It seems like layers must be on
>> the component level, so are you then suggesting having layers in
>> two places? Or always using a LayerPainter for the component (and
>> force this via API)?
>>
>> Richard
>> [Message sent by forum member 'rbair' (rbair)]
>>
>> http://forums.java.net/jive/thread.jspa?messageID=166936
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
>> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
>
> - Blasting forth in three part harmony!
>
>

- Blasting forth in three part harmony!

[att1.html]

rbair
Offline
Joined: 2003-07-08

> A good layering system is a tough thing to create.
> I don't know really what's your final goal on it, i
> just saw the thread topic on java.net index, put i
> passed a bit of my spare time in the last months to
> create one.
> When i started that project, i wanted to have layers
> where programmers could act independently of others,
> add layers, uptade them, change content, let layers
> act onto others (shadowing of one/all over background
> ...), animate them, ....
> I came to what i believe is a pretty neat system
> (edit: in respect of what i wanted to do, of
> course... YMMV), you might want to take a look.
> https://swash.dev.java.net

:-). Looks like something Romain and I had whiteboarded earlier this year, using the TimingFramework for the animation work. Good luck! It's really encouraging to see so many client oriented frameworks and projects springing up!

Richard

pepe
Offline
Joined: 2003-06-10

> :-). Looks like something Romain and I had
> whiteboarded earlier this year, using the
> TimingFramework for the animation work. Good luck!
> It's really encouraging to see so many client
> oriented frameworks and projects springing up!
>

Looks like Romain is not far when there are things moving around swing. This is the case for me too, as i decided to start it right after seeing his presentation at javapolis. :)

On the subject of having many frameworks coming out, i'm not sure this is such a great thing, just because of the loss of energy. I did hesitate a long time before starting mine and even after it ran and got demoed.

> Brilliant! I hope you can attract interest in this. Great work!
whew... thanks for the kind words. please allow me to faint a bit. :)

Kleopatra

Joshua Marinacci wrote:

Jumping in with a couple of comments - not burdened by much knowledge of
any gory details nor an overview of what already has been discussed :-)

> want to do with them in practice. I think that having a layering
> ability is important, though I want to preserve a simple API.

yeah, I agree - even would go a bit further: layering is _the_ important
aspect of Painters, IMO.

> I've also
> come to realize that there is absolutely no reliable way to separate a
> normal component's foreground and background.

Hmm ... that's a problem, but as I see it a problem of today - or a
future one as well? Assuming that painters will be part of core Swing in
MarsCow (an animal yet to be detected in one of the next missions :) I
would expect painters be used *exclusively* for painting in components
and their uiDelegates. The basic layering would be something like

- below content
- content
- above content

and uidelegates by default use a PainterUIResource for each. Clients can
add and/or replace any of these.

Doesn't help in todays problems, though :-)

Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

twalljava
Offline
Joined: 2004-07-26

You can return the painters as a sorted Map (e.g. TreeMap), which would preserve both the order and the layer information.

Why should overlays and validation be part of the component painting itself, and not a logically separate decoration (JLayeredPane handles this just fine, see the decorators at http://rabbit-hole.blogspot.com)?

Taking out overlays (validation is a type of overlay, really), you have foreground and background, which seem like a sensible split.

Joshua Marinacci

I meant that overlays and validation are additional layers. These are
just constants that represent common layer areas. They are completely
arbitrary. We just need to figure out what the useful ones are and
assign them ints in the right order.

- J

On Oct 24, 2006, at 5:24 AM, jdnc-interest@javadesktop.org wrote:

> You can return the painters as a sorted Map (e.g. TreeMap), which
> would preserve both the order and the layer information.
>
> Why should overlays and validation be part of the component
> painting itself, and not a logically separate decoration
> (JLayeredPane handles this just fine, see the decorators at http://
> rabbit-hole.blogspot.com)?
>
> Taking out overlays (validation is a type of overlay, really), you
> have foreground and background, which seem like a sensible split.
> [Message sent by forum member 'twalljava' (twalljava)]
>
> http://forums.java.net/jive/thread.jspa?messageID=166298
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

- Blasting forth in three part harmony!

[att1.html]

pepe
Offline
Joined: 2003-06-10

A good layering system is a tough thing to create.
I don't know really what's your final goal on it, i just saw the thread topic on java.net index, put i passed a bit of my spare time in the last months to create one.
When i started that project, i wanted to have layers where programmers could act independently of others, add layers, uptade them, change content, let layers act onto others (shadowing of one/all over background ...), animate them, ....
I came to what i believe is a pretty neat system (edit: in respect of what i wanted to do, of course... YMMV), you might want to take a look.
https://swash.dev.java.net

Patrick Wright

> I came to what i believe is a pretty neat system, you might want to take a look.
> https://swash.dev.java.net

Brilliant! I hope you can attract interest in this. Great work!

Patrick

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

mikaelgrev
Offline
Joined: 2006-09-27

First:
> So what do you think? Is this all possible?

Of course! There's no kids involved so nothing can go wrong. Right? ;)

I think we solved a few of the issues here:
http://forums.java.net/jive/thread.jspa?forumID=73&threadID=14296

The glow of the labels might be a problem though since it need access to the component's rendering pipeline. It can be solved if the painter is getting a reference to the component it is about to decorate. It can then do whatever it wants with it including rendering it to a buffer and "glow" it there and then paint that. I haven't looked at JXPanel and the Painter interface for a while though so maybe this is already accounted for in the Painter API?

In our Painter interface we have a method processEvent(AWTEvent e) that will get the events in the painter stacking order, provided by the Component. The painter can then either just "read" the events to know what's going on or it might even block events (InputEvents by calling consume() or by a boolean return value). It gives a lot of power though and it can lead to interesting bugs if used incorrectly.

A smart implementation with negative "magic" numbers (layer index > 0) for the predefined painters (such as background) can be used to create a very flexible layering system that is very performant. Then the different "painter recievers" (CellRenderer and JXPanel) can just choose what to expose through properties (for use in IDEs) and also expose a more collection like approach, which I like. This is what was handled in the thread linked above.

It's a start.

Cheers,
Mikael

Joshua Marinacci

I've looked through the original thread and come up with a new
proposal. In the six months since we originally discussed this I've
written a lot more painters and started figuring out what I will
really want to do with them in practice. I think that having a
layering ability is important, though I want to preserve a simple
API. I've also come to realize that there is absolutely no reliable
way to separate a normal component's foreground and background. The
Windows Look and Feel implementation of a button, for example, does
not provide a way to draw the text separate from the background
without making specific hacks just for this look and feel. This means
we need to figure out how our layering system will address these issues.

Any solution needs to address the following:
* define what to do with the component's original drawing code
* make the common cases very simple while still enabling complex
usage and not hindering full subclass hacking
* introduce minimal new api to the components themselves

Here's my proposal:

Create a LayerPainter which will extend AbstractPainter. This means
it will pick up the Graphics2D controls like AntiAliasing, Quality vs
Speed settings, translation and rotation, etc. LayerPainter has
methods to set, query, and modify and ordered list of painters. The
painters can be set at well known layers using int constants. If you
call add instead of set and there is already a painter at that
constant, then it will move that painter up and insert yours at the
original location [i'm still not sure about this part].

LayerPainter
setPainter(Painter, int layer)
Painter getPainter(int layer)
addPainter(Painter, int layer)
addPainter(Painter) [defaults to the foreground layer]
removePainter(Painter)
removePainter(int layer)
Painter[] getPainters()
setPainters(Painter[])
// constants
int BACKGROUND
int COMPONENT
int FOREGROUND
int OVERLAY
int VALIDATION

There are still some dicey parts, such as how you preserve the layer
levels if you retrieve the painters all at once. ex:
layerPainter.setPainters(layerPainter.getPainters());
would preserve the ordering but nuke the layers.

Still, you can get the general idea. With the LayerPainter in hand
we change JXPanel to have just three sets of methods

JXPanel
get/setLayerPainter(LayerPainter)
get/setBackgroundPainter(Painter)
get/setForegroundPainter(Painter)

the background and foreground painter methods simply delegate to the
layer painter like this:
public void setBackgroundPainter(Painter painter) {
getLayerPainter().setPainter(painter,LayerPainter.BACKGROUND);
}

The component will have a layer painter preinstalled. This painter
contains an inner Painter which calls paintComponent(Graphics) on the
component. This inner painter is installed at the COMPONENT layer
level (level 0). This means that you can put your painters anywhere
you want relative to the component painter using the appropriate
level. You can replace it with a new painter or 'null' using
layerPainter.setPainter(painter, LayerPainter.COMPONENT).

To preserve compatibility with existing component and the general
Swing architecture the painters will not affect the component opacity
at all. The existing contract will be kept. If you want effects
which require turning off the background but not the foreground will
require the developer to manually change the opacity. I don't see
any other reasonable way to do this.

Here's a few examples of how it would work:

* add a painter on top of a component, original drawing still done
comp.setForegroundPainter(painter)

* add a validaiton painter on top of a component which already has
painters on it, possibly even validation painters
comp.getLayerPainter().addPainter(painter, LayerPainter.Validation)

* remove the previous validation painter once the input is corrected
comp.getLayerPainter().removePainter(painter)

* use a painter to replace the background of a panel
comp.setBackgroundPainter(painter);
comp.setOpaque(false);
or
comp.getLayerPainter().setPainter(painter, LayerPainter.Component)

* use a painter for the foreground of a jbutton
comp.setForegroundPainter(painter), will be drawn on top of the
component. if you want to get rid of the component drawing then you
must replace the component drawing completely or else set the text
color to transparent so it's hidden.

So what do you think? I think this will give us a functional API with
a minimal number of methods on the component itself.

- Josh

On Oct 20, 2006, at 12:17 PM, jdnc-interest@javadesktop.org wrote:

> First:
>> So what do you think? Is this all possible?
>
> Of course! There's no kids involved so nothing can go wrong. Right? ;)
>
> I think we solved a few of the issues here:
> http://forums.java.net/jive/thread.jspa?forumID=73&threadID=14296
>
> The glow of the labels might be a problem though since it need
> access to the component's rendering pipeline. It can be solved if
> the painter is getting a reference to the component it is about to
> decorate. It can then do whatever it wants with it including
> rendering it to a buffer and "glow" it there and then paint that. I
> haven't looked at JXPanel and the Painter interface for a while
> though so maybe this is already accounted for in the Painter API?
>
> In our Painter interface we have a method processEvent(AWTEvent e)
> that will get the events in the painter stacking order, provided by
> the Component. The painter can then either just "read" the events
> to know what's going on or it might even block events (InputEvents
> by calling consume() or by a boolean return value). It gives a lot
> of power though and it can lead to interesting bugs if used
> incorrectly.
>
> A smart implementation with negative "magic" numbers (layer index
> > 0) for the predefined painters (such as background) can be
> used to create a very flexible layering system that is very
> performant. Then the different "painter recievers" (CellRenderer
> and JXPanel) can just choose what to expose through properties (for
> use in IDEs) and also expose a more collection like approach, which
> I like. This is what was handled in the thread linked above.
>
> It's a start.
>
> Cheers,
> Mikael
> [Message sent by forum member 'mikaelgrev' (mikaelgrev)]
>
> http://forums.java.net/jive/thread.jspa?messageID=165393
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

- Blasting forth in three part harmony!

[att1.html]

mikaelgrev
Offline
Joined: 2006-09-27

Josh, It's a good solution you are proposing.

Would be great to have those add/remove bean spec properties in beans wouldn't it. To solve the problem that indexed properties should have solved.. :)

Cheers,

Joshua Marinacci

I agree. That's really what my question is about. How can we make
LayerPainter be a proper bean. Realistically, are we going to have a
non-custom editor edit this property of the component anyway? I
suspect not. We will need a custom painter editor to control and edit
the stack of painters inside the layerpainter. By itself, NetBeans,
Eclipse, Idea, or any other IDE wouldn't do anything useful with this
property.

- j

On Oct 25, 2006, at 8:48 AM, jdnc-interest@javadesktop.org wrote:

> Josh, It's a good solution you are proposing.
>
> Would be great to have those add/remove bean spec properties in
> beans wouldn't it. To solve the problem that indexed properties
> should have solved.. :)
>
> Cheers,
> [Message sent by forum member 'mikaelgrev' (mikaelgrev)]
>
> http://forums.java.net/jive/thread.jspa?messageID=166873
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

- Blasting forth in three part harmony!

[att1.html]

rbair
Offline
Joined: 2003-07-08

I tried to reply earlier, but the forum kept crashing on me when trying to quote the original post!

One thing I'd argue about is whether it makes sense to have a LayourPainter, or to build the layers directly into the components. Personally, I think the components is where you want the layering, not in the painter heirarchy.

Reason:

[code]
JXPanel panel = new JXPanel();
panel.setPainter(30, somePainter);
...
panel.setPainter(20, otherPainter);

/* vs. */

JXPanel panel = new JXPanel();
panel.setPainter(layerPainter);
...
/* either I keep a reference to layerPainter and do: */
layerPainter.add(30, somePainter);
/* or I have to */
((LayerPainter)panel.getPainter()).add(20, otherPainter);
[/code]

Or am I missing something here? It seems like layers must be on the component level, so are you then suggesting having layers in two places? Or always using a LayerPainter for the component (and force this via API)?

Richard

mikaelgrev
Offline
Joined: 2006-09-27

Either way is good with me. My initial proposal was to have it in the component API, I just think it is cleaner that way.

Dream scenario is to have JSR-273 add support for Collection properties like these and that this Painter layering implementation would be the first real use for it and the concrete thing that "forces" the IDE creators to support it.

Cheers,