Changeset 277279 in webkit


Ignore:
Timestamp:
May 10, 2021 11:43:47 AM (15 months ago)
Author:
Devin Rousso
Message:

Web Inspector: add support for panning/zooming on images
https://bugs.webkit.org/show_bug.cgi?id=224655

Reviewed by Timothy Hatcher.

  • UserInterface/Controllers/GestureController.js: Added.

(WI.GestureController):
(WI.GestureController.prototype.get scale):
(WI.GestureController.prototype.set scale):
(WI.GestureController.prototype.get translate):
(WI.GestureController.prototype.set translate):
(WI.GestureController.prototype.reset):
(WI.GestureController.prototype._startScaleInteraction):
(WI.GestureController.prototype._updateScaleInteraction):
(WI.GestureController.prototype._endScaleInteraction):
(WI.GestureController.prototype._handleWheel):
(WI.GestureController.prototype._handleGestureStart):
(WI.GestureController.prototype._handleGestureChange):
(WI.GestureController.prototype._handleGestureEnd):
(WI.GestureController.prototype._handleMouseDown):
(WI.GestureController.prototype._handleMouseMove):
(WI.GestureController.prototype._handleMouseUp):
Add a general controller class that takes a target (and optionally a container) and adds
event listeners to handle various gestures:

  • scale (both via trackpad and mouse wheel)
  • transform (mouse click and drag)
  • UserInterface/Views/ImageResourceContentView.js:

(WI.ImageResourceContentView):
(WI.ImageResourceContentView.prototype.get navigationItems):
(WI.ImageResourceContentView.prototype.contentAvailable):
(WI.ImageResourceContentView.prototype.gestureControllerDidScale): Added.
(WI.ImageResourceContentView.prototype.gestureControllerDidTranslate): Added.
(WI.ImageResourceContentView.prototype._updateResetGestureButtonNavigationItemLabel): Added.
(WI.ImageResourceContentView.prototype._handleResetGestureButtonNavitationItemClicked): Added.
(WI.ImageResourceContentView.prototype._handleZoomOutGestureButtonNavitationItemClicked): Added.
(WI.ImageResourceContentView.prototype._handleZoomInGestureButtonNavitationItemClicked): Added.

  • UserInterface/Views/ImageResourceContentView.css:

(.content-view.resource.image > .img-container):
(.navigation-bar > .item.image-gesture-reset): Added.
Add a WI.GestureController and manipulate the scale and transform of the <img>.
Add navigation items that show the current scale (clicking it will reset the gesture), zoom
in, and zoom out.

  • UserInterface/Views/LocalResourceOverrideLabelView.css:

(.local-resource-override-label-view):
Add a z-index so that zoomed images don't appear on top.

  • UserInterface/Views/ResourceCollectionContentView.js:

(WI.ResourceCollectionContentView.prototype.get contentViewConstructorOptions):
Don't create the WI.GestureController in collection views.

  • UserInterface/Main.html:
  • UserInterface/Images/ZoomIn.svg: Added.
  • UserInterface/Images/ZoomOut.svg: Added.
  • Localizations/en.lproj/localizedStrings.js:
Location:
trunk/Source/WebInspectorUI
Files:
3 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebInspectorUI/ChangeLog

    r277213 r277279  
     12021-05-10  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: add support for panning/zooming on images
     4        https://bugs.webkit.org/show_bug.cgi?id=224655
     5
     6        Reviewed by Timothy Hatcher.
     7
     8        * UserInterface/Controllers/GestureController.js: Added.
     9        (WI.GestureController):
     10        (WI.GestureController.prototype.get scale):
     11        (WI.GestureController.prototype.set scale):
     12        (WI.GestureController.prototype.get translate):
     13        (WI.GestureController.prototype.set translate):
     14        (WI.GestureController.prototype.reset):
     15        (WI.GestureController.prototype._startScaleInteraction):
     16        (WI.GestureController.prototype._updateScaleInteraction):
     17        (WI.GestureController.prototype._endScaleInteraction):
     18        (WI.GestureController.prototype._handleWheel):
     19        (WI.GestureController.prototype._handleGestureStart):
     20        (WI.GestureController.prototype._handleGestureChange):
     21        (WI.GestureController.prototype._handleGestureEnd):
     22        (WI.GestureController.prototype._handleMouseDown):
     23        (WI.GestureController.prototype._handleMouseMove):
     24        (WI.GestureController.prototype._handleMouseUp):
     25        Add a general controller class that takes a `target` (and optionally a `container`) and adds
     26        event listeners to handle various gestures:
     27         - scale (both via trackpad and mouse wheel)
     28         - transform (mouse click and drag)
     29
     30        * UserInterface/Views/ImageResourceContentView.js:
     31        (WI.ImageResourceContentView):
     32        (WI.ImageResourceContentView.prototype.get navigationItems):
     33        (WI.ImageResourceContentView.prototype.contentAvailable):
     34        (WI.ImageResourceContentView.prototype.gestureControllerDidScale): Added.
     35        (WI.ImageResourceContentView.prototype.gestureControllerDidTranslate): Added.
     36        (WI.ImageResourceContentView.prototype._updateResetGestureButtonNavigationItemLabel): Added.
     37        (WI.ImageResourceContentView.prototype._handleResetGestureButtonNavitationItemClicked): Added.
     38        (WI.ImageResourceContentView.prototype._handleZoomOutGestureButtonNavitationItemClicked): Added.
     39        (WI.ImageResourceContentView.prototype._handleZoomInGestureButtonNavitationItemClicked): Added.
     40        * UserInterface/Views/ImageResourceContentView.css:
     41        (.content-view.resource.image > .img-container):
     42        (.navigation-bar > .item.image-gesture-reset): Added.
     43        Add a `WI.GestureController` and manipulate the `scale` and `transform` of the `<img>`.
     44        Add navigation items that show the current scale (clicking it will reset the gesture), zoom
     45        in, and zoom out.
     46
     47        * UserInterface/Views/LocalResourceOverrideLabelView.css:
     48        (.local-resource-override-label-view):
     49        Add a `z-index` so that zoomed images don't appear on top.
     50
     51        * UserInterface/Views/ResourceCollectionContentView.js:
     52        (WI.ResourceCollectionContentView.prototype.get contentViewConstructorOptions):
     53        Don't create the `WI.GestureController` in collection views.
     54
     55        * UserInterface/Main.html:
     56        * UserInterface/Images/ZoomIn.svg: Added.
     57        * UserInterface/Images/ZoomOut.svg: Added.
     58        * Localizations/en.lproj/localizedStrings.js:
     59
    1602021-05-07  Patrick Angle  <pangle@apple.com>
    261
  • trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

    r276681 r277279  
    314314localizedStrings["Click to create a Local Override from this content"] = "Click to create a Local Override from this content";
    315315localizedStrings["Click to import a file and create a Local Override\nShift-click to create a Local Override from this content"] = "Click to import a file and create a Local Override\nShift-click to create a Local Override from this content";
     316/* Title of text button that resets the gesture controls in the image resource content view. */
     317localizedStrings["Click to reset @ Image Resource Content View Gesture Controls"] = "Click to reset";
    316318localizedStrings["Click to select a color"] = "Click to select a color";
    317319localizedStrings["Click to select a color\nShift-click to switch color formats"] = "Click to select a color\nShift-click to switch color formats";
     
    17041706localizedStrings["XPath"] = "XPath";
    17051707localizedStrings["Yes"] = "Yes";
     1708/* Title of image button that increases the zoom of the image resource content view. */
     1709localizedStrings["Zoom In @ Image Resource Content View Gesture Controls"] = "Zoom In";
     1710/* Title of image button that decreases the zoom of the image resource content view. */
     1711localizedStrings["Zoom Out @ Image Resource Content View Gesture Controls"] = "Zoom Out";
    17061712localizedStrings["Zoom:"] = "Zoom:";
    17071713localizedStrings["\u0022%s\u0022 has a non-array \u0022%s\u0022 value"] = "\u0022%s\u0022 has a non-array \u0022%s\u0022 value";
  • trunk/Source/WebInspectorUI/UserInterface/Main.html

    r276714 r277279  
    909909    <script src="Controllers/DragToAdjustController.js"></script>
    910910    <script src="Controllers/FormatterSourceMap.js"></script>
     911    <script src="Controllers/GestureController.js"></script>
    911912    <script src="Controllers/HARBuilder.js"></script>
    912913    <script src="Controllers/HeapManager.js"></script>
  • trunk/Source/WebInspectorUI/UserInterface/Views/ImageResourceContentView.css

    r269438 r277279  
    4242    justify-content: center;
    4343    align-items: center;
     44    position: relative;
    4445    width: 100%;
    4546    height: 100%;
     
    5657}
    5758
     59.navigation-bar > .item.image-gesture-reset {
     60    font-variant-numeric: tabular-nums;
     61}
     62
    5863@media (prefers-color-scheme: dark) {
    5964    .content-view.resource.image {
  • trunk/Source/WebInspectorUI/UserInterface/Views/ImageResourceContentView.js

    r270604 r277279  
    2626WI.ImageResourceContentView = class ImageResourceContentView extends WI.ResourceContentView
    2727{
    28     constructor(resource, {disableDropZone} = {})
     28    constructor(resource, {disableInteractions} = {})
    2929    {
    3030        console.assert(resource instanceof WI.Resource);
     
    3434        this._imageElement = null;
    3535        this._draggingInternalImageElement = false;
    36         this._disableDropZone = disableDropZone || false;
     36        this._disableInteractions = disableInteractions || false;
    3737
    3838        const toolTip = WI.repeatedUIString.showTransparencyGridTooltip();
    3939        const activatedToolTip = WI.UIString("Hide transparency grid");
    4040        this._showGridButtonNavigationItem = new WI.ActivateButtonNavigationItem("show-grid", toolTip, activatedToolTip, "Images/NavigationItemCheckers.svg", 13, 13);
    41         this._showGridButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
    4241        this._showGridButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._showGridButtonClicked, this);
    4342        this._showGridButtonNavigationItem.activated = !!WI.settings.showImageGrid.value;
     43
     44        if (!this._disableInteractions) {
     45            this._resetGestureButtonNavitationItem = new WI.ButtonNavigationItem("image-gesture-reset", "");
     46            this._resetGestureButtonNavitationItem.tooltip = WI.UIString("Click to reset", "Click to reset @ Image Resource Content View Gesture Controls", "Title of text button that resets the gesture controls in the image resource content view.");
     47            this._resetGestureButtonNavitationItem.hidden = true;
     48            this._resetGestureButtonNavitationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleResetGestureButtonNavitationItemClicked, this);
     49
     50            this._zoomOutGestureButtonNavitationItem = new WI.ButtonNavigationItem("image-gesture-zoom-out", WI.UIString("Zoom Out", "Zoom Out @ Image Resource Content View Gesture Controls", "Title of image button that decreases the zoom of the image resource content view."), "Images/ZoomOut.svg", 16, 16);
     51            this._zoomOutGestureButtonNavitationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
     52            this._zoomOutGestureButtonNavitationItem.hidden = true;
     53            this._zoomOutGestureButtonNavitationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleZoomOutGestureButtonNavitationItemClicked, this);
     54
     55            this._zoomInGestureButtonNavitationItem = new WI.ButtonNavigationItem("image-gesture-zoom-in", WI.UIString("Zoom In", "Zoom In @ Image Resource Content View Gesture Controls", "Title of image button that increases the zoom of the image resource content view."), "Images/ZoomIn.svg", 16, 16);
     56            this._zoomInGestureButtonNavitationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
     57            this._zoomInGestureButtonNavitationItem.hidden = true;
     58            this._zoomInGestureButtonNavitationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleZoomInGestureButtonNavitationItemClicked, this);
     59
     60            this._gestureNavigationItemsDivider = new WI.DividerNavigationItem;
     61            this._gestureNavigationItemsDivider.hidden = true;
     62
     63        }
    4464    }
    4565
     
    4868    get navigationItems()
    4969    {
    50         let items = super.navigationItems;
    51 
     70        let items = [];
     71        if (!this._disableInteractions) {
     72            items.push(this._resetGestureButtonNavitationItem);
     73            items.push(this._zoomOutGestureButtonNavitationItem);
     74            items.push(this._zoomInGestureButtonNavitationItem);
     75            items.push(new WI.DividerNavigationItem);
     76        }
     77        items.pushAll(super.navigationItems);
    5278        items.push(this._showGridButtonNavigationItem);
    53 
    5479        return items;
    5580    }
     
    7095        }
    7196
    72         let imageContainer = this.element.appendChild(document.createElement("div"));
    73         imageContainer.className = "img-container";
    74 
    75         this._imageElement = imageContainer.appendChild(document.createElement("img"));
     97        this._imageContainer = this.element.appendChild(document.createElement("div"));
     98        this._imageContainer.className = "img-container";
     99
     100        this._imageElement = this._imageContainer.appendChild(document.createElement("img"));
    76101        this._imageElement.addEventListener("load", function() { URL.revokeObjectURL(objectURL); });
    77102        this._imageElement.src = objectURL;
    78103        this._imageElement.setAttribute("filename", this.resource.urlComponents.lastPathComponent || "");
     104        this._imageElement.draggable = true;
    79105        this._updateImageGrid();
    80106
     107        // Drag-and-Drop should not be considered as the same "kind" of interaction as those below.
    81108        this._imageElement.addEventListener("dragstart", (event) => {
    82109            console.assert(!this._draggingInternalImageElement);
     
    88115        });
    89116
    90         if (WI.NetworkManager.supportsOverridingResponses() && !this._disableDropZone) {
    91             let dropZoneView = new WI.DropZoneView(this);
    92             dropZoneView.targetElement = imageContainer;
    93             this.addSubview(dropZoneView);
    94 
    95             if (this.resource.localResourceOverride)
    96                 this.resource.addEventListener(WI.SourceCode.Event.ContentDidChange, this._handleLocalResourceContentDidChange, this);
     117        if (!this._disableInteractions) {
     118            this._gestureController = new WI.GestureController(this._imageElement, this, {container: this._imageContainer, supportsScale: true, supportsTranslate: true});
     119
     120            this._resetGestureButtonNavitationItem.hidden = false;
     121            this._zoomOutGestureButtonNavitationItem.hidden = false;
     122            this._zoomInGestureButtonNavitationItem.hidden = false;
     123            this._gestureNavigationItemsDivider.hidden = false;
     124            this._updateResetGestureButtonNavigationItemLabel();
     125
     126            if (WI.NetworkManager.supportsOverridingResponses()) {
     127                let dropZoneView = new WI.DropZoneView(this);
     128                dropZoneView.targetElement = this._imageContainer;
     129                this.addSubview(dropZoneView);
     130
     131                if (this.resource.localResourceOverride)
     132                    this.resource.addEventListener(WI.SourceCode.Event.ContentDidChange, this._handleLocalResourceContentDidChange, this);
     133            }
    97134        }
    98135    }
     
    114151
    115152        super.detached();
     153    }
     154
     155    // GestureController delegate
     156
     157    gestureControllerDidScale(gestureController)
     158    {
     159        this._imageElement.style.setProperty("scale", this._gestureController.scale);
     160
     161        this._updateResetGestureButtonNavigationItemLabel();
     162    }
     163
     164    gestureControllerDidTranslate(gestureController, x, y)
     165    {
     166        this._imageElement.style.setProperty("translate", `${this._gestureController.translate.x}px ${this._gestureController.translate.y}px`);
    116167    }
    117168
     
    183234    }
    184235
     236    _updateResetGestureButtonNavigationItemLabel()
     237    {
     238        const precision = 0;
     239        this._resetGestureButtonNavitationItem.label = Number.percentageString(this._gestureController.scale, precision);
     240    }
     241
    185242    _showGridButtonClicked(event)
    186243    {
     
    190247    }
    191248
     249    _handleResetGestureButtonNavitationItemClicked(event)
     250    {
     251        this._gestureController.reset();
     252    }
     253
     254    _handleZoomOutGestureButtonNavitationItemClicked(event)
     255    {
     256        this._gestureController.scale /= 2;
     257    }
     258
     259    _handleZoomInGestureButtonNavitationItemClicked(event)
     260    {
     261        this._gestureController.scale *= 2;
     262    }
     263
    192264    _handleLocalResourceContentDidChange(event)
    193265    {
  • trunk/Source/WebInspectorUI/UserInterface/Views/LocalResourceOverrideLabelView.css

    r249504 r277279  
    2828    justify-content: center;
    2929    align-items: center;
     30    z-index: 1;
    3031    width: 100%;
    3132    height: var(--navigation-bar-height);
  • trunk/Source/WebInspectorUI/UserInterface/Views/ResourceCollectionContentView.js

    r269359 r277279  
    105105        let contentViewConstructorOptions = super.contentViewConstructorOptions;
    106106        if (this.representedObject.resourceType === WI.Resource.Type.Image)
    107             contentViewConstructorOptions.disableDropZone = true;
     107            contentViewConstructorOptions.disableInteractions = true;
    108108        return contentViewConstructorOptions;
    109109    }
Note: See TracChangeset for help on using the changeset viewer.