Add preview_open and preview_close events to Gallery (#10303)

* Add preview_open and preview_close events to Gallery

* add changeset

* notebooks

* trigger change when upload

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
This commit is contained in:
Freddy Boulton 2025-01-08 15:25:47 -05:00 committed by GitHub
parent 6b63fdec44
commit f19ca89cdd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 55 additions and 14 deletions

View File

@ -0,0 +1,6 @@
---
"@gradio/gallery": minor
"gradio": minor
---
feat:Add preview_open and preview_close events to Gallery

View File

@ -1 +1 @@
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: gallery_component_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " files = [\n", " \"https://gradio-builds.s3.amazonaws.com/assets/cheetah-003.jpg\",\n", " \"https://gradio-static-files.s3.amazonaws.com/world.mp4\",\n", " \"https://gradio-builds.s3.amazonaws.com/assets/TheCheethcat.jpg\",\n", " ]\n", " with gr.Row():\n", " with gr.Column():\n", " gal = gr.Gallery(columns=4, interactive=True, label=\"Input Gallery\")\n", " btn = gr.Button()\n", " with gr.Column():\n", " output_gal = gr.Gallery(columns=4, interactive=True, label=\"Output Gallery\")\n", " with gr.Row():\n", " textbox = gr.Json(label=\"uploaded files\")\n", " num_upload = gr.Number(value=0, label=\"Num Upload\")\n", " num_change = gr.Number(value=0, label=\"Num Change\")\n", " select_output = gr.Textbox(label=\"Select Data\")\n", " gal.upload(lambda v,n: (v, v, n+1), [gal, num_upload], [textbox, output_gal, num_upload])\n", " gal.change(lambda v,n: (v, v, n+1), [gal, num_change], [textbox, output_gal, num_change])\n", "\n", " btn.click(lambda: files, None, [output_gal])\n", "\n", " def select(select_data: gr.SelectData):\n", " return select_data.value['image']['url'] if 'image' in select_data.value else select_data.value['video']['url']\n", "\n", " output_gal.select(select, None, select_output)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: gallery_component_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " files = [\n", " \"https://gradio-builds.s3.amazonaws.com/assets/cheetah-003.jpg\",\n", " \"https://gradio-static-files.s3.amazonaws.com/world.mp4\",\n", " \"https://gradio-builds.s3.amazonaws.com/assets/TheCheethcat.jpg\",\n", " ]\n", " with gr.Row():\n", " with gr.Column():\n", " gal = gr.Gallery(columns=4, interactive=True, label=\"Input Gallery\")\n", " btn = gr.Button()\n", " with gr.Column():\n", " output_gal = gr.Gallery(columns=4, interactive=True, label=\"Output Gallery\")\n", " with gr.Row():\n", " textbox = gr.Json(label=\"uploaded files\")\n", " num_upload = gr.Number(value=0, label=\"Num Upload\")\n", " num_change = gr.Number(value=0, label=\"Num Change\")\n", " preview_open = gr.Number(value=0, label=\"Preview Open?\")\n", " select_output = gr.Textbox(label=\"Select Data\")\n", " gal.upload(lambda v,n: (v, v, n+1), [gal, num_upload], [textbox, output_gal, num_upload])\n", " gal.change(lambda v,n: (v, v, n+1), [gal, num_change], [textbox, output_gal, num_change])\n", " output_gal.preview_open(lambda: 1, inputs=None, outputs=preview_open)\n", " output_gal.preview_close(lambda: 0, inputs=None, outputs=preview_open)\n", "\n", " btn.click(lambda: files, None, [output_gal])\n", "\n", " def select(select_data: gr.SelectData):\n", " return select_data.value['image']['url'] if 'image' in select_data.value else select_data.value['video']['url']\n", "\n", " output_gal.select(select, None, select_output)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}

View File

@ -16,9 +16,12 @@ with gr.Blocks() as demo:
textbox = gr.Json(label="uploaded files")
num_upload = gr.Number(value=0, label="Num Upload")
num_change = gr.Number(value=0, label="Num Change")
preview_open = gr.Number(value=0, label="Preview Open?")
select_output = gr.Textbox(label="Select Data")
gal.upload(lambda v,n: (v, v, n+1), [gal, num_upload], [textbox, output_gal, num_upload])
gal.change(lambda v,n: (v, v, n+1), [gal, num_change], [textbox, output_gal, num_change])
output_gal.preview_open(lambda: 1, inputs=None, outputs=preview_open)
output_gal.preview_close(lambda: 0, inputs=None, outputs=preview_open)
btn.click(lambda: files, None, [output_gal])

View File

@ -24,7 +24,7 @@ from gradio_client.utils import is_http_url_like
from gradio import image_utils, processing_utils, utils, wasm_utils
from gradio.components.base import Component
from gradio.data_classes import FileData, GradioModel, GradioRootModel, ImageData
from gradio.events import Events
from gradio.events import EventListener, Events
from gradio.exceptions import Error
if TYPE_CHECKING:
@ -57,7 +57,19 @@ class Gallery(Component):
Demos: fake_gan
"""
EVENTS = [Events.select, Events.upload, Events.change]
EVENTS = [
Events.select,
Events.upload,
Events.change,
EventListener(
"preview_close",
doc="This event is triggered when the Gallery preview is closed by the user",
),
EventListener(
"preview_open",
doc="This event is triggered when the Gallery preview is opened by the user",
),
]
data_model = GalleryData

View File

@ -46,6 +46,8 @@
error: string;
prop_change: Record<string, any>;
clear_status: LoadingStatus;
preview_open: never;
preview_close: never;
}>;
export let show_fullscreen_button = true;
@ -112,6 +114,7 @@
const files = Array.isArray(e.detail) ? e.detail : [e.detail];
value = await process_upload_files(files);
gradio.dispatch("upload", value);
gradio.dispatch("change", value);
}}
on:error={({ detail }) => {
loading_status = loading_status || {};
@ -127,6 +130,8 @@
on:select={(e) => gradio.dispatch("select", e.detail)}
on:share={(e) => gradio.dispatch("share", e.detail)}
on:error={(e) => gradio.dispatch("error", e.detail)}
on:preview_open={() => gradio.dispatch("preview_open")}
on:preview_close={() => gradio.dispatch("preview_close")}
{label}
{show_label}
{columns}

View File

@ -16,14 +16,7 @@
import { tick } from "svelte";
import type { GalleryImage, GalleryVideo } from "../types";
import {
Download,
Image as ImageIcon,
Maximize,
Minimize,
Clear,
Play
} from "@gradio/icons";
import { Download, Image as ImageIcon, Clear, Play } from "@gradio/icons";
import { FileData } from "@gradio/client";
import { format_gallery_for_sharing } from "./utils";
import type { I18nFormatter } from "@gradio/utils";
@ -56,6 +49,8 @@
const dispatch = createEventDispatcher<{
change: undefined;
select: SelectData;
preview_open: undefined;
preview_close: undefined;
}>();
// tracks whether the value of the gallery was reset
@ -287,7 +282,10 @@
<IconButton
Icon={Clear}
label="Close"
on:click={() => (selected_index = null)}
on:click={() => {
selected_index = null;
dispatch("preview_close");
}}
/>
{/if}
</IconButtonWrapper>
@ -388,7 +386,12 @@
<button
class="thumbnail-item thumbnail-lg"
class:selected={selected_index === i}
on:click={() => (selected_index = i)}
on:click={() => {
if (selected_index === null && allow_preview) {
dispatch("preview_open");
}
selected_index = i;
}}
aria-label={"Thumbnail " + (i + 1) + " of " + resolved_value.length}
>
{#if "image" in entry}

View File

@ -46,6 +46,18 @@ test("Gallery click-to-upload, upload and change events work correctly", async (
]);
await expect(page.getByLabel("Num Upload")).toHaveValue("1");
await page.getByLabel("Clear").first().click();
await expect(page.getByLabel("Num Change")).toHaveValue("1");
await page.getByLabel("Clear").first().click();
await expect(page.getByLabel("Num Change")).toHaveValue("2");
});
test("Gallery preview_open and close events work correctly", async ({
page
}) => {
await page.getByRole("button", { name: "Run" }).click();
await page.getByLabel("Thumbnail 2 of 3").click();
await expect(page.getByLabel("Preview Open?")).toHaveValue("1");
await page.getByLabel("Close").click();
await expect(page.getByLabel("Preview Open?")).toHaveValue("0");
});