Customizing the Scratch Environment
Relevant source files
The following files were used as context for generating this wiki page:- apps/scratch/src/blocks/make-toolbox-xml.ts
- apps/scratch/src/components/customized-scratch-components/gui/Gui.tsx
- apps/scratch/src/containers/customized-scratch-containers/Blocks.tsx
- apps/scratch/src/components/TaskConfig.tsx
- frontend/src/pages/task/[taskId]/edit.tsx
- frontend/src/pages/class/[classId]/session/[sessionId]/task/[taskId]/solve.tsx
- apps/scratch/src/blocks/xml/sensing.ts
- frontend/src/components/task/TaskForm.tsx
The Collimator project integrates a heavily customized version of the Scratch GUI to serve as a structured environment for creating and solving programming tasks. Unlike the standard open-ended Scratch editor, this implementation introduces distinct modes for teachers (editing a task) and students (solving a task), with specific UI and functional constraints for each.
Key customizations include a dynamic block toolbox that can be restricted on a per-task basis, a system for freezing blocks to create immutable starter code, and specialized UI components for task configuration. These modifications are orchestrated through a central configuration object and a series of high-order components (HOCs) that wrap and extend the base Scratch GUI functionality.
Core Architecture
The customization is built around a central configuration object, ScratchCrtConfig, which is attached to the Scratch Virtual Machine (VM) instance. This object dictates the behavior of the editor, particularly the differences between the "edit" and "solve" modes.
ScratchCrtConfig
The ScratchCrtConfig object holds all task-specific settings. It is managed primarily through the TaskConfig modal in the editor's "edit" mode.
| Property | Type | Description | Source File |
|---|---|---|---|
allowedBlocks | BlockLimits | An object defining which blocks are available and their usage limits. | apps/scratch/src/blocks/make-toolbox-xml.ts:33-44 |
maximumExecutionTimeInMs | number | The maximum time in milliseconds a student's script can run, particularly for assertions. | apps/scratch/src/components/TaskConfig.tsx:136-138 |
enableStageInteractions | boolean | If true, students can interact with the stage (e.g., click sprites). | apps/scratch/src/components/TaskConfig.tsx:173-176 |
freezeStateByBlockId | Record<string, FreezeState> | Stores the "freeze" state for the top-level block of each stack (e.g., editable, frozen, appendable). | apps/scratch/src/containers/customized-scratch-containers/Blocks.tsx:1003-1006 |
Sources: apps/scratch/src/components/TaskConfig.tsx, apps/scratch/src/containers/customized-scratch-containers/Blocks.tsx
BlockLimits Type
The BlockLimits type is fundamental to restricting the toolbox. It's a record where keys are block opcodes and values determine their availability.
| Value | Meaning |
|---|---|
> 0 | The block can be used a specific number of times. |
0 | The block is not shown in the toolbox. |
< 0 (or -1) | The block can be used an unlimited number of times. |
undefined | The block is not shown in the toolbox. |
variables: boolean | Toggles the visibility of the "Variables" category. |
customBlocks: boolean | Toggles the visibility of the "My Blocks" (custom procedures) category. |
Sources: apps/scratch/src/blocks/make-toolbox-xml.ts:33-44
Component Hierarchy
The application wraps the standard Scratch GUI in several layers of HOCs to inject custom logic and state. The CrtHoc is particularly important for passing down the crtConfig and the canEditTask flag.
This diagram shows the component hierarchy for the customized GUI.
Dynamic Toolbox Generation
The block toolbox is not static; it is dynamically generated based on the allowedBlocks configuration for the current task. This process is primarily handled by the makeToolboxXML function.
The following diagram illustrates the flow of generating the toolbox XML.
The makeToolboxXML function iterates through each standard Scratch block category (Motion, Looks, etc.) and calls a corresponding builder function (e.g., buildSensingXml). These builders generate the XML for each block within that category, but only if the block is permitted by the blockLimits object. If a limit is 0 or the opcode is not present in blockLimits, the block is excluded from the generated XML.
Sources: apps/scratch/src/blocks/make-toolbox-xml.ts:182-198, apps/scratch/src/blocks/xml/sensing.ts:113-125
UI Customizations
The UI is significantly altered depending on whether the user is editing or solving a task. This is controlled by the canEditTask prop passed into the GUIComponent.
Edit Mode vs. Solve Mode
The application has two primary modes that dictate the user's capabilities within the Scratch editor. The mode is determined by the page loading the Scratch iframe (/edit vs. /solve).
| Feature | Edit Mode (canEditTask: true) | Solve Mode (canEditTask: false) |
|---|---|---|
| Toolbox | All blocks are available by default. | Restricted by crtConfig.allowedBlocks. |
| Block Config | Buttons open a configuration modal. | Buttons show usage counts (∞, 5, 0, etc.). |
| Block Freezing | Freeze buttons (✍️, 🔒, +) are visible and functional on block stacks. | Frozen blocks are immutable and cannot be moved or deleted. |
| Task Config | "Task Config" button is visible, allowing crtConfig modification. | "Task Config" button is hidden. |
| Extensions | "Add Extension" button is visible. | "Add Extension" button is hidden. |
| Assertions | Can be enabled/disabled via the Task Config modal. | Automatically enabled if the Assertions extension is part of the task. |
| Stage Interaction | Always enabled. | Controlled by crtConfig.enableStageInteractions. |
Sources: apps/scratch/src/components/customized-scratch-components/gui/Gui.tsx:218-228, 237-251, apps/scratch/src/containers/customized-scratch-containers/Blocks.tsx:509-513, 520-522, apps/scratch/src/components/TaskConfig.tsx:17-21
The Blocks Container
The customized Blocks container is a central hub for UI modifications within the block workspace. It overrides the default scratch-gui Blocks component to add custom functionality.
Key responsibilities include:
- Toolbox Updates: It listens for
UpdateBlockToolboxEventand callsrequestToolboxUpdateto regenerate the toolbox XML when the task configuration changes. - Block Freezing: It observes mutations to the block canvas. When new block stacks are added, it calls
addFreezeButtonsToStackto add the freeze state toggle buttons. In solve mode, it callsfreezeTaskBlocksto make configured blocks immutable. - Block Config Buttons: It calls
addBlockConfigButtonsto render the small configuration/counter buttons on each block in the flyout.
Sources: apps/scratch/src/containers/customized-scratch-containers/Blocks.tsx:327-331, 509-513, 856-860
Task Configuration Flow
When a teacher edits a task, they can use the "Task Config" modal to define the constraints for the student.
This sequence diagram shows how updating the configuration triggers a toolbox refresh.
Summary
The customization of the Scratch environment in Collimator is a comprehensive system designed to repurpose Scratch as a powerful tool for education and assessment. By introducing a central configuration object (ScratchCrtConfig), distinct user modes (canEditTask), and a dynamically generated UI, the platform provides teachers with fine-grained control over the learning environment. Key mechanisms like dynamic toolbox generation, block freezing, and role-specific component rendering are crucial to transforming the open-ended creative space of Scratch into a focused, task-oriented experience for students.