Two-Way Tools: Designer ↔ Code Sync
HarbourBuilder's Two-Way Tools engine ensures that your visual form design and your source code are always perfectly synchronized. Every change you make in the visual Form Designer is immediately reflected in the generated code, and every structural change you make to the code is instantly visible in the designer.
The code regeneration engine only updates UI definition lines (DEFINE, @ POSITION, properties). Your METHOD implementations, event handlers, and custom logic are never touched or overwritten.
How It Works
When you work in the Form Designer, every action — dropping a control, resizing, moving, changing a property — triggers a targeted code regeneration. The engine parses your existing source file, identifies the UI definition sections, updates them, and leaves everything else intact.
What Gets Regenerated
The code engine identifies and updates only these categories:
| Category | Example | Regenerated? |
|---|---|---|
| DEFINE statements | DEFINE FORM, DEFINE BUTTON | Yes |
| @ POSITION lines | @ 10, 20 BUTTON ... | Yes |
| Property assignments | ::cTitle := "Hello" | Yes |
| CLASS definitions | CLASS TForm1 FROM TForm | Yes |
| Control creation via code | TButton():New() | Yes |
| METHOD implementations | METHOD OnClick() CLASS TForm1 | No |
| Event handler bodies | bAction := { || ... } | No |
| Custom functions | static function MyHelper() | No |
| Comments | // TODO: ... | No |
Before and After: Code Regeneration
Before: You drop a button in the designer
CLASS TForm1 FROM TForm DATA oBtn1 METHOD CreateForm() METHOD OnBtnClick() ENDCLASS METHOD CreateForm() CLASS TForm1 ::cTitle := "Form1" ::nWidth := 400 ::nHeight := 300 return nil METHOD OnBtnClick() CLASS TForm1 // Your custom logic - PRESERVED MsgInfo( "Button clicked!" ) return nil
After: Code regenerated (button added, method untouched)
CLASS TForm1 FROM TForm DATA oBtn1 METHOD CreateForm() METHOD OnBtnClick() ENDCLASS METHOD CreateForm() CLASS TForm1 ::cTitle := "Form1" ::nWidth := 400 ::nHeight := 300 // --- NEW: Button added by designer --- @ 120, 140 BUTTON ::oBtn1 PROMPT "Button1" ; OF Self SIZE 120, 32 ; ACTION ::OnBtnClick() return nil METHOD OnBtnClick() CLASS TForm1 // Your custom logic - PRESERVED MsgInfo( "Button clicked!" ) return nil
The OnBtnClick method body is completely unchanged. Only the
CreateForm method received the new button definition.
Workflow
Code Parsing Rules
The regeneration engine uses these rules to identify safe-to-modify sections:
- CLASS / ENDCCLASS blocks — DATA and METHOD declarations are updated; existing METHOD bodies are skipped.
DEFINE FORMblocks — Properties within DEFINE blocks are regenerated.- @ POSITION statements — Position, size, and property clauses are updated.
ACTIVATE FORMblocks — Activation clauses are regenerated.- Everything else — Static functions, METHOD bodies, comments, and custom code are left untouched.
Keep your custom logic in separate METHOD implementations or static functions rather than inline within DEFINE blocks. This makes it easier for the regeneration engine to identify and preserve your code.
Handling Conflicts
If you manually edit a line that the designer also manages (e.g., changing a button's position in code while it's also on the form canvas), the designer's view takes precedence on the next regeneration. To avoid conflicts:
- Use the Object Inspector to change properties rather than editing code directly.
- Use the Designer canvas to move and resize controls.
- Use the Code Editor only for METHOD implementations, event handlers, and custom functions.
The regeneration engine has been tested with over 200 edge cases including nested DEFINE blocks, multiple forms in one file, mixed class-based and procedural syntax, and files with extensive comments.
Switching Between Views
Use the toolbar toggle or keyboard shortcut to switch between Designer and Code views:
| Shortcut | Action |
|---|---|
| F12 | Toggle between Designer and Code views |
| Ctrl+Tab | Cycle through open editor tabs |
| Ctrl+S | Save (both design data and code) |