Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Non-visual Tag Decorators
Summary
This design document is a draft and therefore tentative and subject to change.
JSP tags, and JavaServer Faces (JSF) tag in particular, have numerous non-visual nested tags that can change the appearance and behaviour of their parents. Consider the following JSF example:
<h:commandButton value="Submit"> <f:actionListener type="com.company.MyActionListener" /> </h:commandButton>
In this situation, an instance of 'com.company.MyActionListener' will be created and receive action events when the commandButton is pressed.
However, the 'f:actionListener' tag has no visual representation in HTML and so does not appear in the WYSIWYG editor. This forces a user to leave the visual environment and switch to a text or XML editor to:
- discover what nested non-visual tags are present
- learn the attribute settings of each non-visual tag
- select, modify and interact with these tags in the properties and outline views
We believe this is a usability problem that can be solved, at least partially, by using visual decorators.
Formal Statement of Requirements
The visual page designer shall support the ability for tags that support child tags that do not have a visual HTML representation to decorate their canvas image to aid the end-user in interacting with the child tags.
Basic requirements
The decorator design shall allow a user the ability to:
1.1: Quickly determine what non-visual child tags a visual tag contains.
1.2: Obtain a visual representation of the tag that has similar interaction capabilities as a visual tag on the canvas.
Usability requirements
In addition to the basic requirements, the following usability issues shall be addressed:
2.1: The decorators will be as non-intrusive as possible.
2.2: The end-user should be able control when decorators are available and hide them if they wish.
Technical requirements
3.1: The visual page designer is a GEF-based editor. The solution must be designed and implemented within that framework.
3.2: The solution must take into account the ITagConverter interface used to derive WYSIWYG rendering information from the source JSP/JSF markup.
Visual Design
The decorators are implemented as canvas feedback that can be pinned to the canvas through user interaction. A tag may expose its non-visual children through a new method on the ITagConverter interface (requirement 3.2). These children are absorbed as model children of the parent tag's EditPart. This causes the system to treat the non-visual parts as child EditParts (requirement 1.2). Note: this also means that as with visual elements, there is a one-to-one mapping between the elements exposed by a parent as model children and the edit parts that appear on the canvas.
To ensure that the non-visual decorators are non-intrusive (requirement 2.1), the visual figure (IFigure) representation of each child EditPart is moved to a visual editor layer instead of the figure for the parent Editpart as is normally the case.
Determination of Children
A user can quickly determine the non-visual children of a visual tag (requirement 1.1) by rolling the mouse over the visual tag's representation on the editor canvas. If there are visual children, a decorator will appear at the top-right corner as shown below for an h:commandButton JSF tag:
The above image shows an icon for an f:actionListener in a faded out (high transparency alpha channel) state to the top right of the command button, indicating that the button has such a child.
Decorator Access and Parent Selection
If the user wishes to interact with a nested child, they must first select the parent tag. When the user selects the command button there are two steps to visualization. Since the user may have selected the parent tag simply to edit it and not it's children, the icon does not immediately appear. Instead, a 'pin' affordance is shown and on first selection an animation shows the icons minimize into the pin, to show it can be used to access them:
Immediately after selection, the pin affordance and decorator image appear at the top-right of the selected element.
File:CommandButtonDecoratorResponseToSelection2.png
A short animation shows the decorator "minimizing" into pin affordance to imply that this is how the decorator may be accessed by the user.
Finally, at the end of the animation, only the pin affordance is shown.
Activating Decorators for Interaction
When the user mouses over the pin affordance, it becomes opaque to indicate that it is active and also shows a preview of the decorators. At this stage, the decorators are not selectable by the user:
The user is now able to toggle the pin affordance to "pin" or "unpin" the decorator figures to the canvas for interaction. The pin metaphor and icon are taken from the default GEF palette pinning concept to increase consistency and limited new visual concepts. Note that when pinned (shown below), the state of the pin image changes to give additional feedback. When the decorator becomes pinned, it can be moused over for feedback and selected:
When the icon is selected, it now acts the same (within the set configuration for the particular tag type) as any visual tag including synchronizing selection in the XML, property and outline views.
Unwinding Decorator State
The decorator state is unwound automatically when primary selection changes to an edit part other than one of the decorators or its direct parent. Also, by unpinning the decorators and moving the mouse off the pin affordance, the user can cause decorators to be removed from view.
Detailed Design
Four main areas are addressed in the technical design:
1) Modification of the ITagConverter/ElementEditPart classes to allow collection of non-visual children.
2) Addition of a NonVisualComponentEditPart edit part and modification of the system to accomodate its special needs.
3) Modification of the ElementResizableEditPolicy to control the feedback and interaction of the decorators.
4) Creation of a new visual framework for supporting the decorator and pin affordance controller.
Tag Conversion Changes
ElementEditPart's obtain their visual children for rendering through the ITagConverter.getChildModeList (sic) method. However, these model children are assumed to correspond to an HTML rendering. To support calculation of non-visual children, the following method is added to the ITagConverter interface:
/** * @return a list of Element tags that map to non-visual children * Type should be always be Element. */ public List getNonVisualChildren();
The method returns an empty list if there are no children. Each tag converter can determine which of it's host element's children to include.
The ElementEditPart is further modified to so that the framework detects the non-visual children and creates edit parts for them. The following is added to ElementEditPart.getModelChildren:
for (Iterator it = _tagConverter.getNonVisualChildren().iterator(); it.hasNext();) { Element nonVisualChild = (Element) it.next(); children.add(ConverterFactoryRegistry.getInstance().createTagConverter (nonVisualChild, IConverterFactory.MODE_DESIGNER, this.getDestDocumentForDesign())); }
Note that the children are added by their tag converters instead of as simple XML elements. This is necessary so that the HTMLEditPartsFactory can distinguish them as special so that the correct EditPart is created:
else if (model instanceof ITagConverter) { ITagConverter converter = (ITagConverter) model; if (!converter.isVisualByHTML()) { part = new NonVisualComponentEditPart(); } else { part = new ElementEditPart(); } }
TODO: does it make sense for all model children to wrapped in this way so that extra info can be passed to the editpart factory?
NonVisualComponentEditPart
The NonVisualComponentEditPart is the EditPart used to manipulate non-visual children. They exist as children of the EditPart corresponding to the JSP tag that contains them. However, visually, the figure shown in the view should not appear as a child of the parent EditPart as is the norm for ElementEditPart's. To achieve this, the ElementEditPart stores the child visuals in a separate visual container (IFigure). ElementEditPart.addChildVisual is modified to achieve this:
if (childEditPart instanceof NonVisualComponentEditPart) { getNonVisualElementBar().addNonVisualChild(((NonVisualComponentEditPart) childEditPart)); figureAdded = true; }
A special edit policy that address the special needs of the NonVisualComponentEditPart, called NonVisualChildGraphicalEditPolicy is created. The policy is intended to be very similar to ElementResizableEditPolicy so that EditPart behaviour is consistent, but it excludes a those things that don't make sense for non-visual children.
ElementResizableEditPolicy
ElementResizableEditPolicy is the primary edit policy for mouse interaction with ElementEditPart's (visual tag representations). The edit policy was modified to:
1) trigger the mouse-over feedback showing non-visual children on a visual tag.
2) trigger selection feedback (pin affordance and animation) on a visual tag that has children.
Decorator Visualization
The main controller for decorators is the pin affordance. The pin affordance is implemented in MouseSelectableChildDecorator. MouseSelectableChildDecorator controls showing and hiding the decorator menu ElementMenuBar as well managing user events. MouseSelectableChildDecorator obtains its ElementMenuBar from an ElementEditPart when it is constructed. Once constructed by the ElementResizableEditPolicy, MouseSelectableChildDecorator manages its own state.