Skip to content

Commit

Permalink
constraintDelegate Doc & enhancements
Browse files Browse the repository at this point in the history
  • Loading branch information
vdelachaux committed Sep 22, 2023
1 parent bfa139a commit 8e33a41
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 12 deletions.
108 changes: 108 additions & 0 deletions Documentation/Classes/constraintsDelegate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# constraintsDelegate

The `constraintsDelegate` class retains the rules for moving and resizing form objects, and manages them during resizing.

> 📌 Note that, for the moment, only horizontal rules are supported.
> (I've never needed vertical constraints, but perhaps I will in the future...).
## Properties

|Properties|Description|Type|default|
|:----------|:-----------|:-----------:|:-----------|
|**.rules** | The constraints [rules](#rule) |`Collection`| [ ]
|**.scrollBarWidth** | Width of scroll bar |`Integer`| macOS = 15px<br>Windows = 15px
|**.marginH** | Default horizontal spacing between items |`Integer`| macOS = 20px<br>Windows = 20px
|**.labelMargin** | Default spacing between label and input box |`Integer`| macOS = 10px<br>Windows = 10px
|**.offset** | Default offset |`Integer`| macOS = 2px<br>Windows = 2px


| Functions | Action |
|:-------- |:------ |
|.**load**(file: `4D.File`) | Load rules and default values from a file|
|.**setMetrics**(metrics: `Object`) | Allow to set in one time the default values|
|.**add**(rule: `Object`)  → `cs.constraintsDelegate`| Stores a [rule](#rule) or a [set of rules](#set)|
|.**apply**() | Dealing with constraints|


|**.set** | A collection of [rule objects](#rule)|`Collection`| All others properties are ignored

## <a name="rule">Rule object</a>

A rule can have one or more of the following properties.

|Properties|Description|Type||
|:----------|:-----------|:-----------:|:-----------|
|**.formula** | A formula that will be executed|`Text` \| `4D.Function`| All others properties are ignored
|**.target** | The item to which the rule applies.<br>**Mandatory if not a [set of rules](#set)**|`Text` \| `widget`|<br>It can be a comma-separated list of names
|**.type** |[Constraint](#constraint) type.<br>**Mandatory if formula is null**|`Text`|
|**.alignment** | Alignment for certain constraints |`Text`|
|**.value** | Value in percent or px|`Real`| \*
|**.margin** | Margin to respect in px |`Integer`|\*\*
|**.reference** | Name of the element to take as reference|`Text`| Default is current viewport <br>(dialog or container size)
|**.label**|Name of the associated label|`Text`| \*\*\*
|**.toDelete**|**True** if the rule should be deleted after application|`Boolean`|Enables a rule to be applied only once, usually on loading.

\* for `right`, `left`, `minimum-width`, `maximum-width`, `tile` & `float` rules

\*\* for `fit-width`, `margin` left or right, `horizontal-alignment` left or right, `anchor` left or right, `inline` & `float` left or right

\*\*\* If ommitted use "\<target>.label" if exists

## <a name="set">Set of rules</a>

Allow to store more than one rule for a same target.

|Properties|Description|Type||
|:----------|:-----------|:-----------:|:-----------|
|**.target** | The item to which the rule applies. <br>Mandatory!|`Text` \| `widget`|<br>It can be a comma-separated list of names
|**.set** | Collection of [rule objects](#rule) without target|`Collection`|All others properties are ignored


## <a name="constraint">Constraint types</a>

|Properties|Description| |
|:----------|:-----------|:-----------|
|"right"|Keeps the right edge of an element as % of the ref|`value` From 0 to 1 or 1 to 100
|"left"|Keeps the left edge of an element as % of the ref|`value` From 0 to 1 or 1 to 100
|"minimum-width"|Sets the minimum width of an element|`value` = limit in px
|"maximum-width"|Sets the maximum width of an element|`value` = limit in px
|"fit-width"|Adjusts width to ref |Optional `margin` left & right in px, default is 0
|"margin"|Maintains a horizontal margin from the ref |`alignment` should be "auto", "left" or "right"
|"horizontal-alignment"| Maintains vertical alignment with the reference |`alignment` should be "center", "left" or "right". <br>`margin` if passed is used for "left" & "right" alignments
|"anchor"| Maintains vertical alignment with the reference |`alignment` should be "center", "left" or "right". <br>`margin` if passed is used for "left" & "right" alignments
|"inline"| Maintains the element at the right of the reference | use `margin`if passed, `marginH` if not
|"tile"| Set element width as percent of the reference | `value` From 0 to 1 or 1 to 100


## <a name="sample">Code sample</a>

```4d
// Class _myDialog_Controller
Class constructor This.isSubform:=False This.toBeInitialized:=False // Instantiate the formDelegate This.form:=cs.formDelegate.new(This)
...
This.form.init()
Function init()
This.listbox:=This.form.listbox.new("List Box")
...
// The right edge of the lisbox must be in the middle (50%) of the dialog, // & the width must be no less than 130px and no more than 520 px This.form.constraints.add({target: This.listbox; set: [\ {type: "right"; value: 50}; \ {type: "minimum-width"; value: 150}; \ {type: "maximum-width"; value: 520}\ ]})
// The "input" box must stay centered in the dialog. // 📌 The "input.label" is automatically attached to the input box. This.form.constraints.add({\ target: "input"; \ type: "horizontal-alignment"; \ alignment: "center"\ })
...
Function handleEvents($e : cs.evt) $e:=$e || cs.evt.new() If ($e.form) // Mark: FORM METHOD Case of //============================================== : ($e.load) This.form.onLoad() //============================================== : ($e.resize) // Applying the constraints This.form.constraints.apply() //============================================== End case Else // Mark: WIDGETS METHOD
... End if
Function onLoad()
...
// Applying the constraints This.form.constraints.apply()
```

Expand Down
1 change: 1 addition & 0 deletions Documentation/Classes/formDelegate.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ Function update()
|**.isSubform** | Is the form used as a subform * |`Boolean`|**False**|<font color="green">X</font>
|**.toBeInitialized** | Has the form been initialized * |`Boolean`|**True**|<font color="green">X</font>
|**.window** | Current form window class object |`cs.windowDelegate`
|**.constraints** | The constraints manager |`cs.constraintsDelegate`

> * To be set up by the dialog form class
Expand Down
4 changes: 2 additions & 2 deletions Project/Sources/Classes/_DEMO_constraints_Controller.4dm
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ Function init()
// The left panel should always be 50% of the window width
This:C1470.form.constraints.add({\
target: "left"; \
type: "right"; \
value: 50\
type: "tile"; \
value: 0.5\
})

// The right edge of the first hello world must be in the middle (50%),
Expand Down
51 changes: 42 additions & 9 deletions Project/Sources/Classes/constraintsDelegate.4dm
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,37 @@ Class constructor($metrics : Object)

This:C1470.rules:=[]

If (OB Instance of:C1731($metrics; 4D:C1709.File))

This:C1470.load($metrics)

Else

This:C1470.setMetrics($metrics)

End if

This:C1470._matrix:=Not:C34(Is compiled mode:C492) // True if Dev mode

// === === === === === === === === === === === === === === === === === === === === === === === ===
Function load($file : 4D:C1709.File)

var $metrics; $o : Object

$o:=JSON Parse:C1218($metrics.getText().rules)
This:C1470.rules:=$o.rules || []

This:C1470.setMetrics($o)

// === === === === === === === === === === === === === === === === === === === === === === === ===
Function setMetrics($metrics : Object)

// TODO: Adjusting default values for Windows
This:C1470.scrollBarWidth:=$metrics.scrollBarWidth || Is macOS:C1572 ? 15 : 15
This:C1470.marginV:=$metrics.marginV || Is macOS:C1572 ? 2 : 2
This:C1470.marginH:=$metrics.marginH || Is macOS:C1572 ? 20 : 20

This:C1470.labelMargin:=Is macOS:C1572 ? 10 : 10
This:C1470.offset:=2

This:C1470._matrix:=Not:C34(Is compiled mode:C492) // True if Dev mode
This:C1470.labelMargin:=$metrics.labelMargin || Is macOS:C1572 ? 10 : 10
This:C1470.offset:=$metrics.offset || Is macOS:C1572 ? 2 : 2

// === === === === === === === === === === === === === === === === === === === === === === === ===
Function add($rule : Object) : cs:C1710.constraintsDelegate
Expand Down Expand Up @@ -78,10 +101,18 @@ Function apply()

For each ($rule; This:C1470.rules)

If ($rule.formula#Null:C1517)\
&& (OB Instance of:C1731($rule.formula; 4D:C1709.Function))
If ($rule.formula#Null:C1517)

If (OB Instance of:C1731($rule.formula; 4D:C1709.Function))

$rule.formula()

Else

Formula from string:C1601(String:C10($rule.formula)).call(Null:C1517)

End if

$rule.formula.call(Null:C1517)
continue

End if
Expand Down Expand Up @@ -434,7 +465,9 @@ Function apply()

// MARK:tile
// Calculate proportional width
$width:=Int:C8(($ref.width)*Num:C11($rule.value))
$width:=Int:C8(($ref.width)*($rule.value<1 ? $rule.value : $rule.value/100))

//$width:=$ref.width*($rule.value<1 ? $rule.value : $rule.value/100)

If ($rule.parent#Null:C1517)

Expand Down
3 changes: 3 additions & 0 deletions Project/Sources/Classes/formDelegate.4dm
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ property isSubform; toBeInitialized : Boolean
property pages : Object
property entryOrder; _instantiableWidgets; _mapEvents : Collection

property window : cs:C1710.windowDelegate
property constraints : cs:C1710.constraintsDelegate

property __CLASS__ : Object
property __DELEGATES__ : Collection

Expand Down
2 changes: 1 addition & 1 deletion Project/Sources/Forms/DEMO_constraints/form.4DForm
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@
}
}
],
"geometryStamp": 899,
"geometryStamp": 907,
"editor": {
"activeView": "View 1",
"defaultView": "View 1",
Expand Down
28 changes: 28 additions & 0 deletions Resources/en.lproj/syntaxEN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2480,6 +2480,17 @@
"Params": [],
"Summary": ""
},
"load()": {
"Syntax": "**.load**( *file* : 4D.File )",
"Params": [
[
"file",
"4D.File",
"->"
]
],
"Summary": ""
},
"add()": {
"Syntax": "**.add**( *rule* : Object ) : cs.ui.constraintsDelegate",
"Params": [
Expand All @@ -2496,6 +2507,17 @@
],
"Summary": ""
},
"setMetrics()": {
"Syntax": "**.setMetrics**( *metrics* : Object )",
"Params": [
[
"metrics",
"Object",
"->"
]
],
"Summary": ""
},
"rules": {
"Syntax": "rules : Collection"
}
Expand Down Expand Up @@ -5169,6 +5191,9 @@
"Params": [],
"Summary": ""
},
"window": {
"Syntax": "window : cs.ui.windowDelegate"
},
"entryOrder": {
"Syntax": "entryOrder : Collection"
},
Expand All @@ -5178,6 +5203,9 @@
"toBeInitialized": {
"Syntax": "toBeInitialized : Boolean"
},
"constraints": {
"Syntax": "constraints : cs.ui.constraintsDelegate"
},
"isSubform": {
"Syntax": "isSubform : Boolean"
}
Expand Down

0 comments on commit 8e33a41

Please sign in to comment.