From ffd8e3abd3bd0181b0b12bb67c818715642fc68e Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Wed, 27 May 2026 15:10:42 -0500 Subject: [PATCH] Route unknown legacy string keys on `ImageViewGUI` to `extras` Pre-0.13 code used the GUI `Dict` as scratch space for arbitrary keys (e.g. stashing a `zoom_region` observable). The 0.13 shim was strict and threw `ArgumentError` on unknown keys, which broke downstream packages that did this. Route unknown keys through the `extras::Dict{Symbol,Any}` field instead, preserving the scratch-space pattern through the deprecation cycle. Also define `Base.haskey(::ImageViewGUI, ::AbstractString)`. Mark `ImageDisplay`, `ImageViewGUI`, and `ImageROI` public so downstream packages can dispatch on them without tripping ExplicitImports. Co-Authored-By: Claude Opus 4.7 --- NEWS.md | 5 +++++ Project.toml | 2 +- src/ImageView.jl | 5 +++++ src/deprecated.jl | 16 +++++++++++++--- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/NEWS.md b/NEWS.md index a76900d..32dcba2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,10 @@ # New in 0.13 +- 0.13.3: the legacy string-key shim on `ImageViewGUI` now routes unknown + keys to the `extras::Dict{Symbol,Any}` field instead of throwing + `ArgumentError`. This restores the pre-0.13 pattern of using the GUI + handle as a scratch space for downstream-defined keys (with a depwarn). + `Base.haskey(::ImageViewGUI, ::AbstractString)` is also defined. - `imshow` now returns an `ImageDisplay` struct rather than a nested `Dict{String,Any}`. The nested GUI and ROI groupings are exposed as the structs `ImageViewGUI` (returned by `imshow_gui`) and `ImageROI` diff --git a/Project.toml b/Project.toml index 67f5dcc..09c32ea 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "ImageView" uuid = "86fae568-95e7-573e-a6b2-d8a6b900c9ef" author = ["Tim Holy "] -version = "0.13.2" +version = "0.13.3" [deps] AxisArrays = "39de3d68-74b9-583c-8d2d-e117c070f3a9" diff --git a/src/ImageView.jl b/src/ImageView.jl index 66349a5..b3b27a3 100644 --- a/src/ImageView.jl +++ b/src/ImageView.jl @@ -20,6 +20,11 @@ export AnnotationText, AnnotationPoint, AnnotationPoints, export CLim, annotate!, annotations, canvasgrid, imshow, imshow!, imshow_gui, imlink, roi, scalebar, setup_contrast_popup!, slice2d +# Public-but-not-exported types that downstream packages dispatch on. +@static if VERSION >= v"1.11" + eval(Expr(:public, :ImageDisplay, :ImageViewGUI, :ImageROI)) +end + const AbstractGray{T} = Color{T,1} const GrayLike = Union{AbstractGray,Number} const FixedColorant{T<:FixedPoint} = Colorant{T} diff --git a/src/deprecated.jl b/src/deprecated.jl index 54ba23f..b6c9897 100644 --- a/src/deprecated.jl +++ b/src/deprecated.jl @@ -66,14 +66,24 @@ function _legacy_get(g::ImageViewGUI, key::AbstractString) key == "hoverinfo" && return getfield(g, :hoverinfo) key == "zoomregion_info" && return getfield(g, :zoomregion_info) key == "guidata" && return getfield(g, :extras)[:guidata] - throw(KeyError(key)) + # Pre-0.13 callers used the GUI Dict as scratch space for arbitrary keys + # (e.g. stashing a `zoom_region` observable). Route those through `extras`. + return getfield(g, :extras)[Symbol(key)] end function _legacy_set!(g::ImageViewGUI, key::AbstractString, value) key == "hoverinfo" && (g.hoverinfo = value; return value) key == "zoomregion_info" && (g.zoomregion_info = value; return value) key == "players" && (g.players = value; return value) - key == "guidata" && (g.extras[:guidata] = value; return value) - throw(ArgumentError("cannot assign legacy key \"$key\" on ImageViewGUI")) + getfield(g, :extras)[Symbol(key)] = value + return value +end + +Base.haskey(g::ImageViewGUI, key::AbstractString) = + _legacy_haskey_known(g, key) || haskey(getfield(g, :extras), Symbol(key)) + +function _legacy_haskey_known(::ImageViewGUI, key::AbstractString) + return key in ("window", "vbox", "frame", "canvas", "status", "viewlabel", + "players", "hoverinfo", "zoomregion_info", "guidata") end function _legacy_get(r::ImageROI, key::AbstractString)