Modify Blockly renderers, Decrease block height in Zelos

438 views
Skip to first unread message

Melissa Hollingsworth

unread,
Mar 23, 2023, 6:29:51 PM3/23/23
to Blockly
Hello,

I am currently using Blockly with the Zelos renderer. I prefer that one over Geras, but don't like that the blocks are so much taller than in Geras, and would like to change the font as well. I'm looking for a way to change/customize the Zelos renderer. I've tried simply copying the code from Zelos into a new renderer, but it was made with TypeScript and my project uses regular JavaScript. I've also tried looking through the Blockly.zelos object in the page body, but it doesn't offer a way to customize the height. I've also tried making my own renderer which "extends" the Zelos one, but none of the changes do anything.

Is there a way to customize the Zelos renderer to decrease the block height and change the font?

Mark Friedman

unread,
Mar 23, 2023, 7:28:18 PM3/23/23
to blo...@googlegroups.com
Melissa,

  I believe that what you want to do is to create a custom renderer, using the Zelos renderer as a base class, rather than copying the code.  The Blockly rendering mechanism is designed to support that and you can find the documentation for it here.  There's also a related codelab (i.e. tutorial) for creating a custom render here.

  Note that the code shown in the custom renderer codelab uses an older mechanism than the current Blockly code uses for creating JavaScript classes and establishing subclass relationships, so you may need to adjust that.

-Mark


--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/blockly/ffd657e0-6be0-4547-9cb5-6d722dac6774n%40googlegroups.com.

Melissa Hollingsworth

unread,
Mar 23, 2023, 8:52:32 PM3/23/23
to Blockly
We tried that, actually. We extended the zelos renderer, and our extension loaded, but none of the changes in it actually worked.

class OurRenderer extends Blockly.zelos.Renderer {
  //constants_!: ConstantProvider;
  constructor() {
    super();
  }
  makeConstants_() {
    return new OurConstantProvider();
  }
}

OurConstantProvider() is where we're trying to put our custom instructions. However, they don't seem to do anything. I've tried setting them to ludicrous levels, just to see a change, and I don't see a change.

I noticed that extending the renderer class is deprecated, so I thought perhaps there was just some different way to do it. 

Mark Friedman

unread,
Mar 24, 2023, 1:16:54 PM3/24/23
to blo...@googlegroups.com
Melissa,

  You probably did this, but just to be sure, did you register your custom renderer and use it as the renderer option in your call to Blockly.inject, as shown in steps 3 and 4 of the custom renderer documentation?  If so, are you seeing any messages in the browser console that might be related to your problem?  If not, perhaps you can post the code for your custom ConstantProvider?

I noticed that extending the renderer class is deprecated, so I thought perhaps there was just some different way to do it. 

As I understand it, the documentation is currently inconsistent, and extending an existing renderer class is still the way to go.

Hope this helps!

-Mark


Melissa Hollingsworth

unread,
Mar 24, 2023, 1:19:44 PM3/24/23
to Blockly
Yes, here is the code for our renderer:

class CoolRenderer extends Blockly.zelos.Renderer {
  //protected override constants_!: ConstantProvider;
  constructor() {
    super();
  }
  makeConstants_() {
    return new CoolConstantProvider();
  }
}

class CoolConstantProvider extends Blockly.zelos.ConstantProvider {
constructor(){
super();
this.GRID_UNIT = 4;
  this.MIN_BLOCK_HEIGHT = 4 * this.GRID_UNIT;
}

}

Blockly.blockRendering.register('cool', CoolRenderer);

And I did inject that renderer. There were no messages in the console at all, it just looked like Zelos, unchanged.

Mark Friedman

unread,
Mar 24, 2023, 6:09:09 PM3/24/23
to blo...@googlegroups.com
Melissa,

  I believe I have tracked this down.  It appears that the Zelos ConstantProvider (code here) sets a bunch of its constants based on this.GRID_UNIT in its constructor.  Consequently, changing the value of this.GRID_UNIT after the call to super has no effect on those constants.  I think that Zelos ConstantProvider should probably be changed to take the grid unit as an argument, but as a workaround until then you'll need to set all the constants that it sets explicitly in your ConstantProvider.  For example:

class CoolConstantProvider extends Blockly.zelos.ConstantProvider {
  constructor(){
    super();
    this.GRID_UNIT = 10;

    this.SHAPE_IN_SHAPE_PADDING = {
      1: {
        // Outer shape: hexagon.
        0: 5 * this.GRID_UNIT,  // Field in hexagon.
        1: 2 * this.GRID_UNIT,  // Hexagon in hexagon.
        2: 5 * this.GRID_UNIT,  // Round in hexagon.
        3: 5 * this.GRID_UNIT,  // Square in hexagon.
      },
      2: {
        // Outer shape: round.
        0: 3 * this.GRID_UNIT,  // Field in round.
        1: 3 * this.GRID_UNIT,  // Hexagon in round.
        2: 1 * this.GRID_UNIT,  // Round in round.
        3: 2 * this.GRID_UNIT,  // Square in round.
      },
      3: {
        // Outer shape: square.
        0: 2 * this.GRID_UNIT,  // Field in square.
        1: 2 * this.GRID_UNIT,  // Hexagon in square.
        2: 2 * this.GRID_UNIT,  // Round in square.
        3: 2 * this.GRID_UNIT,  // Square in square.
      },
    };

    this.SMALL_PADDING = this.GRID_UNIT;
    this.MEDIUM_PADDING = 2 * this.GRID_UNIT;
    this.MEDIUM_LARGE_PADDING = 3 * this.GRID_UNIT;
    this.LARGE_PADDING = 4 * this.GRID_UNIT;
    this.CORNER_RADIUS = 1 * this.GRID_UNIT;
    this.NOTCH_WIDTH = 9 * this.GRID_UNIT;
    this.NOTCH_HEIGHT = 2 * this.GRID_UNIT;
    this.NOTCH_OFFSET_LEFT = 3 * this.GRID_UNIT;
    this.STATEMENT_INPUT_NOTCH_OFFSET = this.NOTCH_OFFSET_LEFT;
    this.MIN_BLOCK_WIDTH = 2 * this.GRID_UNIT;
    this.MIN_BLOCK_HEIGHT = 12 * this.GRID_UNIT;
    this.EMPTY_STATEMENT_INPUT_HEIGHT = 6 * this.GRID_UNIT;
    this.TOP_ROW_MIN_HEIGHT = this.CORNER_RADIUS;
    this.TOP_ROW_PRECEDES_STATEMENT_MIN_HEIGHT = this.LARGE_PADDING;
    this.BOTTOM_ROW_MIN_HEIGHT = this.CORNER_RADIUS;
    this.BOTTOM_ROW_AFTER_STATEMENT_MIN_HEIGHT = 6 * this.GRID_UNIT;
    this.STATEMENT_BOTTOM_SPACER = -this.NOTCH_HEIGHT;
    /** Minimum statement input spacer width. */
    this.STATEMENT_INPUT_SPACER_MIN_WIDTH = 40 * this.GRID_UNIT;
    this.STATEMENT_INPUT_PADDING_LEFT = 4 * this.GRID_UNIT;
    this.EMPTY_INLINE_INPUT_PADDING = 4 * this.GRID_UNIT;
    this.EMPTY_INLINE_INPUT_HEIGHT = 8 * this.GRID_UNIT;
    this.DUMMY_INPUT_MIN_HEIGHT = 8 * this.GRID_UNIT;
    this.DUMMY_INPUT_SHADOW_MIN_HEIGHT = 6 * this.GRID_UNIT;
    this.CURSOR_WS_WIDTH = 20 * this.GRID_UNIT;
    this.FIELD_TEXT_FONTSIZE = 3 * this.GRID_UNIT;
    this.FIELD_BORDER_RECT_RADIUS = this.CORNER_RADIUS;
    this.FIELD_BORDER_RECT_X_PADDING = 2 * this.GRID_UNIT;
    this.FIELD_BORDER_RECT_Y_PADDING = 1.625 * this.GRID_UNIT;
    this.FIELD_BORDER_RECT_HEIGHT = 8 * this.GRID_UNIT;
    this.FIELD_DROPDOWN_BORDER_RECT_HEIGHT = 8 * this.GRID_UNIT;
    this.FIELD_DROPDOWN_SVG_ARROW_PADDING = this.FIELD_BORDER_RECT_X_PADDING;
    this.FIELD_COLOUR_DEFAULT_WIDTH = 2 * this.GRID_UNIT;
    this.FIELD_COLOUR_DEFAULT_HEIGHT = 4 * this.GRID_UNIT;
    this.FIELD_CHECKBOX_X_OFFSET = 1 * this.GRID_UNIT;
    /** The maximum width of a dynamic connection shape. */
    this.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH = 12 * this.GRID_UNIT;
  }
}

  I tried it and it appeared to work.

-Mark


Melissa Hollingsworth

unread,
Mar 24, 2023, 7:22:29 PM3/24/23
to Blockly
Thank you, 
this works!

Maribeth Bottorff

unread,
Mar 27, 2023, 2:01:01 PM3/27/23
to Blockly
Thanks for your help here, Mark!

I've filed a feature request for this problem here: https://github.com/google/blockly/issues/6928

Reply all
Reply to author
Forward
0 new messages