Repository: napari/napari

Issue:
Change name of clims
From @jni in #172

> Side note, clims needs a name change

Can you elaborate here / do you have ideas on what name should be?
Expand button
# Description
This PR resolves #321 by adding a button to explicitly expand the layer properties. As requested by @jni it preserves the option to doubleclick elsewhere inside the the layer properties to toggle the expansion.

Right now the PR is still in progress as I need help from our style and icon guru @freeman-lab to improve the icon. I have a "sandwhich bar" in there right now but I think I might switch to up / down triangles. Open to other suggestions too if people have them.

![image](https://user-images.githubusercontent.com/6531703/59044000-214dcd00-8832-11e9-9590-dbf48d965705.png)

## Type of change
<!-- Please delete options that are not relevant. -->
- [ ] New feature (non-breaking change which adds functionality)

# How has this been tested?
<!-- Please describe the tests that you ran to verify your changes. -->
- [x] run examples and toggle button

## Final checklist:
- [x] My PR is the minimum possible work for the desired functionality
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] I have added tests that prove my fix is effective or that my feature works



Discussion:
clim means literally nothing to someone not already familiar with the terminology and/or our software.

Not sure what the best option is, but something along the lines of `brightness_range` or `displayed_data_range`.
Agreed we should have a more intuitive name. `look_up_table_range` is something some communities might understand, but maybe is a little jargony. How about `display_range`?
Looking into this more - the same functionality in matplotlib is called `clim` - see [here](https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.clim.html#matplotlib.pyplot.clim) which makes me lean towards keeping. If we are going to change though, I'd like to do it now so that things on the repo can be more stable as we move forward. Thoughts @jni @royerloic?  
I think #310 is more urgent, but anyway. =P

matplotlib itself has a lot of historical baggage, so in terms of API it's not necessarily the best model to move forward with. It's unclear that they would keep it if they were starting anew.

Currently I'm thinking that the middle road is the best one: use `clim` but being more explicit: `contrast_limits`.
I think explicit is better, I thought that clim meant 'color-limits' and I thought it was bad.
'contrast-limits' is a bit better, but technically it is wrong, since both brightness (offset) and contrast(slope) are affected by changing any of the two clim values...  So unless we find 
something better than 'contrast-limits' that's fine. Any ideas?
"saturation_range", "saturation_limits", "saturation_points"? But I think "contrast_limits" is clear enough, despite your reservations...
I'm think `contrast_limits` is fine, agreed it's not strictly correct, but it is clear enough not to be confusing for most people (beginners in particular, whom might have heard of `clim` before in matplotlib and can recognize the similarity)
I've updated the style of the icon based on a design from @freeman-lab. See below in the gif. This PR is now ready for review.

![expand_button](https://user-images.githubusercontent.com/6531703/59059699-74387c00-8854-11e9-9d5c-638ef983e3de.gif)

Hello @sofroniewn! Thanks for updating this PR. We checked the lines you've touched for [PEP 8](https://www.python.org/dev/peps/pep-0008) issues, and found:







There are currently no PEP 8 issues detected in this Pull Request. Cheers! :beers: 

##### Comment last updated at 2019-06-07 02:55:49 UTC
Line length issue with black has been fixed by replacing `max-line-length` with `line-length` in the `pyproject.toml` and the python 3.7 compatibility mentioned in #328 by using `python3` in our `pre-commit-config.yaml`. This is already to go and I will merge once the tests pass

Resolving patch:
diff --git a/docs/_scripts/prep_docs.py b/docs/_scripts/prep_docs.py
--- a/docs/_scripts/prep_docs.py
+++ b/docs/_scripts/prep_docs.py
@@ -19,12 +19,12 @@ def prep_npe2():
 
     npe2_version = version("npe2")
 
-    check_call("rm -rf npe2".split())
+    check_call(f"rm -rf {NPE}".split())
     check_call(f"git clone https://github.com/napari/npe2 {NPE}".split())
     if not parse(npe2_version).is_devrelease:
         check_call(f"git checkout tags/v{npe2_version}".split(), cwd=NPE)
-    check_call([sys.executable, "npe2/_docs/render.py", DOCS / 'plugins'])
-    check_call("rm -rf npe2".split())
+    check_call([sys.executable, f"{NPE}/_docs/render.py", DOCS / 'plugins'])
+    check_call(f"rm -rf {NPE}".split())
 
 
 def main():
diff --git a/docs/conf.py b/docs/conf.py
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -14,13 +14,14 @@
 # import sys
 # sys.path.insert(0, os.path.abspath('.'))
 
+import os
 import re
 from importlib import import_module
 from pathlib import Path
 from urllib.parse import urlparse, urlunparse
 
-import qtgallery
 from jinja2.filters import FILTERS
+from sphinx_gallery import scrapers
 from sphinx_gallery.sorting import ExampleTitleSortKey
 
 import napari
@@ -78,7 +79,7 @@
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
 #
-html_theme = 'napari'
+html_theme = 'napari_sphinx_theme'
 
 # Define the json_url for our version switcher.
 json_url = "https://napari.org/dev/_static/version_switcher.json"
@@ -90,12 +91,17 @@
         {"name": "napari hub", "url": "https://napari-hub.org"}
     ],
     "github_url": "https://github.com/napari/napari",
-    "navbar_start": ["navbar-project"],
+    "navbar_start": ["navbar-logo", "navbar-project"],
     "navbar_end": ["version-switcher", "navbar-icon-links"],
     "switcher": {
         "json_url": json_url,
         "version_match": version_match,
     },
+    "navbar_persistent": [],
+    "header_links_before_dropdown": 6,
+    "secondary_sidebar_items": ["page-toc"],
+    "pygment_light_style": "napari",
+    "pygment_dark_style": "napari",
 }
 
 # Add any paths that contain custom static files (such as style sheets) here,
@@ -152,10 +158,10 @@
     'tasklist',
 ]
 
-myst_heading_anchors = 3
+myst_heading_anchors = 4
 
 version_string = '.'.join(str(x) for x in __version_tuple__[:3])
-python_version = '3.9'
+python_version = '3.10'
 python_version_range = '3.8-3.10'
 python_minimum_version = '3.8'
 
@@ -169,6 +175,8 @@
     "conda_create_env": f"```sh\nconda create -y -n napari-env -c conda-forge python={python_version}\nconda activate napari-env\n```",
 }
 
+myst_footnote_transition = False
+
 nb_output_stderr = 'show'
 
 panels_add_bootstrap_css = False
@@ -194,12 +202,46 @@
 napoleon_custom_sections = [('Events', 'params_style')]
 
 
-def reset_napari_theme(gallery_conf, fname):
+def reset_napari(gallery_conf, fname):
+    from qtpy.QtWidgets import QApplication
+
     from napari.settings import get_settings
 
     settings = get_settings()
     settings.appearance.theme = 'dark'
-    qtgallery.reset_qapp(gallery_conf, fname)
+
+    # Disabling `QApplication.exec_` means example scripts can call `exec_`
+    # (scripts work when run normally) without blocking example execution by
+    # sphinx-gallery. (from qtgallery)
+    QApplication.exec_ = lambda _: None
+
+
+def napari_scraper(block, block_vars, gallery_conf):
+    """Basic napari window scraper.
+
+    Looks for any QtMainWindow instances and takes a screenshot of them.
+
+    `app.processEvents()` allows Qt events to propagateo and prevents hanging.
+    """
+    imgpath_iter = block_vars['image_path_iterator']
+
+    if app := napari.qt.get_app():
+        app.processEvents()
+    else:
+        return ""
+
+    img_paths = []
+    for win, img_path in zip(
+        reversed(napari._qt.qt_main_window._QtMainWindow._instances),
+        imgpath_iter,
+    ):
+        img_paths.append(img_path)
+        win._window.screenshot(img_path, canvas_only=False)
+
+    napari.Viewer.close_all()
+    app.processEvents()
+
+    return scrapers.figure_rst(img_paths, gallery_conf['src_dir'])
 
 
 sphinx_gallery_conf = {
@@ -211,28 +253,44 @@ def reset_napari_theme(gallery_conf, fname):
     / 'napari'
     / 'resources'
     / 'logo.png',
-    'plot_gallery': True,
+    'plot_gallery': "'True'",  # https://github.com/sphinx-gallery/sphinx-gallery/pull/304/files
     'download_all_examples': False,
     'min_reported_time': 10,
     'only_warn_on_example_error': True,
     'image_scrapers': (
         "matplotlib",
-        qtgallery.qtscraper,
+        napari_scraper,
     ),
-    'reset_modules': (reset_napari_theme,),
+    'reset_modules': (reset_napari,),
     'reference_url': {'napari': None},
     'within_subsection_order': ExampleTitleSortKey,
 }
 
+GOOGLE_CALENDAR_API_KEY = os.environ.get('GOOGLE_CALENDAR_API_KEY', '')
+
+
+def add_google_calendar_secrets(app, docname, source):
+    """Add google calendar api key to meeting schedule page.
+
+    The source argument is a list whose single element is the contents of the
+    source file. You can process the contents and replace this item to implement
+    source-level transformations.
+    """
+    if docname == 'community/meeting_schedule':
+        source[0] = source[0].replace('{API_KEY}', GOOGLE_CALENDAR_API_KEY)
+
 
 def setup(app):
-    """Ignore .ipynb files.
+    """Set up docs build.
 
-    Prevents sphinx from complaining about multiple files found for document
-    when generating the gallery.
+    * Ignores .ipynb files to prevent sphinx from complaining about multiple
+      files found for document when generating the gallery
+    * Rewrites github anchors to be comparable
+    * Adds google calendar api key to meetings schedule page
 
     """
     app.registry.source_suffix.pop(".ipynb", None)
+    app.connect('source-read', add_google_calendar_secrets)
     app.connect('linkcheck-process-uri', rewrite_github_anchor)
 
 


Test patch: