Skip to content

Commit f19ca89

Browse files
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 <[email protected]>
1 parent 6b63fde commit f19ca89

File tree

7 files changed

+55
-14
lines changed

7 files changed

+55
-14
lines changed

.changeset/ripe-pigs-attend.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@gradio/gallery": minor
3+
"gradio": minor
4+
---
5+
6+
feat:Add preview_open and preview_close events to Gallery
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +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}
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", " 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}

demo/gallery_component_events/run.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@
1616
textbox = gr.Json(label="uploaded files")
1717
num_upload = gr.Number(value=0, label="Num Upload")
1818
num_change = gr.Number(value=0, label="Num Change")
19+
preview_open = gr.Number(value=0, label="Preview Open?")
1920
select_output = gr.Textbox(label="Select Data")
2021
gal.upload(lambda v,n: (v, v, n+1), [gal, num_upload], [textbox, output_gal, num_upload])
2122
gal.change(lambda v,n: (v, v, n+1), [gal, num_change], [textbox, output_gal, num_change])
23+
output_gal.preview_open(lambda: 1, inputs=None, outputs=preview_open)
24+
output_gal.preview_close(lambda: 0, inputs=None, outputs=preview_open)
2225

2326
btn.click(lambda: files, None, [output_gal])
2427

gradio/components/gallery.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from gradio import image_utils, processing_utils, utils, wasm_utils
2525
from gradio.components.base import Component
2626
from gradio.data_classes import FileData, GradioModel, GradioRootModel, ImageData
27-
from gradio.events import Events
27+
from gradio.events import EventListener, Events
2828
from gradio.exceptions import Error
2929

3030
if TYPE_CHECKING:
@@ -57,7 +57,19 @@ class Gallery(Component):
5757
Demos: fake_gan
5858
"""
5959

60-
EVENTS = [Events.select, Events.upload, Events.change]
60+
EVENTS = [
61+
Events.select,
62+
Events.upload,
63+
Events.change,
64+
EventListener(
65+
"preview_close",
66+
doc="This event is triggered when the Gallery preview is closed by the user",
67+
),
68+
EventListener(
69+
"preview_open",
70+
doc="This event is triggered when the Gallery preview is opened by the user",
71+
),
72+
]
6173

6274
data_model = GalleryData
6375

js/gallery/Index.svelte

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
error: string;
4747
prop_change: Record<string, any>;
4848
clear_status: LoadingStatus;
49+
preview_open: never;
50+
preview_close: never;
4951
}>;
5052
export let show_fullscreen_button = true;
5153
@@ -112,6 +114,7 @@
112114
const files = Array.isArray(e.detail) ? e.detail : [e.detail];
113115
value = await process_upload_files(files);
114116
gradio.dispatch("upload", value);
117+
gradio.dispatch("change", value);
115118
}}
116119
on:error={({ detail }) => {
117120
loading_status = loading_status || {};
@@ -127,6 +130,8 @@
127130
on:select={(e) => gradio.dispatch("select", e.detail)}
128131
on:share={(e) => gradio.dispatch("share", e.detail)}
129132
on:error={(e) => gradio.dispatch("error", e.detail)}
133+
on:preview_open={() => gradio.dispatch("preview_open")}
134+
on:preview_close={() => gradio.dispatch("preview_close")}
130135
{label}
131136
{show_label}
132137
{columns}

js/gallery/shared/Gallery.svelte

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,7 @@
1616
import { tick } from "svelte";
1717
import type { GalleryImage, GalleryVideo } from "../types";
1818
19-
import {
20-
Download,
21-
Image as ImageIcon,
22-
Maximize,
23-
Minimize,
24-
Clear,
25-
Play
26-
} from "@gradio/icons";
19+
import { Download, Image as ImageIcon, Clear, Play } from "@gradio/icons";
2720
import { FileData } from "@gradio/client";
2821
import { format_gallery_for_sharing } from "./utils";
2922
import type { I18nFormatter } from "@gradio/utils";
@@ -56,6 +49,8 @@
5649
const dispatch = createEventDispatcher<{
5750
change: undefined;
5851
select: SelectData;
52+
preview_open: undefined;
53+
preview_close: undefined;
5954
}>();
6055
6156
// tracks whether the value of the gallery was reset
@@ -287,7 +282,10 @@
287282
<IconButton
288283
Icon={Clear}
289284
label="Close"
290-
on:click={() => (selected_index = null)}
285+
on:click={() => {
286+
selected_index = null;
287+
dispatch("preview_close");
288+
}}
291289
/>
292290
{/if}
293291
</IconButtonWrapper>
@@ -388,7 +386,12 @@
388386
<button
389387
class="thumbnail-item thumbnail-lg"
390388
class:selected={selected_index === i}
391-
on:click={() => (selected_index = i)}
389+
on:click={() => {
390+
if (selected_index === null && allow_preview) {
391+
dispatch("preview_open");
392+
}
393+
selected_index = i;
394+
}}
392395
aria-label={"Thumbnail " + (i + 1) + " of " + resolved_value.length}
393396
>
394397
{#if "image" in entry}

js/spa/test/gallery_component_events.spec.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,18 @@ test("Gallery click-to-upload, upload and change events work correctly", async (
4646
]);
4747

4848
await expect(page.getByLabel("Num Upload")).toHaveValue("1");
49-
await page.getByLabel("Clear").first().click();
5049
await expect(page.getByLabel("Num Change")).toHaveValue("1");
50+
await page.getByLabel("Clear").first().click();
51+
await expect(page.getByLabel("Num Change")).toHaveValue("2");
52+
});
53+
54+
test("Gallery preview_open and close events work correctly", async ({
55+
page
56+
}) => {
57+
await page.getByRole("button", { name: "Run" }).click();
58+
await page.getByLabel("Thumbnail 2 of 3").click();
59+
await expect(page.getByLabel("Preview Open?")).toHaveValue("1");
60+
61+
await page.getByLabel("Close").click();
62+
await expect(page.getByLabel("Preview Open?")).toHaveValue("0");
5163
});

0 commit comments

Comments
 (0)