monaco-editor icon indicating copy to clipboard operation
monaco-editor copied to clipboard

Provide straight-forward zoneWidget API

Open robclive opened this issue 8 years ago • 5 comments

I'm trying to create a view zone similar to the one which shows up while displaying errors:

screenshot from 2017-02-21 19-13-49

I used changeViewZones to insert a viewzone but it creates a zone which spans from the end of line gutter to the end of the editor. I want it to start from the start of the line gutter.

screenshot from 2017-02-21 19-12-50

Is there any way I can reuse what is being used in the error viewzone. If not, how can I mimic it.

robclive avatar Feb 21 '17 13:02 robclive

The go to error widget does two things:

  1. inserts a view zone to reserve a vertical gap in the text
  2. inserts an overlay widget that is kept position-wise in sync with the view zone

The trick is that when inserting a view zone, it is possible to provide two callbacks: onDomNodeTop and onComputedHeight. The callbacks provide the top and the height of the view zone. These values can then be used to position correctly an overlay widget.

Internally, we have something called a zoneWidget, and I think there are many use-cases for this. We should provide straight-forward API for the zoneWidget.

alexdima avatar Jun 08 '17 07:06 alexdima

Until the zoneWidget API is available this is an example of how you could implement the trick explained above.

     // Create a zone over the margin. Uses the trick explained
    // at https://github.com/Microsoft/monaco-editor/issues/373

    // overlay that will be placed over the zone.
    let overlayDom = document.createElement('div');
    overlayDom.id = 'overlayId';
    overlayDom.style.width = '100%';
    overlayDom.style.background = '#ffb275';

    // https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.ioverlaywidget.html
    let overlayWidget = {
      getId: () => 'overlay.zone.widget',
      getDomNode: () => overlayDom,
      getPosition: () => null
    };
    editor.addOverlayWidget(overlayWidget);

    // Used only to compute the position.
    let zoneNode = document.createElement('div');
    zoneNode.style.background = '#8effc9';
    zoneNode.id = "zoneId";

    // Can be used to fill the margin
    let marginDomNode = document.createElement('div');
    marginDomNode.style.background = '#ff696e';
    marginDomNode.id = "zoneMarginId";

    editor.changeViewZones(function(changeAccessor) {
      changeAccessor.addZone({
        afterLineNumber: 3,
        heightInLines: 3,
        domNode: zoneNode,
        marginDomNode: marginDomNode,
        onDomNodeTop: top => {
          overlayDom.style.top = top + "px";
        },
        onComputedHeight: height => {
          overlayDom.style.height = height + "px";
        }

      });
    });

hadrienk avatar Sep 10 '18 13:09 hadrienk

If anyone wants another example of how to use changeViewZones, check this out: https://microsoft.github.io/monaco-editor/playground.html#interacting-with-the-editor-listening-to-mouse-events

samghelms avatar Dec 25 '18 20:12 samghelms

Sorry for resurrecting this old issue. Was just wondering, is there a way to add view zones through VS Code's APIs?
If I can't do it in VS Code, I'm forced to use Monaco Editor as a standalone dependency in a webview.

lppedd avatar Mar 06 '24 16:03 lppedd

Until the zoneWidget API is available this is an example of how you could implement the trick explained above.在 zoneWidget API可用之前,这是一个如何实现上面解释的技巧的示例。

     // Create a zone over the margin. Uses the trick explained
    // at https://github.com/Microsoft/monaco-editor/issues/373

    // overlay that will be placed over the zone.
    let overlayDom = document.createElement('div');
    overlayDom.id = 'overlayId';
    overlayDom.style.width = '100%';
    overlayDom.style.background = '#ffb275';

    // https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.ioverlaywidget.html
    let overlayWidget = {
      getId: () => 'overlay.zone.widget',
      getDomNode: () => overlayDom,
      getPosition: () => null
    };
    editor.addOverlayWidget(overlayWidget);

    // Used only to compute the position.
    let zoneNode = document.createElement('div');
    zoneNode.style.background = '#8effc9';
    zoneNode.id = "zoneId";

    // Can be used to fill the margin
    let marginDomNode = document.createElement('div');
    marginDomNode.style.background = '#ff696e';
    marginDomNode.id = "zoneMarginId";

    editor.changeViewZones(function(changeAccessor) {
      changeAccessor.addZone({
        afterLineNumber: 3,
        heightInLines: 3,
        domNode: zoneNode,
        marginDomNode: marginDomNode,
        onDomNodeTop: top => {
          overlayDom.style.top = top + "px";
        },
        onComputedHeight: height => {
          overlayDom.style.height = height + "px";
        }

      });
    });

Thank you very much for your Demo, it solved my problem

shanhexi avatar Mar 24 '24 08:03 shanhexi