From a220a48da4a81b5f9c6b3635e3bfdaf4a9ee7fdc Mon Sep 17 00:00:00 2001 From: s233039 <s233039@student.dtu.dk> Date: Wed, 26 Jun 2024 12:05:28 +0200 Subject: [PATCH] Qim theme --- qim3d/css/gradio.css | 2 +- qim3d/gui/annotation_tool.py | 27 +++---- qim3d/gui/data_explorer.py | 41 +++++----- qim3d/gui/images/qim_platform-icon.svg | 104 ++++++++++++++++++++++++ qim3d/gui/iso3d.py | 23 +++--- qim3d/gui/local_thickness.py | 27 +++---- qim3d/gui/qim_theme.py | 106 +++++++++++++++++++++++++ qim3d/utils/cli.py | 12 +-- 8 files changed, 272 insertions(+), 70 deletions(-) create mode 100644 qim3d/gui/images/qim_platform-icon.svg create mode 100644 qim3d/gui/qim_theme.py diff --git a/qim3d/css/gradio.css b/qim3d/css/gradio.css index 9c424329..72407d14 100644 --- a/qim3d/css/gradio.css +++ b/qim3d/css/gradio.css @@ -351,7 +351,7 @@ input[type="range"]::-webkit-slider-thumb { /* Buttons */ .btn-html { position: sticky; - display: flex; + /* display: flex; */ justify-content: center; background: white !important; border-color: #6c757d !important; diff --git a/qim3d/gui/annotation_tool.py b/qim3d/gui/annotation_tool.py index 40b3fda8..a554b463 100644 --- a/qim3d/gui/annotation_tool.py +++ b/qim3d/gui/annotation_tool.py @@ -28,6 +28,10 @@ import gradio as gr import numpy as np import qim3d.utils from qim3d.io import load, save +from qim3d.io.logger import log +from .qim_theme import QimTheme +from pathlib import Path +import qim3d class Session: @@ -50,14 +54,12 @@ class Interface: self.temp_dir = os.path.join(tempfile.gettempdir(), f"qim-{self.username}") self.name_suffix = None - # CSS path - current_dir = os.path.dirname(os.path.abspath(__file__)) - self.css_path = os.path.join(current_dir, "..", "css", "gradio.css") - def launch(self, img=None, **kwargs): + + def launch(self, img=None, force_light_mode:bool = True, **kwargs): # Create gradio interfaces # img = "/tmp/qim-fima/2dimage.png" - self.interface = self.create_interface(img) + self.interface = self.create_interface(img, force_light_mode=force_light_mode) # Set gradio verbose level if self.verbose: @@ -69,6 +71,7 @@ class Interface: quiet=quiet, height=self.height, # width=self.width, + favicon_path = Path(qim3d.__file__).parents[0] / "gui/images/qim_platform-icon.svg", **kwargs, ) @@ -94,15 +97,9 @@ class Interface: def set_visible(self): return gr.update(visible=True) - def create_interface(self, img=None): - from PIL import Image - - if img is not None: - custom_css = "annotation-tool" - else: - custom_css = "annotation-tool no-img" + def create_interface(self, img=None, force_light_mode:bool = False): - with gr.Blocks(css=self.css_path, title=self.title) as gradio_interface: + with gr.Blocks(theme = QimTheme(force_light_mode = force_light_mode), title=self.title) as gradio_interface: brush = gr.Brush( colors=[ @@ -134,7 +131,6 @@ class Interface: show_download_button=True, container=False, transforms=["crop"], - elem_classes=custom_css, layers=False, ) @@ -142,13 +138,12 @@ class Interface: with gr.Row(): overlay_img = gr.Image( - show_download_button=False, show_label=False, visible=False, elem_classes="no-interpolation" + show_download_button=False, show_label=False, visible=False, ) with gr.Row(): masks_download = gr.File( label="Download masks", visible=False, - elem_classes=custom_css, ) temp_dir = gr.Textbox(value=self.temp_dir, visible=False) diff --git a/qim3d/gui/data_explorer.py b/qim3d/gui/data_explorer.py index a8b44701..a786d453 100644 --- a/qim3d/gui/data_explorer.py +++ b/qim3d/gui/data_explorer.py @@ -27,10 +27,13 @@ import matplotlib.pyplot as plt import numpy as np import outputformat as ouf import tifffile +from pathlib import Path +import qim3d from qim3d.io import load from qim3d.io.logger import log from qim3d.utils import internal_tools +from .qim_theme import QimTheme class Interface: @@ -49,9 +52,6 @@ class Interface: "Intensity histogram", "Data summary", ] - # CSS path - current_dir = os.path.dirname(os.path.abspath(__file__)) - self.css_path = os.path.join(current_dir, "..", "css", "gradio.css") def clear(self): """Used to reset outputs with the clear button""" @@ -77,14 +77,12 @@ class Interface: def set_spinner(self, message): return gr.update( - elem_classes="btn btn-spinner", value=f"{message}", interactive=False, ) def set_relaunch_button(self): return gr.update( - elem_classes="btn btn-run", value=f"Relaunch", interactive=True, ) @@ -98,8 +96,9 @@ class Interface: update_list.append(gr.update(visible=False)) return update_list - def create_interface(self): - with gr.Blocks(css=self.css_path) as gradio_interface: + def create_interface(self, force_light_mode:bool = True): + with gr.Blocks(theme = QimTheme(force_light_mode=force_light_mode), + title = self.title) as gradio_interface: gr.Markdown("# Data Explorer") # File selection and parameters @@ -112,12 +111,11 @@ class Interface: max_lines=1, container=False, label="Base path", - elem_classes="h-36", value=os.getcwd(), ) with gr.Column(scale=1, min_width=36): reload_base_path = gr.Button( - value="⟳", elem_classes="btn-html h-36" + value="⟳" ) explorer = gr.FileExplorer( ignore_glob="*/.*", # ignores hidden files @@ -126,7 +124,7 @@ class Interface: render=True, file_count="single", interactive=True, - elem_classes="h-320 hide-overflow", + height = 320, ) with gr.Column(scale=1): @@ -180,22 +178,22 @@ class Interface: ) with gr.Row(): btn_run = gr.Button( - value="Load & Run", elem_classes="btn btn-html btn-run" + value="Load & Run", variant = "primary", ) # Visualization and results - with gr.Row(elem_classes="mt-64"): + with gr.Row(): # Z Slicer with gr.Column(visible=False) as result_z_slicer: - zslice_plot = gr.Plot(label="Z slice", elem_classes="rounded") + zslice_plot = gr.Plot(label="Z slice") zpos = gr.Slider( minimum=0, maximum=1, value=0.5, step=0.01, label="Z position" ) # Y Slicer with gr.Column(visible=False) as result_y_slicer: - yslice_plot = gr.Plot(label="Y slice", elem_classes="rounded") + yslice_plot = gr.Plot(label="Y slice") ypos = gr.Slider( minimum=0, maximum=1, value=0.5, step=0.01, label="Y position" @@ -203,7 +201,7 @@ class Interface: # X Slicer with gr.Column(visible=False) as result_x_slicer: - xslice_plot = gr.Plot(label="X slice", elem_classes="rounded") + xslice_plot = gr.Plot(label="X slice") xpos = gr.Slider( minimum=0, maximum=1, value=0.5, step=0.01, label="X position" @@ -211,13 +209,13 @@ class Interface: # Z Max projection with gr.Column(visible=False) as result_z_max_projection: max_projection_plot = gr.Plot( - label="Z max projection", elem_classes="rounded" + label="Z max projection", ) # Z Min projection with gr.Column(visible=False) as result_z_min_projection: min_projection_plot = gr.Plot( - label="Z min projection", elem_classes="rounded" + label="Z min projection", ) # Intensity histogram @@ -230,7 +228,7 @@ class Interface: lines=24, label=None, show_label=False, - elem_classes="monospace-box", + value="Data summary", ) ### Gradio objects lists @@ -379,13 +377,13 @@ class Interface: return session, gr.update(label=f"X slice: {session.xslice}") - def launch(self, **kwargs): + def launch(self,force_light_mode:bool = True, **kwargs): # Show header if self.show_header: internal_tools.gradio_header(self.title, self.port) - # Create gradio interfaces - interface = self.create_interface() + # Create gradio interfaces + interface = self.create_interface(force_light_mode=force_light_mode) # Set gradio verbose level if self.verbose: @@ -397,6 +395,7 @@ class Interface: quiet=quiet, height=self.height, width=self.width, + favicon_path = Path(qim3d.__file__).parents[0] / "gui/images/qim_platform-icon.svg", **kwargs, ) diff --git a/qim3d/gui/images/qim_platform-icon.svg b/qim3d/gui/images/qim_platform-icon.svg new file mode 100644 index 00000000..b40bab5f --- /dev/null +++ b/qim3d/gui/images/qim_platform-icon.svg @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + width="8.3444281mm" + height="7.7738566mm" + viewBox="0 0 8.344428 7.7738567" + version="1.1" + id="svg1" + inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)" + sodipodi:docname="qim_platform-icon.svg" + inkscape:export-filename="qim_platform-icon.png" + inkscape:export-xdpi="779.25055" + inkscape:export-ydpi="779.25055" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview1" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" + inkscape:document-units="mm" + inkscape:zoom="3.1345226" + inkscape:cx="90.603908" + inkscape:cy="61.253347" + inkscape:window-width="1266" + inkscape:window-height="631" + inkscape:window-x="3830" + inkscape:window-y="56" + inkscape:window-maximized="0" + inkscape:current-layer="layer1" /> + <defs + id="defs1" /> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-49.212495,-93.140004)"> + <g + id="g95" + transform="matrix(1.0725239,0,0,1.0727401,-76.182898,-88.386314)" + style="stroke-width:0.932287"> + <path + id="path94" + style="fill:#ff9900;fill-opacity:1;stroke:none;stroke-width:0.443769;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" + d="m 117.13806,171.16039 v -1.08393 c 0,-0.35299 0.2857,-0.63715 0.64059,-0.63715 v 0 h 6.05523 c 0.35489,0 0.64059,0.28416 0.64059,0.63715 v 1.08393" + sodipodi:nodetypes="csscssc" /> + <path + id="rect75" + style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.443769;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" + d="m 117.13806,172.211 v -2.13454 c 0,-0.35299 0.2857,-0.63715 0.64059,-0.63715 v 0 h 6.05523 c 0.35489,0 0.64059,0.28416 0.64059,0.63715 v 3.9123" + sodipodi:nodetypes="csscssc" /> + <path + id="path76" + style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.443769;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" + d="m 124.47447,174.94459 v 0.66053 c 0,0.35299 -0.2857,0.63715 -0.64059,0.63715 h -6.05523 c -0.35489,0 -0.64059,-0.28416 -0.64059,-0.63715 v -2.43526" + sodipodi:nodetypes="cssssc" /> + <path + style="fill:#cd4d00;fill-opacity:1;stroke:#000000;stroke-width:0.443769;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" + d="m 118.00096,170.34725 h 0.28389" + id="path72" + sodipodi:nodetypes="cc" /> + <path + style="fill:#cd4d00;fill-opacity:1;stroke:#000000;stroke-width:0.443769;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" + d="m 120.63414,170.34725 h 2.93385" + id="path74" + sodipodi:nodetypes="cc" /> + <path + style="fill:#cd4d00;fill-opacity:1;stroke:#000000;stroke-width:0.443769;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" + d="m 119.04851,170.34725 h 0.28389" + id="path75" + sodipodi:nodetypes="cc" /> + <g + id="g93" + transform="matrix(0.36505828,0,0,0.35972642,83.784309,128.37775)" + style="stroke-width:2.57263"> + <path + id="path91" + d="m 100.83326,125.49607 -5.27832,2.18097 c -0.37814,0.14893 -0.41489,0.7496 -0.0409,0.91436 l 5.17239,2.13082 c 0.4877,0.18116 1.00239,0.18129 1.45479,0 l 5.17239,-2.13082 c 0.37397,-0.16476 0.33723,-0.76543 -0.0409,-0.91436 l -5.27831,-2.18097 c -0.44426,-0.18069 -0.70409,-0.18273 -1.1611,0 z" + fill="#ffab61" + paint-order="normal" + style="fill:#990000;fill-opacity:1;stroke:#000000;stroke-width:1.2246;stroke-dasharray:none;stroke-opacity:1" /> + <path + id="path92" + d="m 100.83326,123.02262 -5.27832,2.18097 c -0.37814,0.14893 -0.41489,0.7496 -0.0409,0.91436 l 5.17239,2.13082 c 0.4877,0.18116 1.00239,0.18129 1.45479,0 l 5.17239,-2.13082 c 0.37397,-0.16476 0.33723,-0.76543 -0.0409,-0.91436 l -5.27831,-2.18097 c -0.44426,-0.18069 -0.70409,-0.18272 -1.1611,0 z" + fill="#ffc861" + paint-order="normal" + style="fill:#cd4d00;fill-opacity:1;stroke:#000000;stroke-width:1.2246;stroke-dasharray:none;stroke-opacity:1" /> + <path + id="path93" + d="m 100.83325,120.5494 -5.27832,2.18098 c -0.37814,0.14893 -0.41489,0.7496 -0.0409,0.91436 l 5.17239,2.13082 c 0.4877,0.18115 1.00239,0.18128 1.45479,0 l 5.17239,-2.13082 c 0.37397,-0.16477 0.33723,-0.76544 -0.0409,-0.91436 l -5.27831,-2.18098 c -0.44426,-0.18069 -0.70409,-0.18271 -1.1611,0 z" + fill="#55a1ff" + paint-order="normal" + style="fill:#ff9900;fill-opacity:1;stroke:#000000;stroke-width:1.2246;stroke-dasharray:none;stroke-opacity:1" /> + </g> + </g> + </g> +</svg> diff --git a/qim3d/gui/iso3d.py b/qim3d/gui/iso3d.py index f6b0870d..ff154400 100644 --- a/qim3d/gui/iso3d.py +++ b/qim3d/gui/iso3d.py @@ -22,8 +22,11 @@ import os from qim3d.utils import internal_tools from qim3d.io import DataLoader from qim3d.io.logger import log +from .qim_theme import QimTheme import plotly.graph_objects as go from scipy import ndimage +from pathlib import Path +import qim3d class Interface: @@ -54,9 +57,6 @@ class Interface: [os.path.join(current_dir, *examples_dir, example)] ) - # CSS path - self.css_path = os.path.join(current_dir, "..", "css", "gradio.css") - def clear(self): """Used to reset the plot with the clear button""" return None @@ -210,10 +210,10 @@ class Interface: # as it otherwise is not deleted os.remove("iso3d.html") - def create_interface(self): + def create_interface(self, force_light_mode:bool = True): # Create gradio app - with gr.Blocks(css=self.css_path) as gradio_interface: + with gr.Blocks(theme = QimTheme(force_light_mode = force_light_mode), title = self.title) as gradio_interface: if self.show_header: gr.Markdown( """ @@ -229,7 +229,7 @@ class Interface: with gr.Tab("Input"): # File loader gradio_file = gr.File( - show_label=False, elem_classes="file-input h-128" + show_label=False ) with gr.Tab("Examples"): gr.Examples(examples=self.img_examples, inputs=gradio_file) @@ -238,11 +238,11 @@ class Interface: with gr.Row(): with gr.Column(scale=3, min_width=64): btn_run = gr.Button( - value="Run 3D visualization", elem_classes="btn btn-run" + value="Run 3D visualization", variant = "primary" ) with gr.Column(scale=1, min_width=64): btn_clear = gr.Button( - value="Clear", elem_classes="btn btn-clear" + value="Clear", variant = "stop" ) with gr.Tab("Display"): @@ -255,7 +255,6 @@ class Interface: label="Display resolution", info="Number of voxels for the largest dimension", value=64, - elem_classes="", ) surface_count = gr.Slider( 2, 16, step=1, label="Total iso-surfaces", value=6 @@ -373,7 +372,6 @@ class Interface: label="Download interactive plot", show_label=True, visible=False, - elem_classes="w-256", ) outputs = [volvizplot, plot_download] @@ -399,13 +397,13 @@ class Interface: def make_visible(self): return gr.update(visible=True) - def launch(self, **kwargs): + def launch(self, force_light_mode:bool = True, **kwargs): # Show header if self.show_header: internal_tools.gradio_header(self.title, self.port) # Create gradio interface - self.interface = self.create_interface() + self.interface = self.create_interface(force_light_mode=force_light_mode) # Set gradio verbose level if self.verbose: @@ -417,6 +415,7 @@ class Interface: quiet=quiet, height=self.height, width=self.width, + favicon_path = Path(qim3d.__file__).parents[0] / "gui/images/qim_platform-icon.svg", **kwargs, ) diff --git a/qim3d/gui/local_thickness.py b/qim3d/gui/local_thickness.py index 4dcc9113..44af9791 100644 --- a/qim3d/gui/local_thickness.py +++ b/qim3d/gui/local_thickness.py @@ -45,10 +45,13 @@ from scipy import ndimage import outputformat as ouf import plotly.graph_objects as go import localthickness as lt -import matplotlib + # matplotlib.use("Agg") import matplotlib.pyplot as plt +from pathlib import Path +import qim3d +from .qim_theme import QimTheme class Interface: @@ -75,8 +78,6 @@ class Interface: [os.path.join(current_dir, *examples_dir, example)] ) - # CSS path - self.css_path = os.path.join(current_dir, "..", "css", "gradio.css") def clear(self): """Used to reset the plot with the clear button""" @@ -106,14 +107,14 @@ class Interface: session.zpos = zpos return session - def launch(self, img=None,**kwargs): + def launch(self, img=None, force_light_mode:bool = True, **kwargs): # Show header if self.show_header: internal_tools.gradio_header(self.title, self.port) # Create gradio interfaces - self.interface = self.create_interface(img=img) + self.interface = self.create_interface(img=img, force_light_mode=force_light_mode) # Set gradio verbose level if self.verbose: @@ -125,6 +126,7 @@ class Interface: quiet=quiet, height=self.height, width=self.width, + favicon_path = Path(qim3d.__file__).parents[0] / "gui/images/qim_platform-icon.svg", **kwargs ) @@ -152,8 +154,8 @@ class Interface: return vol_lt - def create_interface(self, img=None): - with gr.Blocks(css=self.css_path) as gradio_interface: + def create_interface(self, img=None, force_light_mode:bool = True): + with gr.Blocks(theme = QimTheme(force_light_mode=force_light_mode), title = self.title) as gradio_interface: gr.Markdown( "# 3D Local thickness \n Interface for _Fast local thickness in 3D and 2D_ (https://github.com/vedranaa/local-thickness)" ) @@ -166,7 +168,6 @@ class Interface: with gr.Tab("Input"): data = gr.File( show_label=False, - elem_classes="file-input h-128", value=img, ) with gr.Tab("Examples"): @@ -228,10 +229,10 @@ class Interface: with gr.Row(): with gr.Column(scale=3, min_width=64): btn = gr.Button( - "Run local thickness", elem_classes="btn btn-run" + "Run local thickness", variant = "primary" ) with gr.Column(scale=1, min_width=64): - btn_clear = gr.Button("Clear", elem_classes="btn btn-clear") + btn_clear = gr.Button("Clear", variant = "stop") inputs = [ data, @@ -250,21 +251,18 @@ class Interface: show_label=True, label="Original", visible=True, - elem_classes="plot", ) binary_vol = gr.Plot( show_label=True, label="Binary", visible=True, - elem_classes="plot", ) output_vol = gr.Plot( show_label=True, label="Local thickness", visible=True, - elem_classes="plot", ) with gr.Row(): histogram = gr.Plot( @@ -278,7 +276,6 @@ class Interface: show_label=True, label="Output file", visible=False, - elem_classes="", ) # Pipelines @@ -316,7 +313,7 @@ class Interface: fn=pipeline.input_viz, inputs=session, outputs=input_vol, show_progress=False).success( fn=pipeline.binary_viz, inputs=session, outputs=binary_vol,show_progress=False).success( fn=pipeline.output_viz, inputs=session, outputs=output_vol,show_progress=False) - # fmt: on + # fmt: on return gradio_interface diff --git a/qim3d/gui/qim_theme.py b/qim3d/gui/qim_theme.py new file mode 100644 index 00000000..4dd19054 --- /dev/null +++ b/qim3d/gui/qim_theme.py @@ -0,0 +1,106 @@ +import gradio as gr + +class QimTheme(gr.themes.Default): + """ + QIM3D Theme for gradio interface + The theming options are quite broad. However if there is something you can not achieve with this theme + there is a possibility to add some more css if you override _get_css_theme function as shown at the bottom + in comments. + """ + def __init__(self, force_light_mode:bool = True): + """ + Parameters: + ----------- + - force_light_mode (bool, optional): Gradio themes have dark mode by default. + Qim platform is not ready for dark mode yet, thus the tools should also be in light mode. + This sets the darkmode values to be the same as light mode values. + """ + super().__init__() + self.force_light_mode = force_light_mode + self.general_values() # Not color related + self.set_light_mode_values() + self.set_dark_mode_values() # Checks the light mode setting inside + + def general_values(self): + self.set_button() + self.set_h1() + + def set_light_mode_values(self): + self.set_light_primary_button() + self.set_light_secondary_button() + self.set_light_checkbox() + self.set_light_cancel_button() + self.set_light_example() + + def set_dark_mode_values(self): + if self.force_light_mode: + for attr in [dark_attr for dark_attr in dir(self) if not dark_attr.startswith("_") and dark_attr.endswith("dark")]: + self.__dict__[attr] = self.__dict__[attr[:-5]] # ligth and dark attributes have same names except for '_dark' at the end + else: + self.set_dark_primary_button() + # Secondary button looks good by default in dark mode + self.set_dark_checkbox() + self.set_dark_cancel_button() + # Example looks good by default in dark mode + + def set_button(self): + self.button_transition = "0.15s" + self.button_large_text_weight = "normal" + + def set_light_primary_button(self): + self.run_color = "#198754" + self.button_primary_background_fill = "#FFFFFF" + self.button_primary_background_fill_hover = self.run_color + self.button_primary_border_color = self.run_color + self.button_primary_text_color = self.run_color + self.button_primary_text_color_hover = "#FFFFFF" + + def set_dark_primary_button(self): + self.bright_run_color = "#299764" + self.button_primary_background_fill_dark = self.button_primary_background_fill_hover + self.button_primary_background_fill_hover_dark = self.bright_run_color + self.button_primary_border_color_dark = self.button_primary_border_color + self.button_primary_border_color_hover_dark = self.bright_run_color + + def set_light_secondary_button(self): + self.button_secondary_background_fill = "white" + + def set_light_example(self): + """ + This sets how the examples in gradio.Examples look like. Used in iso3d. + """ + self.border_color_accent = self.neutral_100 + self.color_accent_soft = self.neutral_100 + + def set_h1(self): + self.text_xxl = "2.5rem" + + def set_light_checkbox(self): + light_blue = "#60a5fa" + self.checkbox_background_color_selected = light_blue + self.checkbox_border_color_selected = light_blue + self.checkbox_border_color_focus = light_blue + + def set_dark_checkbox(self): + self.checkbox_border_color_dark = self.neutral_500 + self.checkbox_border_color_focus_dark = self.checkbox_border_color_focus_dark + + def set_light_cancel_button(self): + self.cancel_color = "#dc3545" + self.button_cancel_background_fill = "white" + self.button_cancel_background_fill_hover = self.cancel_color + self.button_cancel_border_color = self.cancel_color + self.button_cancel_text_color = self.cancel_color + self.button_cancel_text_color_hover = "white" + + def set_dark_cancel_button(self): + self.button_cancel_background_fill_dark = self.cancel_color + self.button_cancel_background_fill_hover_dark = "red" + self.button_cancel_border_color_dark = self.cancel_color + self.button_cancel_border_color_hover_dark = "red" + self.button_cancel_text_color_dark = "white" + + # def _get_theme_css(self): + # sup = super()._get_theme_css() + # return "\n.svelte-182fdeq {\nbackground: rgba(255, 0, 0, 0.5) !important;\n}\n" + sup # You have to use !important, so it overrides other css + \ No newline at end of file diff --git a/qim3d/utils/cli.py b/qim3d/utils/cli.py index e4a64b9a..4b057142 100644 --- a/qim3d/utils/cli.py +++ b/qim3d/utils/cli.py @@ -97,26 +97,28 @@ def main(): data_explorer.run_interface(arghost) else: interface = data_explorer.Interface() - interface.launch(inbrowser=inbrowser) + interface.launch(inbrowser=inbrowser, force_light_mode=False) elif args.iso3d: if args.platform: iso3d.run_interface(arghost) else: interface = iso3d.Interface() - interface.launch(inbrowser=inbrowser) - + interface.launch(inbrowser=inbrowser, force_light_mode=False) + elif args.annotation_tool: if args.platform: annotation_tool.run_interface(arghost) else: interface = annotation_tool.Interface() - interface.launch(inbrowser=inbrowser) + interface.launch(inbrowser=inbrowser, force_light_mode=False) elif args.local_thickness: if args.platform: local_thickness.run_interface(arghost) else: interface = local_thickness.Interface() - interface.launch(inbrowser=inbrowser) + interface.launch(inbrowser=inbrowser, force_light_mode=False) + + elif args.subcommand == "viz": if not args.source: print("Please specify a source file using the argument --source") -- GitLab