anchor.diff:          this._scrollToMainBlock();
         },
   
  -      setToolbox(toolboxXml) {
  -        this._getBlockly().toolbox = { defaultToolbox: toolboxXml };
  -        // Blockly's workspace is destroyed when toolbox changes, so we initialize it here.
  -        this._initializeBlocklyWorkspace();
  -      },
  -
  -      loadToolboxFromUrl(toolboxUrl) {
  -        $.get(toolboxUrl, (toolboxXml) => {
  -          this.setToolbox(toolboxXml);
  -        });
  +      /**
  +       * Configures a custom toolbox using a toolbox url
  +       * This method does nothing if editor is read-only, but
  +       * assumes a gs-toolbox element is present - otherwise it would
  +       * have no sense to have a toolboxUrl.
  +       */
  +      configureCustomToolboxFromUrl(toolboxUrl) {
  +        if (!this.readOnly) {
  +          $.get(toolboxUrl, (toolboxXml) => {
  +            this._initializeCustomToolboxBlocklyWorkspace(toolboxXml);
  +          });
  +        }
  +      },
  +
  +      /**
  +       * Wether a custom toolbox is required. Read only editors and gs-toolbox-less context
  +       * don't require it
  +       */
  +      hasCustomToolbox() {
  +        return !this.readOnly && $('gs-toolbox').length;
         },
   
         compile(code) {
  
positive.code:         });
  
          $(window).resize(() => this._relocateTrash());
        },
  
        _initializeBlocklyWorkspace() {
  
negative.code:       _configureBlocklyBehavior() {
          this._setTeacherActions();
          this._setGameActions();
          this._initializeNonCustomToolboxBlocklyWorkspace();
          this._registerLayoutChangedEvent();
        },
  
  