-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create separate renderer classes #152
Conversation
This will fail ATM on non-Windows systems (because Display was not updated there yet), but I wanted to get your feedback first. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some quick feedback:
Separating the renderers from the widgets themselves makes sense to me, so that's definitely a great improvement.
I am not completely sure about the intention with the Windows...Renderer
implementations. Is the goal to implement OS-specific renderers for all widgets? For me it would be important that we do not require for every widget that is custom implemented to have a renderer for each of the OSes, as that would mean too much effort for the initial contributions and we really need to focus on having more widgets custom implemented than having each widget implemented in different shaped. May be that we eventually want to have different renderers, but I am also not sure whether they will or should be according to the current OS-specific look&feel or whether they may be "themes" that are independent from that.
Thanks for the quick feedback. Well, the current controls imitate the Windows look, hence I've named them that way. For Label and Link I only have implemented a One aspect that this PR discussion should clarify is where to store the (official and internal) state of the controls. The offical state is about those properties available from the control's official API (e.g. |
I don't really like the "Windows" in the name of the renderers. During implementation i try to emulate the rendering of the windows native widgets but this is just to compare with the native implementation. I see this as an intermediate step. As soon as the SWT skija implementation reaches feature parity, the look&feal should get an modern, not-OS-related look. In that case Windows*Renderer would not make sense and for now it might suggests that each renderer would have to look like windows. |
What prefix you'd prefer instead? |
d24e13d
to
5b78ba5
Compare
Either no prefix or Default or, if we decide to give the default design a proper name, use that is prefix. EG. FlatLafButton. This is far the the future though. |
5b78ba5
to
8c89329
Compare
For the copyright-header: when extracting major parts of one class to another, should I also copy the original copyright-header? |
f6e2b76
to
3f7d4f6
Compare
Do you still see some changes that I should fix before merging? |
Thank you for all your comments and the discussion. I see there is already a good agreement.
I understand, thank you for the clarification! So it was not about providing renderers for each OS but just indicating what the renderer is about (currently, providing Windows look&feel, also on, e.g., Linux). But I think you already found a good agreement and we may change the names of the renderers later on once we agree which renderers we want to have.
Even though the answer might be unsatisfying, I would say that it depends (like you also argued in your further comment): in case it's state about that widget that would, e.g, need to be preserved upon exchanging the renderer, it should be stored in the widget itself (like its enablement, visibility or checked state). If it's about state of the rendering or some transient state that can be restored (like hovering), it might be part of the renderer.
I am not sure whether there is any strict policy since the actual contributions are documented via version control anyway. When a class is based on an existing other class, I usually copy over the copyright header from there, as it's basically an evolved version of that file.
To me it looks good now. I am only wondering about the different RendererFactories: since they are all the same right now, shouldn't we defer creating separate factories until we actually have differences in them? Good chance that there won't be Windows/Linux/MacOS factories but rather ones according whatever kinds of renderer "themes" we provide. |
3f7d4f6
to
96f7f99
Compare
Let's look at the |
96f7f99
to
0f3046d
Compare
For the Button I now have moved the properties back into the control, but for the Label I don't see a good way because, e.g., it does not expose all background related properties. |
1.) Why do you bind the RendererFactory to the Display? I would rather create a singleton factory, which then returns the right Renderer dependent on the input control: `` var renderer = RendererFactory.getInstance().createRenderer(buttonWithRatioButtonStyle); // returns the right renderer for Radiobuttons `` I would rather prefer stateless renderers, which gets all control attributes from the control.
In this design, the disabled image is a cached data for the image. Which means if you change images the renderer should invalidate its cache. If the disabled image is created in the label and the renderer requests it from there, then it is an attribute. In my opinion all necessary label attributes should be made accessible for the renderer. Or it is possible to create a ControlAttributes class, which then contains all attributes of the control. Maybe this should be clarified first. Nonetheless, I think a renderer design would be useful. |
I thought about something like this before, but backed away from it because i did not want to over engineer things from the start.
But there is also a disadvantage: We don't know in advance what attributes will be required by a custom Renderer. Thus we would have to add all attributes, event those that are currently not used by our Renderer implementation. This could be a performance hit but i image a rather small one. |
0f3046d
to
e67ef20
Compare
Because it is the natural central for all GUI related stuff and I would expect to have a method
I consider singletons mostly as anti-pattern. Better avoid them if you can - they make discovering a feature harder, they make detecting dependencies harder, they make testing harder.
There are two kind of states, the official API states like
It should be possible to implement the renderer in any package. This would not be possible with making it (package) protected. |
Currently they need a reference not just to access states (
This best would be done with immutable states (records). |
Currently, #154 causes me to be reluctant in merging (AKA splitting the |
There can be multiple Display instances, so if someone changes the RendererFactory in one Display, multiple RendererFactories with different configuration could exist.
Singleton Pattern: I don't see it that way, especially because of the alternatives. But this is a general discussion.
When i think about animations, then it might make sense. This would be the idea of custom animations by custom renderers for a control. This is thinkable... But this argumentation breaks if the rest of the control also needs a specific information. Currently i am not sure about this. @HeikoKlare |
Out of curiosity: what is the idea behind having multiple display instances? Heiko hat a similar suggestion in my color provider PR #130, but I could convince him;). |
Multiple Display instances is a Windows feature. This means you can run one java program, and have two shells which are thread independent and don't interfere with each other. |
Common use case for this is asynchronous "off-screen" rendering. We use that to keep the UI responsive while doing a complex rendering on a separate display and copy over the result once that's done. |
e67ef20
to
7a061cb
Compare
Thanks for the usecases - I've did not know them. Could it be useful to set one display a different color-provider/renderer-factory than the other? |
I dont't think so. |
fbdb170
to
2434ed4
Compare
Does someone object to be merged in the current state? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am fine with the changes. I have just tested them and did not find any introduced issues so far.
I only saw an accidentally removed copyright header. Once that is readded, I am fine with merging.
bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/ScaleRenderer.java
Show resolved
Hide resolved
2434ed4
to
bf07024
Compare
for checkbox, radio button and arrow button
…ating the renderers
bf07024
to
e3dbbbf
Compare
I've extracted the LinkRenderer stuff into a different branch because it is not yet ready (the properties are not moved back yet to the control, because the Link needs to be reworked anyway #154). |
|
||
protected abstract void paint(GC gc, int width, int height); | ||
|
||
private final CustomControl control; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does it have to be a CustomControl
instead of a Control
? I was trying to adapt my current PR (#150) to use the renderers but since Spinner
still extends Control
then I get a compilation error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw I tried simply changing the type to Control
and adapting 2 other methods to accept Control
as parameters and everything compiles and seems to run fine (I tested the ControlsExample
). I just ask in case this was not a mistake and I am missing the big picture :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As Spinner
is a Composite
that can't be a child of CustomControl
, your change is fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it could make sense to make ControlRenderer
generic: ControlRenderer<C extends Control>
and making the field control
protected, so subclasses can easily use it?
I've tried to extract the computeSize and paint code into separate *Renderer classes with one abstract parent class, e.g.
ScaleRenderer
and an implementation class likeWindowsScaleRenderer
. For buttons, I've also split to separate classes for checkbox, radio button, arrow button and "normal" (AKA push/toggle) button.Those renderer instances are created by a factory owned by the
Display
.