From 104a312ab31fb4b51bd879edf1140b9860859e72 Mon Sep 17 00:00:00 2001 From: Dan Branley Date: Sun, 28 Jul 2024 15:49:19 -0400 Subject: [PATCH 1/4] feat: Display image in a graphics_card #1817 --- py/h2o_lightwave/h2o_lightwave/types.py | 30 ++++++++++++++++ py/h2o_lightwave/h2o_lightwave/ui.py | 9 +++++ py/h2o_wave/h2o_wave/types.py | 30 ++++++++++++++++ py/h2o_wave/h2o_wave/ui.py | 9 +++++ r/R/ui.R | 14 ++++++++ .../resources/templates/wave-components.xml | 5 ++- .../vscode-extension/component-snippets.json | 2 +- ui/src/graphics.test.tsx | 11 ++++++ ui/src/graphics.tsx | 36 +++++++++++++++---- 9 files changed, 137 insertions(+), 9 deletions(-) diff --git a/py/h2o_lightwave/h2o_lightwave/types.py b/py/h2o_lightwave/h2o_lightwave/types.py index 855b47747f..1b5af730e9 100644 --- a/py/h2o_lightwave/h2o_lightwave/types.py +++ b/py/h2o_lightwave/h2o_lightwave/types.py @@ -8984,12 +8984,18 @@ def __init__( scene: Optional[PackedData] = None, width: Optional[str] = None, height: Optional[str] = None, + path: Optional[str] = None, + image: Optional[str] = None, + type: Optional[str] = None, commands: Optional[List[Command]] = None, ): _guard_scalar('GraphicsCard.box', box, (str,), False, False, False) _guard_scalar('GraphicsCard.view_box', view_box, (str,), False, False, False) _guard_scalar('GraphicsCard.width', width, (str,), False, True, False) _guard_scalar('GraphicsCard.height', height, (str,), False, True, False) + _guard_scalar('GraphicsCard.path', path, (str,), False, True, False) + _guard_scalar('GraphicsCard.image', image, (str,), False, True, False) + _guard_scalar('GraphicsCard.type', type, (str,), False, True, False) _guard_vector('GraphicsCard.commands', commands, (Command,), False, True, False) self.box = box """A string indicating how to place this component on the page.""" @@ -9003,6 +9009,12 @@ def __init__( """The displayed width of the rectangular viewport. (Not the width of its coordinate system.)""" self.height = height """The displayed height of the rectangular viewport. (Not the height of its coordinate system.)""" + self.path = path + """The path or URL or data URL of the background image, e.g. `/foo.png` or `http://example.com/foo.png` or `data:image/png;base64,???`.""" + self.image = image + """Background image data, base64-encoded.""" + self.type = type + """The background image MIME subtype. One of `apng`, `bmp`, `gif`, `x-icon`, `jpeg`, `png`, `webp`. Required only if `image` is set.""" self.commands = commands """Contextual menu commands for this component.""" @@ -9012,6 +9024,9 @@ def dump(self) -> Dict: _guard_scalar('GraphicsCard.view_box', self.view_box, (str,), False, False, False) _guard_scalar('GraphicsCard.width', self.width, (str,), False, True, False) _guard_scalar('GraphicsCard.height', self.height, (str,), False, True, False) + _guard_scalar('GraphicsCard.path', self.path, (str,), False, True, False) + _guard_scalar('GraphicsCard.image', self.image, (str,), False, True, False) + _guard_scalar('GraphicsCard.type', self.type, (str,), False, True, False) _guard_vector('GraphicsCard.commands', self.commands, (Command,), False, True, False) return _dump( view='graphics', @@ -9021,6 +9036,9 @@ def dump(self) -> Dict: scene=self.scene, width=self.width, height=self.height, + path=self.path, + image=self.image, + type=self.type, commands=None if self.commands is None else [__e.dump() for __e in self.commands], ) @@ -9037,6 +9055,12 @@ def load(__d: Dict) -> 'GraphicsCard': _guard_scalar('GraphicsCard.width', __d_width, (str,), False, True, False) __d_height: Any = __d.get('height') _guard_scalar('GraphicsCard.height', __d_height, (str,), False, True, False) + __d_path: Any = __d.get('path') + _guard_scalar('GraphicsCard.path', __d_path, (str,), False, True, False) + __d_image: Any = __d.get('image') + _guard_scalar('GraphicsCard.image', __d_image, (str,), False, True, False) + __d_type: Any = __d.get('type') + _guard_scalar('GraphicsCard.type', __d_type, (str,), False, True, False) __d_commands: Any = __d.get('commands') _guard_vector('GraphicsCard.commands', __d_commands, (dict,), False, True, False) box: str = __d_box @@ -9045,6 +9069,9 @@ def load(__d: Dict) -> 'GraphicsCard': scene: Optional[PackedData] = __d_scene width: Optional[str] = __d_width height: Optional[str] = __d_height + path: Optional[str] = __d_path + image: Optional[str] = __d_image + type: Optional[str] = __d_type commands: Optional[List[Command]] = None if __d_commands is None else [Command.load(__e) for __e in __d_commands] return GraphicsCard( box, @@ -9053,6 +9080,9 @@ def load(__d: Dict) -> 'GraphicsCard': scene, width, height, + path, + image, + type, commands, ) diff --git a/py/h2o_lightwave/h2o_lightwave/ui.py b/py/h2o_lightwave/h2o_lightwave/ui.py index 46327b4518..885b09e077 100644 --- a/py/h2o_lightwave/h2o_lightwave/ui.py +++ b/py/h2o_lightwave/h2o_lightwave/ui.py @@ -3121,6 +3121,9 @@ def graphics_card( scene: Optional[PackedData] = None, width: Optional[str] = None, height: Optional[str] = None, + path: Optional[str] = None, + image: Optional[str] = None, + type: Optional[str] = None, commands: Optional[List[Command]] = None, ) -> GraphicsCard: """Create a card for displaying vector graphics. @@ -3132,6 +3135,9 @@ def graphics_card( scene: Foreground layer for rendering dynamic SVG elements. width: The displayed width of the rectangular viewport. (Not the width of its coordinate system.) height: The displayed height of the rectangular viewport. (Not the height of its coordinate system.) + path: The path or URL or data URL of the background image, e.g. `/foo.png` or `http://example.com/foo.png` or `data:image/png;base64,???`. + image: Background image data, base64-encoded. + type: The background image MIME subtype. One of `apng`, `bmp`, `gif`, `x-icon`, `jpeg`, `png`, `webp`. Required only if `image` is set. commands: Contextual menu commands for this component. Returns: A `h2o_wave.types.GraphicsCard` instance. @@ -3143,6 +3149,9 @@ def graphics_card( scene, width, height, + path, + image, + type, commands, ) diff --git a/py/h2o_wave/h2o_wave/types.py b/py/h2o_wave/h2o_wave/types.py index 855b47747f..1b5af730e9 100644 --- a/py/h2o_wave/h2o_wave/types.py +++ b/py/h2o_wave/h2o_wave/types.py @@ -8984,12 +8984,18 @@ def __init__( scene: Optional[PackedData] = None, width: Optional[str] = None, height: Optional[str] = None, + path: Optional[str] = None, + image: Optional[str] = None, + type: Optional[str] = None, commands: Optional[List[Command]] = None, ): _guard_scalar('GraphicsCard.box', box, (str,), False, False, False) _guard_scalar('GraphicsCard.view_box', view_box, (str,), False, False, False) _guard_scalar('GraphicsCard.width', width, (str,), False, True, False) _guard_scalar('GraphicsCard.height', height, (str,), False, True, False) + _guard_scalar('GraphicsCard.path', path, (str,), False, True, False) + _guard_scalar('GraphicsCard.image', image, (str,), False, True, False) + _guard_scalar('GraphicsCard.type', type, (str,), False, True, False) _guard_vector('GraphicsCard.commands', commands, (Command,), False, True, False) self.box = box """A string indicating how to place this component on the page.""" @@ -9003,6 +9009,12 @@ def __init__( """The displayed width of the rectangular viewport. (Not the width of its coordinate system.)""" self.height = height """The displayed height of the rectangular viewport. (Not the height of its coordinate system.)""" + self.path = path + """The path or URL or data URL of the background image, e.g. `/foo.png` or `http://example.com/foo.png` or `data:image/png;base64,???`.""" + self.image = image + """Background image data, base64-encoded.""" + self.type = type + """The background image MIME subtype. One of `apng`, `bmp`, `gif`, `x-icon`, `jpeg`, `png`, `webp`. Required only if `image` is set.""" self.commands = commands """Contextual menu commands for this component.""" @@ -9012,6 +9024,9 @@ def dump(self) -> Dict: _guard_scalar('GraphicsCard.view_box', self.view_box, (str,), False, False, False) _guard_scalar('GraphicsCard.width', self.width, (str,), False, True, False) _guard_scalar('GraphicsCard.height', self.height, (str,), False, True, False) + _guard_scalar('GraphicsCard.path', self.path, (str,), False, True, False) + _guard_scalar('GraphicsCard.image', self.image, (str,), False, True, False) + _guard_scalar('GraphicsCard.type', self.type, (str,), False, True, False) _guard_vector('GraphicsCard.commands', self.commands, (Command,), False, True, False) return _dump( view='graphics', @@ -9021,6 +9036,9 @@ def dump(self) -> Dict: scene=self.scene, width=self.width, height=self.height, + path=self.path, + image=self.image, + type=self.type, commands=None if self.commands is None else [__e.dump() for __e in self.commands], ) @@ -9037,6 +9055,12 @@ def load(__d: Dict) -> 'GraphicsCard': _guard_scalar('GraphicsCard.width', __d_width, (str,), False, True, False) __d_height: Any = __d.get('height') _guard_scalar('GraphicsCard.height', __d_height, (str,), False, True, False) + __d_path: Any = __d.get('path') + _guard_scalar('GraphicsCard.path', __d_path, (str,), False, True, False) + __d_image: Any = __d.get('image') + _guard_scalar('GraphicsCard.image', __d_image, (str,), False, True, False) + __d_type: Any = __d.get('type') + _guard_scalar('GraphicsCard.type', __d_type, (str,), False, True, False) __d_commands: Any = __d.get('commands') _guard_vector('GraphicsCard.commands', __d_commands, (dict,), False, True, False) box: str = __d_box @@ -9045,6 +9069,9 @@ def load(__d: Dict) -> 'GraphicsCard': scene: Optional[PackedData] = __d_scene width: Optional[str] = __d_width height: Optional[str] = __d_height + path: Optional[str] = __d_path + image: Optional[str] = __d_image + type: Optional[str] = __d_type commands: Optional[List[Command]] = None if __d_commands is None else [Command.load(__e) for __e in __d_commands] return GraphicsCard( box, @@ -9053,6 +9080,9 @@ def load(__d: Dict) -> 'GraphicsCard': scene, width, height, + path, + image, + type, commands, ) diff --git a/py/h2o_wave/h2o_wave/ui.py b/py/h2o_wave/h2o_wave/ui.py index 46327b4518..885b09e077 100644 --- a/py/h2o_wave/h2o_wave/ui.py +++ b/py/h2o_wave/h2o_wave/ui.py @@ -3121,6 +3121,9 @@ def graphics_card( scene: Optional[PackedData] = None, width: Optional[str] = None, height: Optional[str] = None, + path: Optional[str] = None, + image: Optional[str] = None, + type: Optional[str] = None, commands: Optional[List[Command]] = None, ) -> GraphicsCard: """Create a card for displaying vector graphics. @@ -3132,6 +3135,9 @@ def graphics_card( scene: Foreground layer for rendering dynamic SVG elements. width: The displayed width of the rectangular viewport. (Not the width of its coordinate system.) height: The displayed height of the rectangular viewport. (Not the height of its coordinate system.) + path: The path or URL or data URL of the background image, e.g. `/foo.png` or `http://example.com/foo.png` or `data:image/png;base64,???`. + image: Background image data, base64-encoded. + type: The background image MIME subtype. One of `apng`, `bmp`, `gif`, `x-icon`, `jpeg`, `png`, `webp`. Required only if `image` is set. commands: Contextual menu commands for this component. Returns: A `h2o_wave.types.GraphicsCard` instance. @@ -3143,6 +3149,9 @@ def graphics_card( scene, width, height, + path, + image, + type, commands, ) diff --git a/r/R/ui.R b/r/R/ui.R index 5d7cae0ddd..001fee1851 100644 --- a/r/R/ui.R +++ b/r/R/ui.R @@ -3639,6 +3639,11 @@ ui_frame_card <- function( #' (Not the width of its coordinate system.) #' @param height The displayed height of the rectangular viewport. #' (Not the height of its coordinate system.) +#' @param path The path or URL or data URL of the background image, +#' e.g. `/foo.png` or `http://example.com/foo.png` or `data:image/png;base64,???`. +#' @param image Background image data, base64-encoded. +#' @param type The background image MIME subtype. One of `apng`, `bmp`, `gif`, `x-icon`, `jpeg`, `png`, `webp`. +#' Required only if `image` is set. #' @param commands Contextual menu commands for this component. #' @return A GraphicsCard instance. #' @export @@ -3649,6 +3654,9 @@ ui_graphics_card <- function( scene = NULL, width = NULL, height = NULL, + path = NULL, + image = NULL, + type = NULL, commands = NULL) { .guard_scalar("box", "character", box) .guard_scalar("view_box", "character", view_box) @@ -3656,6 +3664,9 @@ ui_graphics_card <- function( # TODO Validate scene: Data .guard_scalar("width", "character", width) .guard_scalar("height", "character", height) + .guard_scalar("path", "character", path) + .guard_scalar("image", "character", image) + .guard_scalar("type", "character", type) .guard_vector("commands", "WaveCommand", commands) .o <- list( box=box, @@ -3664,6 +3675,9 @@ ui_graphics_card <- function( scene=scene, width=width, height=height, + path=path, + image=image, + type=type, commands=commands, view='graphics') class(.o) <- append(class(.o), c(.wave_obj, "WaveGraphicsCard")) diff --git a/tools/intellij-plugin/src/main/resources/templates/wave-components.xml b/tools/intellij-plugin/src/main/resources/templates/wave-components.xml index a0c89ee6af..3e2eefb8eb 100644 --- a/tools/intellij-plugin/src/main/resources/templates/wave-components.xml +++ b/tools/intellij-plugin/src/main/resources/templates/wave-components.xml @@ -1473,13 +1473,16 @@