**What does this PR accomplish?**
This PR introduces the `@DefaultValue` annotaâŠtion, which allows component and extension developers to attach real, editable blocks to parameters directly within the Blocks drawer.
*Description*
Currently, when a user drags a component block from the drawer, the parameter sockets are empty, which can be confusing for beginners. With this change, the component appears in the palette with a reasonable default value (e.g., a math "0" or a text "hello") already attached. This provides immediate visual guidance on the expected data type and saves the user from manually searching for basic data blocks to fill the sockets.
*Testing Guidelines*
1. Create or modify a component method/property in Java.
2. Annotate a parameter with @DefaultValue("50") for an int or @DefaultValue("#FFFFFF") for a color.
3. Build the project and open the Blocks Editor.
4. Open the component's drawer; the block should appear with the default value block already attached.
5. Drag the block into the workspace and verify the attached block remains editable and detachable.
6. Here is a demo extension:
```java
package com.jewel.defaultvaluetest;
import com.google.appinventor.components.annotations.Asset;
import com.google.appinventor.components.annotations.DefaultValue;
import com.google.appinventor.components.annotations.DesignerComponent;
import com.google.appinventor.components.annotations.DesignerProperty;
import com.google.appinventor.components.annotations.PropertyCategory;
import com.google.appinventor.components.runtime.AndroidNonvisibleComponent;
import com.google.appinventor.components.runtime.ComponentContainer;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.annotations.SimpleObject;
import com.google.appinventor.components.annotations.SimpleProperty;
import com.google.appinventor.components.runtime.util.YailDictionary;
import com.google.appinventor.components.runtime.util.YailList;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.common.PropertyTypeConstants;
import com.jewel.defaultvaluetest.helpers.TestPriority;
@DesignerComponent(
version = 7,
versionName = "1.0",
description = "Developed by JEWEL using Fast.",
category = ComponentCategory.EXTENSION,
nonVisible = true,
iconName = "aiwebres/icon.png"
)
@SimpleObject(external = true)
public class DefaultValueTest extends AndroidNonvisibleComponent {
public DefaultValueTest(ComponentContainer container) {
super(container.$form());
}
@SimpleFunction(description = "A return type method with three parameters. First parameter has default value.")
public int MethodA(@DefaultValue("10") int firstNumber, int secondNumber, TestPriority priority) {
System.out.println(priority.toUnderlyingValue());
return firstNumber + secondNumber;
}
@SimpleFunction(description = "A void method with three parameters. Second parameter has default value.")
public void MethodB(String text, @DefaultValue("20") int number, TestPriority priority) {
System.out.println(text);
System.out.println(number);
System.out.println(priority.toUnderlyingValue());
}
@SimpleFunction(description = "A void method without default values but asset.")
public void MethodC(int number, String text, @Asset String name) {
System.out.println(number);
System.out.println(text);
System.out.println(name);
}
@SimpleProperty(category = PropertyCategory.APPEARANCE, description = "A setter without DesignerProperty but default value.")
public void SetterA(@DefaultValue("no designer but value") String text) {
System.out.println(text);
}
@DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_TEXT, defaultValue = "designer detter value")
@SimpleProperty(category = PropertyCategory.APPEARANCE, description = "A setter with DesignerProperty.")
public void SetterB(String text) {
System.out.println(text);
}
@SimpleProperty(category = PropertyCategory.APPEARANCE, description = "A setter without DesignerProperty and no value.")
public void SetterC(String text) {
System.out.println(text);
}
@SimpleProperty(category = PropertyCategory.APPEARANCE, description = "A setter without default value but asset.")
public void SetterD(@Asset String name) {
System.out.println(name);
}
@SimpleProperty(category = PropertyCategory.APPEARANCE, description = "A setter without default value but helper.")
public void SetterE(TestPriority priority) {
System.out.println(priority.toUnderlyingValue());
}
@SimpleProperty(category = PropertyCategory.APPEARANCE, description = "A setter that accept empty list.")
public void SetterF(@DefaultValue YailList list) {
System.out.println(list.toString());
}
@SimpleProperty(category = PropertyCategory.APPEARANCE, description = "A setter that accept list with three arguments.")
public void SetterG(@DefaultValue("Value1, Value2, Value3") YailList list) {
System.out.println(list.toString());
}
@SimpleProperty(category = PropertyCategory.APPEARANCE, description = "A setter that accept an empty dictionary.")
public void SetterH(@DefaultValue YailDictionary dictionary) {
System.out.println(dictionary.toString());
}
@SimpleProperty(category = PropertyCategory.APPEARANCE, description = "A setter that accept color.")
public void SetterI(@DefaultValue("#f7df0b") int color) {
System.out.println(color);
}
@SimpleProperty(category = PropertyCategory.APPEARANCE, description = "A setter that accept boolean.")
public void SetterJ(@DefaultValue("False") boolean enabled) {
System.out.println(enabled);
}
@SimpleProperty(category = PropertyCategory.APPEARANCE, description = "A setter that accept list with (number type) three arguments.")
public void SetterK(@DefaultValue(value = "10, 20, 30", type = "number") YailList list) {
System.out.println(list.toString());
}
@SimpleProperty(category = PropertyCategory.APPEARANCE, description = "A setter that accept dictionary with three pairs.")
public void SetterL(@DefaultValue("key1:value1, key2:value2, key3:value3") YailDictionary dictionary) {
System.out.println(dictionary.toString());
}
}
```
7. Expected output:
<img width="778" height="1036" alt="image" src="https://github.com/user-attachments/assets/cf002c7f-e25d-4ae5-9639-82aed20e06dd" />
Resolves # .
#2384
**Context for the changes**
If this PR changes anything related to the companion make sure you have used the `ucr` branch. For all other changes use `master` or provide context for having used a different branch.
See a summary of git branches in the docs: [App Inventor Developer Overview](https://docs.google.com/document/u/1/d/1hIvAtbNx-eiIJcTA2LLPQOawctiGIpnnt0AvfgnKBok/pub#h.g4ai8y7wpbh6)
If your code changes how something works on the device (i.e., it affects the companion):
- [x] I have made no changes that affect the companion
- [ ] I branched from `ucr`
- [ ] My pull request has `ucr` as the base
Further, if you've changed the blocks language or another user-facing designer/blocks API (added a SimpleProperty, etc.):
- [ ] I have updated the corresponding version number in appinventor/components/src/.../common/YaVersion.java
- [ ] I have updated the corresponding upgrader in appinventor/appengine/src/.../client/youngandroid/YoungAndroidFormUpgrader.java (components only)
- [ ] I have updated the corresponding entries in appinventor/blocklyeditor/src/versioning.js
For all other changes:
- [ ] I have made no changes that affect the master branch
- [x] I branched from `master`
- [x] My pull request has `master` as the base
**General items:**
- [ ] I have updated the relevant documentation files under docs/
- [x] My code follows the:
- [x] [Google Java style guide](https://google.github.io/styleguide/javaguide.html) (for .java files)
- [x] [Google JavaScript style guide](https://google.github.io/styleguide/jsguide.html) (for .js files)
- [ ] [Swift style guide](https://google.github.io/swift/) (for .swift files)
- [x] Indentation has been doubled checked
- [x] This PR does not include unnecessary changes such as formatting or white space
- [x] `ant tests` passes on my machine
### **Key Changes**
* **New Annotation:** Added `@DefaultValue` with support for `value` and an optional `type`.
* **Compiler Integration:** Updated the `ComponentProcessor` to parse these values and include them in the component descriptor JSON.
* **Blockly Editor Support:** Modified the blocklyeditor logic to recognize these default values and render the corresponding blocks (text, number, boolean, color, list, dictionary) as attached inputs in the drawer.
* **Smart Validation:** Added compiler-level checks to prevent errors:
* **Events:** Prevents using `@DefaultValue` on Event parameters (since they are output values).
* **Designer Properties:** Prevents conflicts by ensuring `@DesignerProperty` setters use their own `defaultValue` attribute instead.
### **Usage & Formatting**
The system automatically infers the block type from the parameter (e.g., `int` becomes a math block), but it can be manually specified for `Object` types.
* **Colors:** Use 6 digit hex format (e.g., `#FFFFFF`).
* **Lists:** Use comma-separated values (e.g., `item1, item2`).
* **Dictionaries:** Use key-value pairs (e.g., `key1:val1, key2:val2`).
* **Primitives:** Standard strings, numbers, or booleans (e.g., `100`, `hello`, `true`).
```java
@SimpleProperty
public void LedColor(@DefaultValue("#00FF00") int color) {
// This block will now appear in the drawer with a green color block attached.
}
```