diff --git a/py/examples/graphics_background.py b/py/examples/graphics_background.py new file mode 100644 index 0000000000..7727b6cb23 --- /dev/null +++ b/py/examples/graphics_background.py @@ -0,0 +1,19 @@ +# Graphics / Background Image +# Set a background image behind your #graphics. +# Original example: https://docs.python.org/3/library/turtle.html +# --- +from h2o_wave import site, ui, graphics as g + +t = g.turtle().f(100).r(90).pd() +for _ in range(36): + t.f(200).l(170) +spirograph = t.pu(1).path(stroke='red', fill='yellow') + +page = site['/demo'] +page['example'] = ui.graphics_card( + box='1 1 3 4', view_box='0 0 220 220', width='100%', height='100%', + scene=g.scene(foo=spirograph), + image_path='https://images.pexels.com/photos/1269968/pexels-photo-1269968.jpeg?auto=compress', +) + +page.save() diff --git a/py/examples/tour.conf b/py/examples/tour.conf index 8e52c5b338..4b2dbaa640 100644 --- a/py/examples/tour.conf +++ b/py/examples/tour.conf @@ -254,4 +254,5 @@ graphics_clock.py graphics_path.py graphics_turtle.py graphics_hilbert.py +graphics_background.py glider_gun.py diff --git a/py/h2o_lightwave/h2o_lightwave/types.py b/py/h2o_lightwave/h2o_lightwave/types.py index 855b47747f..39d71e6321 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, + image: Optional[str] = None, + image_path: Optional[str] = None, + image_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.image', image, (str,), False, True, False) + _guard_scalar('GraphicsCard.image_path', image_path, (str,), False, True, False) + _guard_scalar('GraphicsCard.image_type', image_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.image = image + """Background image data, base64-encoded.""" + self.image_path = image_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_type = image_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.image', self.image, (str,), False, True, False) + _guard_scalar('GraphicsCard.image_path', self.image_path, (str,), False, True, False) + _guard_scalar('GraphicsCard.image_type', self.image_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, + image=self.image, + image_path=self.image_path, + image_type=self.image_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_image: Any = __d.get('image') + _guard_scalar('GraphicsCard.image', __d_image, (str,), False, True, False) + __d_image_path: Any = __d.get('image_path') + _guard_scalar('GraphicsCard.image_path', __d_image_path, (str,), False, True, False) + __d_image_type: Any = __d.get('image_type') + _guard_scalar('GraphicsCard.image_type', __d_image_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 + image: Optional[str] = __d_image + image_path: Optional[str] = __d_image_path + image_type: Optional[str] = __d_image_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, + image, + image_path, + image_type, commands, ) diff --git a/py/h2o_lightwave/h2o_lightwave/ui.py b/py/h2o_lightwave/h2o_lightwave/ui.py index 46327b4518..6eda9f5844 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, + image: Optional[str] = None, + image_path: Optional[str] = None, + image_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.) + image: Background image data, base64-encoded. + image_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_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, + image, + image_path, + image_type, commands, ) diff --git a/py/h2o_wave/h2o_wave/types.py b/py/h2o_wave/h2o_wave/types.py index 855b47747f..39d71e6321 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, + image: Optional[str] = None, + image_path: Optional[str] = None, + image_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.image', image, (str,), False, True, False) + _guard_scalar('GraphicsCard.image_path', image_path, (str,), False, True, False) + _guard_scalar('GraphicsCard.image_type', image_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.image = image + """Background image data, base64-encoded.""" + self.image_path = image_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_type = image_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.image', self.image, (str,), False, True, False) + _guard_scalar('GraphicsCard.image_path', self.image_path, (str,), False, True, False) + _guard_scalar('GraphicsCard.image_type', self.image_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, + image=self.image, + image_path=self.image_path, + image_type=self.image_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_image: Any = __d.get('image') + _guard_scalar('GraphicsCard.image', __d_image, (str,), False, True, False) + __d_image_path: Any = __d.get('image_path') + _guard_scalar('GraphicsCard.image_path', __d_image_path, (str,), False, True, False) + __d_image_type: Any = __d.get('image_type') + _guard_scalar('GraphicsCard.image_type', __d_image_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 + image: Optional[str] = __d_image + image_path: Optional[str] = __d_image_path + image_type: Optional[str] = __d_image_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, + image, + image_path, + image_type, commands, ) diff --git a/py/h2o_wave/h2o_wave/ui.py b/py/h2o_wave/h2o_wave/ui.py index 46327b4518..6eda9f5844 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, + image: Optional[str] = None, + image_path: Optional[str] = None, + image_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.) + image: Background image data, base64-encoded. + image_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_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, + image, + image_path, + image_type, commands, ) diff --git a/r/R/ui.R b/r/R/ui.R index 5d7cae0ddd..450d48637f 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 image Background image data, base64-encoded. +#' @param image_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_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, + image = NULL, + image_path = NULL, + image_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("image", "character", image) + .guard_scalar("image_path", "character", image_path) + .guard_scalar("image_type", "character", image_type) .guard_vector("commands", "WaveCommand", commands) .o <- list( box=box, @@ -3664,6 +3675,9 @@ ui_graphics_card <- function( scene=scene, width=width, height=height, + image=image, + image_path=image_path, + image_type=image_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..5b93918c0a 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 @@