From 26369d54fbd8f99176655f4062b56575c422c753 Mon Sep 17 00:00:00 2001
From: neozhaoliang <mathzhaoliang@gmail.com>
Date: Tue, 15 Mar 2022 13:49:21 +0800
Subject: [PATCH 1/8] add taichi gallery command

---
 MANIFEST.in            |  2 +-
 python/taichi/_main.py | 76 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/MANIFEST.in b/MANIFEST.in
index cbc8a16b7dc89..d9c29fe03e974 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -4,7 +4,7 @@ include python/*.txt
 include python/*.py
 include *.cfg
 include python/taichi/*.md
-include python/taichi/assets/*
+recursive-include python/taichi/assets *
 recursive-include python/taichi/examples *.py
 include python/taichi/_lib/core/*.so
 include python/taichi/_lib/core/*.pyd
diff --git a/python/taichi/_main.py b/python/taichi/_main.py
index 254553f3ec841..d6685222089e8 100644
--- a/python/taichi/_main.py
+++ b/python/taichi/_main.py
@@ -9,6 +9,7 @@
 from collections import defaultdict
 from functools import wraps
 from pathlib import Path
+import glob
 
 import numpy as np
 from colorama import Fore
@@ -135,6 +136,81 @@ def support_choice_with_dot_py(choice):
 
         return support_choice_with_dot_py
 
+    @register
+    def gallery(self, argumets: list = sys.argv[2:]):
+        # load the gallery image
+        image_source = utils.package_root + '/assets/**/ti_gallery.png'
+        print(image_source)
+        gallery_image_path = glob.glob(image_source, recursive=True)[0]
+        gallery_image = ti.tools.imread(gallery_image_path)
+        width, height = gallery_image.shape[:2]
+
+        # create the gui, 2x4 tiles
+        gui = ti.GUI("Taichi Gallery", res=(width, height))
+        nrows = 2
+        ncols = 4
+
+        # set the spacing parameters in the gallery image
+        left_margin = 7
+        bottom_margin = 23
+        vertical_margin = 32
+        horizontal_margin = 11
+        tile_size = 128
+
+        # side length of a tile
+        dx = tile_size / width
+        dy = tile_size / height
+
+        examples = ["sdf_renderer", "cornell_box", "rasterizer", "euler",
+                    "fractal", "mpm128", "pbf2d", "mass_spring_game"]
+
+        def get_tile_from_mouse(mou_x, mou_y):
+            """Find the image tile of which the mouse is hovering over."""
+            x = int(mou_x * width)
+            y = int(mou_y * height)
+            rind = (y - bottom_margin) // (vertical_margin + tile_size)
+            cind = (x - left_margin) // (vertical_margin + tile_size)
+            valid =  (0 <= rind < nrows and 0 <= cind < ncols)
+            return valid, rind, cind
+
+        def draw_bounding_box(rind, cind):
+            x0 = cind * (horizontal_margin + tile_size) + left_margin
+            y0 = rind * (vertical_margin + tile_size) + bottom_margin
+            x0 /= width
+            y0 /= height
+            pts = [(x0, y0), (x0 + dx, y0), (x0 + dx, y0 + dy), (x0, y0 + dy), (x0, y0)]
+            for i in range(4):
+                gui.line(pts[i], pts[i + 1], radius=2, color=0x0000FF)
+
+        def on_mouse_click_callback(example_name):
+            examples_dir = TaichiMain._get_examples_dir()
+            script = list(examples_dir.rglob(f"{example_name}.py"))[0]
+            with open(script, "r") as f:
+                try:
+                    import rich.syntax, rich.console
+                    content = rich.syntax.Syntax.from_path(script, line_numbers=True)
+                    console = rich.console.Console()
+                    console.print(content)
+                except ImportError:
+                    content = f.readlines()
+                    print(content)
+
+            self._exec_python_file(script)
+
+        while gui.running:
+            gui.set_image(gallery_image)
+            if gui.get_events(gui.MOTION):
+                mou_x, mou_y = gui.get_cursor_pos()
+                valid, rind, cind = get_tile_from_mouse(mou_x, mou_y)
+                if valid:
+                    draw_bounding_box(rind, cind)
+                    if gui.get_event(ti.GUI.PRESS, ti.GUI.LMB):
+                        gui.close()
+                        index = cind + rind * ncols
+                        on_mouse_click_callback(examples[index])
+
+            gui.show()
+
     @register
     def example(self, arguments: list = sys.argv[2:]):
         """Run an example by name (or name.py)"""

From 70be6e38184949b1988ef99bdccd55cc34e7ff3e Mon Sep 17 00:00:00 2001
From: neozhaoliang <mathzhaoliang@gmail.com>
Date: Tue, 15 Mar 2022 14:08:09 +0800
Subject: [PATCH 2/8] add taichi gallery command

---
 python/taichi/_main.py | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/python/taichi/_main.py b/python/taichi/_main.py
index d6685222089e8..b4fcc40194af2 100644
--- a/python/taichi/_main.py
+++ b/python/taichi/_main.py
@@ -140,7 +140,6 @@ def support_choice_with_dot_py(choice):
     def gallery(self, argumets: list = sys.argv[2:]):
         # load the gallery image
         image_source = utils.package_root + '/assets/**/ti_gallery.png'
-        print(image_source)
         gallery_image_path = glob.glob(image_source, recursive=True)[0]
         gallery_image = ti.tools.imread(gallery_image_path)
         width, height = gallery_image.shape[:2]
@@ -187,7 +186,7 @@ def on_mouse_click_callback(example_name):
             script = list(examples_dir.rglob(f"{example_name}.py"))[0]
             with open(script, "r") as f:
                 try:
-                    import rich.syntax, rich.console
+                    import rich.syntax, rich.console  # pylint: disable=C0415
                     content = rich.syntax.Syntax.from_path(script, line_numbers=True)
                     console = rich.console.Console()
                     console.print(content)

From ecc18db79e9abb71944fa60fe3bdbb9f6ea38a31 Mon Sep 17 00:00:00 2001
From: Taichi Gardener <taichigardener@gmail.com>
Date: Tue, 15 Mar 2022 06:10:24 +0000
Subject: [PATCH 3/8] Auto Format

---
 python/taichi/_main.py | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/python/taichi/_main.py b/python/taichi/_main.py
index b4fcc40194af2..22801a457bd93 100644
--- a/python/taichi/_main.py
+++ b/python/taichi/_main.py
@@ -1,4 +1,5 @@
 import argparse
+import glob
 import math
 import os
 import runpy
@@ -9,7 +10,6 @@
 from collections import defaultdict
 from functools import wraps
 from pathlib import Path
-import glob
 
 import numpy as np
 from colorama import Fore
@@ -160,8 +160,10 @@ def gallery(self, argumets: list = sys.argv[2:]):
         dx = tile_size / width
         dy = tile_size / height
 
-        examples = ["sdf_renderer", "cornell_box", "rasterizer", "euler",
-                    "fractal", "mpm128", "pbf2d", "mass_spring_game"]
+        examples = [
+            "sdf_renderer", "cornell_box", "rasterizer", "euler", "fractal",
+            "mpm128", "pbf2d", "mass_spring_game"
+        ]
 
         def get_tile_from_mouse(mou_x, mou_y):
             """Find the image tile of which the mouse is hovering over."""
@@ -169,7 +171,7 @@ def get_tile_from_mouse(mou_x, mou_y):
             y = int(mou_y * height)
             rind = (y - bottom_margin) // (vertical_margin + tile_size)
             cind = (x - left_margin) // (vertical_margin + tile_size)
-            valid =  (0 <= rind < nrows and 0 <= cind < ncols)
+            valid = (0 <= rind < nrows and 0 <= cind < ncols)
             return valid, rind, cind
 
         def draw_bounding_box(rind, cind):
@@ -177,7 +179,8 @@ def draw_bounding_box(rind, cind):
             y0 = rind * (vertical_margin + tile_size) + bottom_margin
             x0 /= width
             y0 /= height
-            pts = [(x0, y0), (x0 + dx, y0), (x0 + dx, y0 + dy), (x0, y0 + dy), (x0, y0)]
+            pts = [(x0, y0), (x0 + dx, y0), (x0 + dx, y0 + dy), (x0, y0 + dy),
+                   (x0, y0)]
             for i in range(4):
                 gui.line(pts[i], pts[i + 1], radius=2, color=0x0000FF)
 
@@ -186,8 +189,10 @@ def on_mouse_click_callback(example_name):
             script = list(examples_dir.rglob(f"{example_name}.py"))[0]
             with open(script, "r") as f:
                 try:
-                    import rich.syntax, rich.console  # pylint: disable=C0415
-                    content = rich.syntax.Syntax.from_path(script, line_numbers=True)
+                    import rich.console
+                    import rich.syntax  # pylint: disable=C0415
+                    content = rich.syntax.Syntax.from_path(script,
+                                                           line_numbers=True)
                     console = rich.console.Console()
                     console.print(content)
                 except ImportError:

From c51c56fc8ee4d84de1f4ebcd2b3c9415438f13a7 Mon Sep 17 00:00:00 2001
From: neozhaoliang <mathzhaoliang@gmail.com>
Date: Tue, 15 Mar 2022 14:11:44 +0800
Subject: [PATCH 4/8] add taichi gallery command

---
 external/assets | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/external/assets b/external/assets
index 41200548a168d..ff2ccc3f88901 160000
--- a/external/assets
+++ b/external/assets
@@ -1 +1 @@
-Subproject commit 41200548a168dcb975f35c80629f14eff3ea63f8
+Subproject commit ff2ccc3f889017519b86d980200efb4edb8c977d

From 12346efcf40d6b721817fcaec9df091a35999cc0 Mon Sep 17 00:00:00 2001
From: neozhaoliang <mathzhaoliang@gmail.com>
Date: Tue, 15 Mar 2022 14:59:24 +0800
Subject: [PATCH 5/8] add taichi gallery command

---
 python/taichi/_main.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python/taichi/_main.py b/python/taichi/_main.py
index 22801a457bd93..10559dd4e4215 100644
--- a/python/taichi/_main.py
+++ b/python/taichi/_main.py
@@ -189,7 +189,7 @@ def on_mouse_click_callback(example_name):
             script = list(examples_dir.rglob(f"{example_name}.py"))[0]
             with open(script, "r") as f:
                 try:
-                    import rich.console
+                    import rich.console  # pylint: disable=C0415
                     import rich.syntax  # pylint: disable=C0415
                     content = rich.syntax.Syntax.from_path(script,
                                                            line_numbers=True)

From 221a9ebe6be1ef034a25a832deb8ff35a7c77482 Mon Sep 17 00:00:00 2001
From: neozhaoliang <mathzhaoliang@gmail.com>
Date: Tue, 15 Mar 2022 15:12:25 +0800
Subject: [PATCH 6/8] add taichi gallery command

---
 external/assets | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/external/assets b/external/assets
index ff2ccc3f88901..150b16ad12ad5 160000
--- a/external/assets
+++ b/external/assets
@@ -1 +1 @@
-Subproject commit ff2ccc3f889017519b86d980200efb4edb8c977d
+Subproject commit 150b16ad12ad58a9a93b8988ded913e632a4df4f

From 12aaa7d587cf6d9a6072d93bfe6d49c18d74e33c Mon Sep 17 00:00:00 2001
From: neozhaoliang <mathzhaoliang@gmail.com>
Date: Tue, 15 Mar 2022 15:17:48 +0800
Subject: [PATCH 7/8] add taichi gallery command

---
 python/taichi/_main.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python/taichi/_main.py b/python/taichi/_main.py
index 10559dd4e4215..23ec789a5af50 100644
--- a/python/taichi/_main.py
+++ b/python/taichi/_main.py
@@ -166,7 +166,7 @@ def gallery(self, argumets: list = sys.argv[2:]):
         ]
 
         def get_tile_from_mouse(mou_x, mou_y):
-            """Find the image tile of which the mouse is hovering over."""
+            """Find the image tile that the mouse is hovering over."""
             x = int(mou_x * width)
             y = int(mou_y * height)
             rind = (y - bottom_margin) // (vertical_margin + tile_size)

From 72c6d684c8e589485909ed7862fc7940a05a3168 Mon Sep 17 00:00:00 2001
From: TiGeekMan <98569595+TiGeekMan@users.noreply.github.com>
Date: Tue, 15 Mar 2022 18:08:59 +0800
Subject: [PATCH 8/8] Update _main.py

---
 python/taichi/_main.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/python/taichi/_main.py b/python/taichi/_main.py
index 23ec789a5af50..a666f2b953de2 100644
--- a/python/taichi/_main.py
+++ b/python/taichi/_main.py
@@ -138,6 +138,7 @@ def support_choice_with_dot_py(choice):
 
     @register
     def gallery(self, argumets: list = sys.argv[2:]):
+        """Use mouse to select and run taichi examples in an interactive gui."""
         # load the gallery image
         image_source = utils.package_root + '/assets/**/ti_gallery.png'
         gallery_image_path = glob.glob(image_source, recursive=True)[0]