[xwiki-dev] [ArchitectureV2] UI Interfaces
Catalin Hritcu
catalin.hritcu at gmail.com
Thu Mar 22 09:44:17 CET 2007
Hi Sergiu,
On 3/22/07, Sergiu Dumitriu <sergiu.dumitriu at gmail.com> wrote:
> Just to clarify some things which might cause confusion:
>
> On 3/20/07, Sergiu Dumitriu <sergiu.dumitriu at gmail.com > wrote:
> >
> >
> >
> > On 3/20/07, Vincent Massol <vincent at massol.net> wrote:
> > >
> > >
> > >
> > >
> > > On Mar 20, 2007, at 4:31 PM, Sergiu Dumitriu wrote:
> > >
> > > Hi,
> > >
> > > To me this seems to have too much Java. I was thinking of a more
> wiki-like solution, using documents, tags and POXO (plain old xwiki objects
> :p ).
> > >
> > >
> > >
> > > We can discuss pros and cons if you want. Could you explain the solution
> you would prefer over the one below and why?
> >
> >
> > XWiki promotes the idea that it allows easy collaborative web application
> development. Such an application might want to add an entry in the menu, or
> a [ del.icio.us] link to the document footer.
> > 1. If we require users to write a java class, compile it, package it in a
> jar and distribute it, then we lose the collaborative/online/easy parts.
> > 2. If we list a number of interfaces that can be extended, then we would
> probably have forgotten the document footer. So we limit the extension
> points drastically. On the other hand, if we do list all the extension
> points, then we'll have minor releases with something like "added an EP for
> this and that", and we'll have dozens of interfaces.
> > 3. I still dream of the wiki that supports importable xar-lets (well,
> named differently, as we agreed .xar is not a good extension), which can
> contribute anything, from simple pages to complete skins, interface
> elements, new classes/templates/sheets. Interface elements seem hard to add
> if we require java classes, right?
> >
> >
> > I have developed some Firefox extensions in the past, so I am a bit biased
> when I insist on taking a XUL-like approach. Here are some ideas (see also
> http://jira.xwiki.org/jira/browse/XWIKI-649 ):
> >
> > 1. Right now we are putting Interface Elements (IE for short, also stands
> for Interface Extension) manually in the current skin. The only thing
> aggregated are the panels. Each of these elements is put in a <div>, maybe
> with an id and class. In XUL, each element having an id is a possible
> extension point (EP for short). It would be hard to use divs and ids, that's
> why we should replace these with something like #startelement("id", "class")
> and #endelement("id" "class"). These macros create extension points, and
> they aggregate any content that wants to be included in here. (as a bonus,
> we can keep a stack of open elements, and when we close an element (with an
> id) we can automatically close the missing #endelement-s)
>
In your example you expanded #startelement some times to a div tag,
but some other time to an img tag (which was wrapped in a div just to
make things fit). This probably means in the end you would have a
#startelement("div" "id" "class") in the first case, and a
#startelement("img" "id" "class") in the second. So one more "tag"
argument.
To me this seems like reinventing HTML tags in Velocity. Why couldn't
we do it in plain HTML using id's and classes for the usual HTML
elements (not necessarily divs)? Every element that wants to be an
extension point could also have class "ep". At this point I don't see
why this wouldn't work. We could just pass the page first through a
very simple "extension renderer", which might even expand begin and
end tags to velocity #startelement-s and #endelement-s, and then leave
the work to Velocity.
The advantage of this would be a very simple syntax with which
designers are already used to (plain HTML), rather that one that looks
like HTML but with an awkward syntax.
> - Any one of "id" and "class" can be missing, but not both at the same time.
> - If an ID is used more than one time, then it is an interface error. We
> should provide either a namespace-like feature ("ns", "id", "class"), or
> require (recommend) a safe naming convention. However, we don't need another
> stack trace or not-so-user-friendly error message, we should just ignore
> this error, and the result is that both elements have the same extensions.
>
> >
> >
> > 2. An IE that wants to extend something can specify an id or/and class
> name, a position (before, after, at the begin, at the end), and some
> ordering hints. And the content, of course. What's more, an IE can add new
> EPs. In the wiki/velocity world, this is best accomplished using XObjects.
>
> - The content can be static text, velocity or groovy code, or a simple call
> to a java method (we still need a scripting language to make the call).
> - If an IE can add content to a class of elements, we need to make sure that
> the context is known. For example, if we make an extension that adds
> permalinks to comments, how do we identify the comment? This requires that
> each EP also list the context-dependent variables that are available, and
> these variables should have the same name under all skins.
> - XObject means XWiki document objects.
>
> >
> >
> > 2a. If we want to push things to an advanced level, we can make the
> selection not just by an id or classname, but something like (basic) XPath
> or like the css (basic) selectors.
> > 3. For java, we can create an interface equivalent to the EP XWiki class.
> This has the advantages that:
> > - it's only one interface, similar in Java and the wiki
> > - it can extend anything
>
> - This is an AND item, not an XOR one. So we have both wiki EP+IE, and java
> EP+IE, sharing the same structure. So the java interface looks like the wiki
> class, and a java implementation does the same thing as a wiki object.
> - "It can extend anything" means it can be an Interface Extension for any
> Extension point defined in the wiki or in another java interface component.
>
> >
> >
> > 4. #startelement and #endelement are implemented in java, by one or more
> components (at least one for java IE and one for wiki IE). In order to speed
> things up, we can make a cache of the extension points. When the platform
> start, it should search for the available extensions, and already prepare
> the list of elements to be added for each element. When startelement is
> called, don't search for anything, just flush the prepared list. We register
> a listener, so when a page is saved, check if it contains an IE object and
> update the affected list of extensions.
> > 5. We should document the extension points present in the skins. First of
> all, we should identify a core list of EPs that should exist in all skins,
> with the same id/class. Each skin can add new EPs, which must be documented,
> and we should warn (outside) developers that only core EPs are guaranteed to
> exist in all the skins.
>
> As I said above in another comment, each EP should also list the
> context-dependent variables that can be used, and when they can be used: at
> the start or/and at the end.
>
> >
> >
> > 6. Each xarlet/plugin should list in the documentation the EPs affected
> and the EPs added. We can have extensions (xarlets) that mainly add a new
> EP, which other xarlets can use (like greasemonkey does for firefox).
> >
> > WDYT?
> >
> > Sergiu
>
> An example is needed for a better understanding:
>
> Scenario: Comments currently don't have user pictures attached (not in the
> albatross skin). How does an extension that wants to add them work?
>
> Step 1: defining the extension points
> The comments should be defined as extension points
>
> #foreach($comment in $comments)
> #startelement("comment_${comment.number}" "comment")
> #startelement("" "commentauthor")${ comment.author} said: #endelement(""
> "commentauthor")
> #startelement("" "commentbody")${comment.content}#endelement(""
> "commentbody")
> #endelement("comment_${ comment.number}" "comment")
> #end
>
Here is how the same thing would look like in HTML:
#foreach($comment in $comments)
<div id="comment_${comment.number}" class="ep comment">
<div class="ep commentauthor">${ comment.author} said:</div>
<div class="commentbody">${comment.content}</div>
</div>
#end
To me it looks a lot cleaner since I don't have to care how these
things are handled internally. Maybe during processing everything is
expanded to the version using velocity macros Sergiu presented, but as
an interface designer why should I care about that?
Also notice that I left out the ep class for the "commentbody" just to
exemplify that it can be a lot easier done. In this case this would be
a normal div which nobody can extend (which probably makes sense in a
lot of cases).
> A comment is an extension point with the id of the form "comment_<number>"
> and the class "comment". It contains two sub-EPs, for the author and the
> content. The context dependent variable is $comment
>
> Step 2: defining the extension
> There should be a document named (for example) Extensions.CommentAvatar,
> with an attached object with the class Extensions.ExtensionClass
>
> object.name = Avatar for comments
> object.selector = .comment
> ( .class selects a class and #id selects an id )
> object.position = start
> object.orderRules = first
> object.content = #startelement(""
> "commentavatar")$xwiki.getAvatar($comment.author)#endelement(""
> "commentavatar")
>
What about something like this?
object.content=<img src="$xwiki.getAvatar($comment.author)" class="ep
commentavatar"/>
> Note that this avatar is also an extension point, so another extension can
> put something around the avatar.
>
> Step 3: how things work
> The core component managing extension points and interface extensions will
> detect the fact that Extensions.CommentAvatar is an InterfaceExtension and
> will register it for the elements having the class "comment"
> (object.selector). It also knows that it must be placed at the start of the
> comment (object.position ) and if no other extensions ask to be placed
> first, it will be the first one to be added (object.orderRules).
>
> When the rendering engine interprets the #startelement macro, it will
> trigger the extension insertion mechanism.
> - First the list of extensions to be placed before the EP is inserted (none
> here)
> - First the html code for an element start is printed : <div id="comment_2"
> class="comment">
> - Then the list of extension that are to be placed at the start of an
> element (but inside) are inserted. In this case, CommentsAvatar. The content
> of the object.content is parsed and then it is copied to the output. We need
> to parse it first because it contains velocity code that must be executed.
> Because it also defines an EP, there will be a recursive call following the
> same stes. Result: <div class="commentavatar"><img src=" my.png"/></div>
> - The content of the comment is parsed. Result: <div
> class="commentauthor">John Doe</div><div class="commentbody">Nice
> thing!</div>
> - The list of extension to be placed at the end of the extension point is
> inserted. None in this case
> - The end element is printed: </div>
> - The list of extension to be placed after the extension point is inserted.
> None in this case
>
>
> So we saw:
> - how easy it is to define a new EP (just use #startelement instead of <div
> id="">)
> - what an wiki IE looks like (a simple wiki object)
> - how an IE tells what it wants to extend (selector, position, orderRules
> properties of the object)
> - how the insertion algorithm works (outputting the list of extensions
> before and after the start tag, before and after the end tag of the element)
>
> Using a java extension is pretty much the same, but instead of using a wiki
> object, we make a class implementing the InterfaceExtension interface,
> having getters with the same name as the wiki object (getName, getSelector,
> getContent...)
>
> Hope this clears the fog a bit...
>
> Sergiu
>
> --
Am I missing something ?
Catalin
More information about the devs
mailing list