glsp icon indicating copy to clipboard operation
glsp copied to clipboard

Ensure rendering control shapes on top ("z-index")

Open planger opened this issue 3 years ago • 4 comments

SVG uses a "painters model" to determine the z-index of elements. That is, elements that are below in the document will be drawn on top of the already drawn elements (painting over already painted top down). Now in Sprotty and GLSP, we often use additional SVG elements for rendering control shapes (e.g. resize handles, issue markers) and add those as part of the elements they concern. Now, however, elements that are below these other elements that contain control shapes will have a higher z-index, which leads to weird cases as a user would expect those control shapes and visual feedback of e.g. currently moved elements, to be always on top.

Examples:

image

image

Due to the painters model, setting a z-index via CSS won't work.

We either need to ensure adding those elements at the end of the document, which would require to move them out of the element they are concerned with. This would add overhead, however, as we'd then programmatically need to move the "control shapes" along with their "main element".

Alternatively, we could render them in a separate SVG element (ie an actual HTML <svg>) on top -- sort of like a feedback/control layer. This <svg> could get a higher z-index and thus is ensured to be rendered on top. However, we would need to sync viewport changes of the diagram <svg> to ensure the feedback/control layer elements stay on the right position.

WDYT?

planger avatar Jan 14 '22 14:01 planger

After considering this a bit, I think the simplest way is to introduce a new SModelExtension named something like AttachableDecoration which has the property decoratedElement: SModelElement. As they reference the element to be decorated, they don't need to be added as children of the decorated element but can be placed as children of the SModelRoot and thereby control their z-index by putting them as last children.

To place them relative to the decorated elements, we could just add an IVNodePostprocessor that -- if the element is an AttachableDecoration -- fetches its decorated element, retrieves the decorated element's diagram position and adds a transform the VNode of the decoration, similar to the Sprotty DecorationPlacer. This way the decoration is moved alongside and placed relative to the decorated element.

This should work fine for resize handles and issue markers.

There is two more case, I can think of, which is (1) feedback edges and (2) moving elements.

  1. Feedback edges don't have a z-index problem, because the feedback edges are new elements that are added to the root, which makes them appear always on top. The same is true for the marquee rectangle. Both have no z-index problem.
  2. Moved elements however can have a z-index problem, because they are just moved, so if they happen to be a child of a container and moved to another container that has a higher z-index as the previous container, the moved element is rendered below the new container. I wonder whether we shouldn't follow the same approach as with edges for element moves: i.e. just adding a feedback element as a child of the root (and set the original moved element as invisible). Code-wise something similar has been done here: https://www.eclipse.org/glsp/gallery/#constrainedlayout (creating a ghost element that is completely detached from the GModel structure, added as the last direct child of the root thus always on top).

WDYT @tortmayr @martin-fleck-at @CamilleLetavernier?

planger avatar Mar 31 '22 15:03 planger

If Feedback/Handle visuals are part of the standard tree (Although closer to the root element, rather than nested inside of the tree structure), do we have a risk of elements "fighting" for z-index?

IIRC, Sprotty automatically reorders elements inside of the root (Especially, selected elements are placed on top, by moving them also to the end of their parent element - which may be the ModelRoot, I think). Could this conflict with Feedback z-index?

CamilleLetavernier avatar Apr 01 '22 07:04 CamilleLetavernier

Yeah, you are right. Sprotty indeed moves the selected child to the end of the parent's containment list on selection. That could indeed conflict with my proposed approach. Within one "layer" we'll always have this problem. But I guess at least across "layers" (the control shapes / feedback layer vs the normal layer), we should at least ensure that the z-index is as expected.

planger avatar Apr 01 '22 08:04 planger

https://github.com/eclipse/sprotty/issues/307

planger avatar Jul 26 '22 08:07 planger