You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@pivot.apache.org by "Greg Brown (JIRA)" <ji...@apache.org> on 2010/06/23 19:05:51 UTC

[jira] Resolved: (PIVOT-542) enable the serializer to initialize components written in java code

     [ https://issues.apache.org/jira/browse/PIVOT-542?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Greg Brown resolved PIVOT-542.
------------------------------

    Resolution: Won't Fix

OK, thanks for the example. I hate to say it, but even after seeing how it might be used in practice, I'm still not a fan of the approach. As I mentioned in another thread, the recommended way to create a custom component is to also create a custom skin that goes with it. So, I'd expect to see an EditorSkin class that uses BXMLSerializer internally to load and bind() to its content. Alternatively, you could have your Editor class implement Bindable and use <bxml:include> to add it to the host component (Bindable is effectively the equivalent of "code-behind" in Pivot).

If you don't want to create a custom skin and don't want to use an include, you could still use BXMLSerializer in the Editor constructor to load the left and right panes and set them via setLeft() and setRight(). After loading each pane, you could call bind() on the editor instance (this) to attach any values declared in the includes to the Editor instance.

While what you suggest makes sense for frameworks that compile XML to classes (e.g. MXML, XAML), it just isn't consistent with the serializer concept. Serializers take an input stream and return an object. The object that creates the serializer isn't meant to also be the object that is instantiated by the serializer. That's just a little too convoluted.

Thanks for the submission, though.


> enable the serializer to initialize components written in java code
> -------------------------------------------------------------------
>
>                 Key: PIVOT-542
>                 URL: https://issues.apache.org/jira/browse/PIVOT-542
>             Project: Pivot
>          Issue Type: Improvement
>            Reporter: Appddevvv
>         Attachments: initialize-examples.zip, WTKXSerializer-with-initialize.patch
>
>
> The current serializer performs two funtions: creating objects and initializing them. The typical use case is to create your component (say java code) then call the serializer to create the content. Then within your class, attach the content and initialize your object in various application specific ways. However, since your object is typically a java object and often a Component subclass, for those writing new components as composites of others, you have to manually write some (not all) initialization code that could also be performed in the BXML file. 
> To initialize your object using bxml content, you can use annotations etc. However, if the bxml file also defines user data or other elements, you also have to manually bring that in from the bxml and do some wiring. In addition, it is currently impossible to initialize some pivot objects that you subclass from, say the splitpane, with content from bxml without having to create an intermediate container or use two bxml files for the left and right child. For example, if you subclass from SplitPane, an underlying bxml file that holds your content must have another container in order to define your left and right children in or you have to use two separate bxml files per child--this may or may not be a good thing and complicates the implementation.
> To support the use case of creating subclasses of Components (and pivot likes to use OO inheritance) and allowing the initialization of that component to be matched by a bxml file, the serializer needs to be able to "apply" itself to the component as if the bxml file and the subclassed component were a reflection of the other. Bindable was designed to help with this, however, the bxml file is still considered at level below (the content) of the Component you are writing.
> The benefits are:
> a) A cleaner code style that has implied semantics--i.e. this bxml file is the mirror image of your subclassed component at the same logical tree level.
> b) More consistent coding conventions for novice programmers.
> The capability to do this can be implemented in different ways including the current approaches of course. The small patch allows a new style of Component creation blending code and bxml in a more seamless way. Its no longer something you instantiate to "get" content, it is the content. It helps Component writers who want to simply subclass another component. It looks like a trivial change but it is a different perspective on initialization that has natural semantics for programmers. It also reduces complexity for creating subclasses of Components that have properties representing the tree e.g. SplitPane.
> This is similar in spirit to "code-behind" in other frameworks.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


Re: [jira] Resolved: (PIVOT-542) enable the serializer to initialize components written in java code

Posted by Greg Brown <gk...@mac.com>.
>> Again, in frameworks that compile to classes, this makes sense. When I
>> define MyClass.xaml and MyClass.cs, they are both combined such that the
>> following both instantiates and initializes the class:
>> 
>>  MyClass myClass = new MyClass();
>> 
>> But this doesn't work for BXMLSerializer.
>> 
> I am not totally familiar with the blending you describe but I don't
> think that object instantiation and initialization are directly tied to
> blending. I am not claiming that "you" create the element directly, just
> that the bxml file holds parts of the freeze dried version of the object
> whether you create the root object in code or bxml. In xaml, I don't think
> there are there are any "do an include to include your object" and you
> should not have to (but its an option), in pivot.

Includes aren't strictly necessary in XAML or MXML because both of those are compiled to classes that can then be referred to directly as elements. For example, if I create MyClass.mxml, I can then use <MyClass> in another MXML file. Since BXML is not compiled, we use includes to achieve the same type of behavior.

To your other point - bind() isn't meant to be a means for initializing all possible member variables. BXML's primary means of initializing member variables is via elements and attributes (i.e. bean setter methods). Binding is simply a convenience for mapping variables defined in BXML (either with bxml:id or in script) to internal member variables that you don't necessarily want to expose via a bean property. And of course you can always perform additional initialization in your class constructor itself.



RE: [jira] Resolved: (PIVOT-542) enable the serializer to initialize components written in java code

Posted by aappddeevv <aa...@verizon.net>.
Thoughts with >>>. My mail program did not auto > the previous email :-)

Thanks for responding to this. I'll close this out.

-----Original Message-----
From: Greg Brown [mailto:gkbrown@mac.com] 
Sent: Wednesday, June 23, 2010 2:41 PM
To: dev@pivot.apache.org
Subject: Re: [jira] Resolved: (PIVOT-542) enable the serializer to
initialize components written in java code

> The seriliazer already plays the initialization role. 

The serializer is the creator and the initializer. In the model you suggest,
it is only the initializer - the new keyword is used to create the object.
This is inconsistent. If you only need initialization, you should use the
bind() method.

>>>bind() cannot automatically perform full binding actually on its own
without coding. Coding is not bad, but its not needed here. With the
proposed approach, variables, not just @WTKX variables, including those
defined in superclasses are automatically initialized because the xml is
just the freeze dried version of the object. In fact the Bindable interface
with the initialize method encourages you to reach in and get resources.  A
cleaner approach is that the properties at the root level of the serializer
are really the properties of the object being created.

> My understanding is that skins are views. Components are
model/controllers.
> The view should not be loading user data and other child content into the
> mode/controller so I'm not sure I would agree that the skin should be
doing
> this at all because part of the initialization is also Component data such
> as userData.

Skins shouldn't get involved in the model data, but they are allowed to add
sub-components. For example, all composite component skins do this (Spinner,
ScrollBar, Frame, etc.).

>>>That's a great point.  And in fact, this initialize() proposal does not
change this it all.

> With the editor, there are a few ways to do this. This is actually a very
> direct approach. In the thoughts below, I am still forced, at a minimum,
to
> use an interface and for me to write code for wiring. I'm not against
> writing code but when the serializer can do it naturally, that's a win.

The problem is that the suggested modifications to the serializer are not
natural because they don't fit in with the overall design of the framework.

>>>I think I get your point about skins and I think I appreciate skins more
now than I did before.

>>>But I can see from other recent changes to the Bindable interface that
you are moving closer to this initialize proposal. If you take Bindable to
the next step, you starting getting the initialize approach I am proposing.
Not against Bindable, but its another interface that's not always needed and
bind() cannot automatically initialize all of the object's properties
automatically such as userData or other properties define in your
code-behind. The serializer is actually inconsistent in its ability to
initialize instance variables of the calling object when you call bind().
Bind() can only do @WTKX variables, but a component has a lot of variables
in superclasses that could use similar help.

>>>Lets say you remove the Bindable interface because you don't want
component writers to have to worry about another interface and their methods
for initialization. What would you do? The initialize() proposal is an
answer and it does more initialization of variables since bind() only does
@WTKX annotated variables. The semantics of Bindable combines two logical
elements into one: some bind() which is instance variable initialization and
notifying the object it has been bound (that it has been initialized through
binding). @WTKX still stays because it initializes variables only in your
subclass without any extra work, a huge convenience.

>>Notifying that a bind has occurred is actually closer to @PostConstruct
which is a java standard. It is called after instantiation and automatic
variable initialization. But in pivot Bindable tries to do both. It combines
two things into one. Teasing this apart slightly with this proposal around
initialization semantics actually improves consistency of instance variable
initialization and provides a new capability for clients. You can't annotate
instance variables in superclasses without access to source code, but you
still want them initialized from the serializer just like @WTKX variables in
your subclass. It's a big convenience.

>>>Example: Think about the MyDialog just posted to the user list. In it,
you define a subclass of Dialog. But to allow them to use it they have to
use an include in the bxml because the "contents" of the dialog are in the
bxml. I say skip the include. When you need to use the MyDialog in code or
bxml, just refer to the class as you would any other pivot-provided
component. The bxml just backs the object being created. In this case, there
is total consistency between code and bxml in terms of using MyDialog
regardless of how its deployed by the client. The MyDialog.bxml would be
used behind the scenes, using this proposal, to initialize the object
whether the client created it in code or bxml. Of course, MyDialog could be
coded other ways, such as creating a skin. But for this, would do really go
through that effort?


> It took me awhile to understand why I
> had to always had to do extra work with includes or setting left and right
> children in code until I realized that the serializer should be doing it
for
> me.

Again, in frameworks that compile to classes, this makes sense. When I
define MyClass.xaml and MyClass.cs, they are both combined such that the
following both instantiates and initializes the class:

  MyClass myClass = new MyClass();

But this doesn't work for BXMLSerializer.

>>> I am not totally familiar with the blending you describe but I don't
think that object instantiation and initialization are directly tied to
blending. I am not claiming that "you" create the element directly, just
that the bxml file holds parts of the freeze dried version of the object
whether you create the root object in code or bxml. In xaml, I don't think
there are there are any "do an include to include your object" and you
should not have to (but its an option), in pivot.


Re: [jira] Resolved: (PIVOT-542) enable the serializer to initialize components written in java code

Posted by Greg Brown <gk...@mac.com>.
> The seriliazer already plays the initialization role. 

The serializer is the creator and the initializer. In the model you suggest, it is only the initializer - the new keyword is used to create the object. This is inconsistent. If you only need initialization, you should use the bind() method.

> My understanding is that skins are views. Components are model/controllers.
> The view should not be loading user data and other child content into the
> mode/controller so I'm not sure I would agree that the skin should be doing
> this at all because part of the initialization is also Component data such
> as userData.

Skins shouldn't get involved in the model data, but they are allowed to add sub-components. For example, all composite component skins do this (Spinner, ScrollBar, Frame, etc.).

> With the editor, there are a few ways to do this. This is actually a very
> direct approach. In the thoughts below, I am still forced, at a minimum, to
> use an interface and for me to write code for wiring. I'm not against
> writing code but when the serializer can do it naturally, that's a win.

The problem is that the suggested modifications to the serializer are not natural because they don't fit in with the overall design of the framework.

> It took me awhile to understand why I
> had to always had to do extra work with includes or setting left and right
> children in code until I realized that the serializer should be doing it for
> me.

Again, in frameworks that compile to classes, this makes sense. When I define MyClass.xaml and MyClass.cs, they are both combined such that the following both instantiates and initializes the class:

  MyClass myClass = new MyClass();

But this doesn't work for BXMLSerializer.



RE: [jira] Resolved: (PIVOT-542) enable the serializer to initialize components written in java code

Posted by aappddeevv <aa...@verizon.net>.
A few thoughts:

The seriliazer already plays the initialization role.  You just mentioned a
bunch of alternatives that are simpler using this approach actually. Using
bxml:include and adding it to the host component (1 up) is a lot less
natural than "just use the class name like everywhere else" to use the
component.

My understanding is that skins are views. Components are model/controllers.
The view should not be loading user data and other child content into the
mode/controller so I'm not sure I would agree that the skin should be doing
this at all because part of the initialization is also Component data such
as userData.

With the editor, there are a few ways to do this. This is actually a very
direct approach. In the thoughts below, I am still forced, at a minimum, to
use an interface and for me to write code for wiring. I'm not against
writing code but when the serializer can do it naturally, that's a win.

This is not a big thought improvement, but incremental. It feels very
natural approach. I personally found the other approaches to be more
difficult (not impossible though).  It took me awhile to understand why I
had to always had to do extra work with includes or setting left and right
children in code until I realized that the serializer should be doing it for
me. The serializer needs a root, why not let the programmer insert the root
and have the serializer build around it.  After all that's what the
programmer is forced to do manually anyway.

I'm not sure that XAML compiles to classes actually. I think it just
compiles to binary XML then loads it in a partial class that you cannot see.
Then the WPF classes all call InitializeComponent() in their constructor. I
don't know the details of WPF though. I'll look at MXML, had not heard of
it.

Thanks for your thoughts.


-----Original Message-----
From: Greg Brown (JIRA) [mailto:jira@apache.org] 
Sent: Wednesday, June 23, 2010 1:06 PM
To: dev@pivot.apache.org
Subject: [jira] Resolved: (PIVOT-542) enable the serializer to initialize
components written in java code


     [
https://issues.apache.org/jira/browse/PIVOT-542?page=com.atlassian.jira.plug
in.system.issuetabpanels:all-tabpanel ]

Greg Brown resolved PIVOT-542.
------------------------------

    Resolution: Won't Fix

OK, thanks for the example. I hate to say it, but even after seeing how it
might be used in practice, I'm still not a fan of the approach. As I
mentioned in another thread, the recommended way to create a custom
component is to also create a custom skin that goes with it. So, I'd expect
to see an EditorSkin class that uses BXMLSerializer internally to load and
bind() to its content. Alternatively, you could have your Editor class
implement Bindable and use <bxml:include> to add it to the host component
(Bindable is effectively the equivalent of "code-behind" in Pivot).

If you don't want to create a custom skin and don't want to use an include,
you could still use BXMLSerializer in the Editor constructor to load the
left and right panes and set them via setLeft() and setRight(). After
loading each pane, you could call bind() on the editor instance (this) to
attach any values declared in the includes to the Editor instance.

While what you suggest makes sense for frameworks that compile XML to
classes (e.g. MXML, XAML), it just isn't consistent with the serializer
concept. Serializers take an input stream and return an object. The object
that creates the serializer isn't meant to also be the object that is
instantiated by the serializer. That's just a little too convoluted.

Thanks for the submission, though.


> enable the serializer to initialize components written in java code
> -------------------------------------------------------------------
>
>                 Key: PIVOT-542
>                 URL: https://issues.apache.org/jira/browse/PIVOT-542
>             Project: Pivot
>          Issue Type: Improvement
>            Reporter: Appddevvv
>         Attachments: initialize-examples.zip,
WTKXSerializer-with-initialize.patch
>
>
> The current serializer performs two funtions: creating objects and
initializing them. The typical use case is to create your component (say
java code) then call the serializer to create the content. Then within your
class, attach the content and initialize your object in various application
specific ways. However, since your object is typically a java object and
often a Component subclass, for those writing new components as composites
of others, you have to manually write some (not all) initialization code
that could also be performed in the BXML file. 
> To initialize your object using bxml content, you can use annotations etc.
However, if the bxml file also defines user data or other elements, you also
have to manually bring that in from the bxml and do some wiring. In
addition, it is currently impossible to initialize some pivot objects that
you subclass from, say the splitpane, with content from bxml without having
to create an intermediate container or use two bxml files for the left and
right child. For example, if you subclass from SplitPane, an underlying bxml
file that holds your content must have another container in order to define
your left and right children in or you have to use two separate bxml files
per child--this may or may not be a good thing and complicates the
implementation.
> To support the use case of creating subclasses of Components (and pivot
likes to use OO inheritance) and allowing the initialization of that
component to be matched by a bxml file, the serializer needs to be able to
"apply" itself to the component as if the bxml file and the subclassed
component were a reflection of the other. Bindable was designed to help with
this, however, the bxml file is still considered at level below (the
content) of the Component you are writing.
> The benefits are:
> a) A cleaner code style that has implied semantics--i.e. this bxml file is
the mirror image of your subclassed component at the same logical tree
level.
> b) More consistent coding conventions for novice programmers.
> The capability to do this can be implemented in different ways including
the current approaches of course. The small patch allows a new style of
Component creation blending code and bxml in a more seamless way. Its no
longer something you instantiate to "get" content, it is the content. It
helps Component writers who want to simply subclass another component. It
looks like a trivial change but it is a different perspective on
initialization that has natural semantics for programmers. It also reduces
complexity for creating subclasses of Components that have properties
representing the tree e.g. SplitPane.
> This is similar in spirit to "code-behind" in other frameworks.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.