diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d0cf8cfad1f056650138d829780a09e1072f614..1689f5d92ed2306c7f80d790e1bbfd916a0cf8f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ## [1.4.1](https://stups.hhu-hosting.de/downloads/prob2-jupyter/prob2-jupyter-kernel-1.4.1-all.jar) * Updated to ProB 1.12.1 (ProB Java API version 4.12.1). +* `:show` now also supports VisB visualizations in addition to the classical `ANIMATION_FUNCTION`. ## [1.4.0](https://stups.hhu-hosting.de/downloads/prob2-jupyter/prob2-jupyter-kernel-1.4.0-all.jar) diff --git a/notebooks/tests/show.ipynb b/notebooks/tests/show.ipynb index b45afcf52ea0dee14eb92d79d1059d11834f9fc2..496f042ce0380a1c73d81d16cc14d46941b58797 100644 --- a/notebooks/tests/show.ipynb +++ b/notebooks/tests/show.ipynb @@ -12,15 +12,19 @@ ":show\n", "```\n", "\n", - "Show the machine's animation function visualisation for the current state.\n", + "Show the machine's visualization for the current state.\n", "\n", - "The visualisation is static, any defined right-click options cannot be viewed or used." + "Only the current state is visualized. Interactively executing operations is not supported.\n", + "\n", + "Both VisB and the classical `ANIMATION_FUNCTION` are supported. The visualization type is detected automatically (if both are defined, VisB is preferred)." ], "text/plain": [ ":show\n", - "Show the machine's animation function visualisation for the current state.\n", + "Show the machine's visualization for the current state.\n", + "\n", + "Only the current state is visualized. Interactively executing operations is not supported.\n", "\n", - "The visualisation is static, any defined right-click options cannot be viewed or used." + "Both VisB and the classical `ANIMATION_FUNCTION` are supported. The visualization type is detected automatically (if both are defined, VisB is preferred)." ] }, "execution_count": 1, @@ -59,10 +63,10 @@ "outputs": [ { "ename": "CommandExecutionException", - "evalue": ":show: Machine is not initialised, cannot show animation function visualisation", + "evalue": ":show: Model is not initialized, cannot show visualization (or no visualization is defined)", "output_type": "error", "traceback": [ - "\u001b[1m\u001b[31m:show: Machine is not initialised, cannot show animation function visualisation\u001b[0m" + "\u001b[1m\u001b[31m:show: Model is not initialized, cannot show visualization (or no visualization is defined)\u001b[0m" ] } ], @@ -97,10 +101,10 @@ "outputs": [ { "ename": "CommandExecutionException", - "evalue": ":show: Machine is not initialised, cannot show animation function visualisation", + "evalue": ":show: Model is not initialized, cannot show visualization (or no visualization is defined)", "output_type": "error", "traceback": [ - "\u001b[1m\u001b[31m:show: Machine is not initialised, cannot show animation function visualisation\u001b[0m" + "\u001b[1m\u001b[31m:show: Model is not initialized, cannot show visualization (or no visualization is defined)\u001b[0m" ] } ], @@ -165,7 +169,7 @@ "</tbody></table>" ], "text/plain": [ - "<Animation function visualisation>" + "<Animation function visualization>" ] }, "execution_count": 7, @@ -234,7 +238,7 @@ "</tbody></table>" ], "text/plain": [ - "<Animation function visualisation>" + "<Animation function visualization>" ] }, "execution_count": 9, @@ -303,7 +307,7 @@ "</tbody></table>" ], "text/plain": [ - "<Animation function visualisation>" + "<Animation function visualization>" ] }, "execution_count": 11, @@ -379,7 +383,7 @@ "</tbody></table>" ], "text/plain": [ - "<Animation function visualisation>" + "<Animation function visualization>" ] }, "execution_count": 13, @@ -498,7 +502,7 @@ "</tbody></table>" ], "text/plain": [ - "<Animation function visualisation>" + "<Animation function visualization>" ] }, "execution_count": 17, @@ -577,7 +581,7 @@ "</tbody></table>" ], "text/plain": [ - "<Animation function visualisation>" + "<Animation function visualization>" ] }, "execution_count": 19, @@ -657,7 +661,7 @@ "</tbody></table>" ], "text/plain": [ - "<Animation function visualisation>" + "<Animation function visualization>" ] }, "execution_count": 21, @@ -763,7 +767,7 @@ "</tbody></table>" ], "text/plain": [ - "<Animation function visualisation>" + "<Animation function visualization>" ] }, "execution_count": 25, diff --git a/src/main/java/de/prob2/jupyter/commands/ShowCommand.java b/src/main/java/de/prob2/jupyter/commands/ShowCommand.java index b1ef1842ea10bf826d5f56654b153b70da6daf33..e6a82ce30c567d79759d490a0f4fca8001f753dd 100644 --- a/src/main/java/de/prob2/jupyter/commands/ShowCommand.java +++ b/src/main/java/de/prob2/jupyter/commands/ShowCommand.java @@ -12,9 +12,12 @@ import com.google.inject.Provider; import de.prob.animator.command.GetAnimationMatrixForStateCommand; import de.prob.animator.command.GetImagesForMachineCommand; import de.prob.animator.command.GetPreferenceCommand; +import de.prob.animator.command.GetVisBHtmlForStates; +import de.prob.animator.command.GetVisBLoadedJsonFileCommand; +import de.prob.animator.command.LoadVisBCommand; import de.prob.animator.domainobjects.AnimationMatrixEntry; import de.prob.statespace.AnimationSelector; -import de.prob.statespace.Trace; +import de.prob.statespace.State; import de.prob2.jupyter.Command; import de.prob2.jupyter.ParameterCompleters; import de.prob2.jupyter.ParameterInspectors; @@ -26,6 +29,7 @@ import de.prob2.jupyter.UserErrorException; import io.github.spencerpark.jupyter.kernel.display.DisplayData; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public final class ShowCommand implements Command { private final @NotNull AnimationSelector animationSelector; @@ -56,29 +60,23 @@ public final class ShowCommand implements Command { @Override public @NotNull String getShortHelp() { - return "Show the machine's animation function visualisation for the current state."; + return "Show the machine's visualization for the current state."; } @Override public @NotNull String getHelpBody() { - return "The visualisation is static, any defined right-click options cannot be viewed or used."; + return "Only the current state is visualized. Interactively executing operations is not supported.\n\n" + + "Both VisB and the classical `ANIMATION_FUNCTION` are supported. The visualization type is detected automatically (if both are defined, VisB is preferred)."; } - @Override - public @NotNull DisplayData run(final @NotNull ParsedArguments args) { - final Trace trace = this.animationSelector.getCurrentTrace(); - - if (!trace.getCurrentState().isInitialised()) { - throw new UserErrorException("Machine is not initialised, cannot show animation function visualisation"); - } - + private @Nullable DisplayData getAnimationFunctionVisualization(final @NotNull State state) { final GetImagesForMachineCommand cmdImages = new GetImagesForMachineCommand(); - final GetAnimationMatrixForStateCommand cmdMatrix = new GetAnimationMatrixForStateCommand(trace.getCurrentState()); + final GetAnimationMatrixForStateCommand cmdMatrix = new GetAnimationMatrixForStateCommand(state); final GetPreferenceCommand cmdImagePadding = new GetPreferenceCommand("TK_CUSTOM_STATE_VIEW_PADDING"); final GetPreferenceCommand cmdStringPadding = new GetPreferenceCommand("TK_CUSTOM_STATE_VIEW_STRING_PADDING"); final GetPreferenceCommand cmdFontName = new GetPreferenceCommand("TK_CUSTOM_STATE_VIEW_FONT_NAME"); final GetPreferenceCommand cmdFontSize = new GetPreferenceCommand("TK_CUSTOM_STATE_VIEW_FONT_SIZE"); - trace.getStateSpace().execute( + state.getStateSpace().execute( cmdImages, cmdMatrix, cmdImagePadding, @@ -87,8 +85,8 @@ public final class ShowCommand implements Command { cmdFontSize ); - if (cmdMatrix.getMatrix() == null) { - throw new UserErrorException("No animation function visualisation available"); + if (cmdMatrix.getMatrix().isEmpty()) { + return null; } final Path machineDirectory = this.proBKernelProvider.get().getCurrentMachineDirectory(); @@ -146,11 +144,55 @@ public final class ShowCommand implements Command { } tableBuilder.append("\n</tbody></table>"); - final DisplayData result = new DisplayData("<Animation function visualisation>"); + final DisplayData result = new DisplayData("<Animation function visualization>"); result.putMarkdown(tableBuilder.toString()); return result; } + private static @Nullable DisplayData getVisBVisualization(final @NotNull State state) { + GetVisBLoadedJsonFileCommand loadedCmd = new GetVisBLoadedJsonFileCommand(); + state.getStateSpace().execute(loadedCmd); + + if (loadedCmd.getPath() == null) { + // Load VisB visualization defined inside the model itself + state.getStateSpace().execute(new LoadVisBCommand("")); + } + + state.getStateSpace().execute(loadedCmd); + if (loadedCmd.getPath() == null) { + // The model doesn't contain any VisB visualization + return null; + } + + GetVisBHtmlForStates htmlCmd = new GetVisBHtmlForStates(state); + state.getStateSpace().execute(htmlCmd); + + final DisplayData result = new DisplayData("<VisB visualization>"); + result.putHTML(htmlCmd.getHtml()); + return result; + } + + @Override + public @NotNull DisplayData run(final @NotNull ParsedArguments args) { + final State state = this.animationSelector.getCurrentTrace().getCurrentState(); + + final DisplayData visBResult = getVisBVisualization(state); + if (visBResult != null) { + return visBResult; + } + + DisplayData animationFunctionResult = this.getAnimationFunctionVisualization(state); + if (animationFunctionResult != null) { + return animationFunctionResult; + } + + if (state.isInitialised()) { + throw new UserErrorException("No VisB visualization or ANIMATION_FUNCTION defined in the model"); + } else { + throw new UserErrorException("Model is not initialized, cannot show visualization (or no visualization is defined)"); + } + } + @Override public @NotNull ParameterInspectors getParameterInspectors() { return ParameterInspectors.NONE;