Fit to screen on model update is unreliable
Whenever the model is updated I want to execute the FitToScreenAction. Currently I do this on the server side by implementing IModelUpdateListener and dispatching a FitToScreenAction (like in the flow example). This does seem to work sometimes, but often nothing happens.
The issue seems to be caused by a race between the FitToScreenAction and the InitializeCanvasBoundsAction. Because the FitToScreenAction depends on the canvas bounds, whenever the client receives the FitToScreenAction before the InitializeCanvasBoundsAction is executed, the model does not get fit to the screen.
Why is an InitializeCanvasBoundsAction triggered? That should happen only if the root element of the model is changed (different type or id). Is that the case in your application?
When the client is initialized, the model is requested from the server. It seems however that when the client receive a response from the server, the model if first set to the default empty model. Only after that it is set to the actual model received from the server.
This is what I get in the browser console (added some extra info):
GraphicsDiagramServer: sending "requestModel"
GraphicsDiagramServer: receiving "requestBounds"
ActionDispatcher: handle SetModelAction
CommandStack: Executing SetModelCommand
ActionDispatcher: Action is postponed due to block condition "requestBounds"
Viewer: rendering SModelRoot { id: "EMPTY", type: "NONE" }
ActionDispatcher: handle InitializeCanvasBoundsAction
CommandStack: Executing InitializeCanvasBoundsCommand
ActionDispatcher: handle "requestBounds"
CommandStack: Executing RequestBoundsCommand
Viewer: rendering hidden
Viewer: rendering SModelRoot { id: "EMPTY", type: "NONE" }
ActionDispatcher: handle ComputedBoundsAction
GraphicsDiagramServer: sending "computedBounds"
GraphicsDiagramServer: receiving "updateModel"
ActionDispatcher: handle "updateModel"
CommandStack: Executing UpdateModelCommand
Viewer: rendering SGraph { id: "my-diagram", type: "graph:mydiagram" }
ActionDispatcher: handle InitializeCanvasBoundsAction
CommandStack: Executing InitializeCanvasBoundsCommand
GraphicsDiagramServer: receiving "fit"
ActionDispatcher: handle "fit"
CommandStack: Executing FitToScreenCommand
Viewer: rendering SGraph { id: "my-diagram", type: "graph:mydiagram" }
Viewer: rendering SGraph { id: "my-diagram", type: "graph:mydiagram" }
Viewer: rendering SGraph { id: "my-diagram", type: "graph:mydiagram" }
Viewer: rendering SGraph { id: "my-diagram", type: "graph:mydiagram" }
Viewer: rendering SGraph { id: "my-diagram", type: "graph:mydiagram" }
Viewer: rendering SGraph { id: "my-diagram", type: "graph:mydiagram" }
Viewer: rendering SGraph { id: "my-diagram", type: "graph:mydiagram" }
Viewer: rendering SGraph { id: "my-diagram", type: "graph:mydiagram" }
ViewportAnimation: 64 fps
Viewer: rendering SGraph { id: "my-diagram", type: "graph:mydiagram" }
ActionDispatcher: handle InitializeCanvasBoundsAction
CommandStack: Executing InitializeCanvasBoundsCommand
Viewer: rendering SGraph { id: "my-diagram", type: "graph:mydiagram" }
ActionDispatcher: handle InitializeCanvasBoundsAction
CommandStack: Executing InitializeCanvasBoundsCommand
Viewer: rendering SGraph { id: "my-diagram", type: "graph:mydiagram" }
In this example the FitToScreen actually worked due to the InitializeCanvasBoundsAction before it. If the FitToScreen was received earlier it would not work
I understand. We might use the blockUntil property on UpdateModelCommand to block following actions until the InitializeCanvasBoundsAction is dispatched.