diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b53123d..d529c89 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,6 +15,8 @@ a duplicate. * Describe steps to reproduce * Full error message if any * Your code if relevant + +Of course you could propose a fix using pull request ### Feature request @@ -31,13 +33,21 @@ a duplicate. * Open a single pull request for each subject. * Prefer to develop in a topic [branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-branches), not master (feature/name) * Update documentation where applicable. +* If any bug related, add `#` in commit message or pull request +* Test your code * The project is organized into folders on the Explorer home page. Please respect this. * The project must be compilable with the "All variable are typed" setting and please don't generate typing! -* When it is necessary, create a `Compiler_xxx` inside each folders for compilation declarations + +### Method properties + +* Methods must be private ie. set invisible by default, if not documented and not to be acceded from outside. +* Method must be set preemptive if possible. ### Naming rules * Try to be compliant with the existing namimg. +* Create a folder by category +* When it is necessary, create a `Compiler_categoryName` inside each folders for compilation declarations * Note that all the generic classe names are camelCase ### Only touch relevant files diff --git a/Documentation/Classes/formDelegate.md b/Documentation/Classes/formDelegate.md index 499a3d4..12759a9 100644 --- a/Documentation/Classes/formDelegate.md +++ b/Documentation/Classes/formDelegate.md @@ -2,7 +2,7 @@ The `formDelegate` class is intended to be called as a delegate by a dialog form class, as in the code example below line 8. -### Code sample for a dialog form class +### Code sample for a dialog form class ```4d // Class _myDialog_Controller diff --git a/Project/Sources/Classes/_DEMO_1_Controller.4dm b/Project/Sources/Classes/_DEMO_1_Controller.4dm index 858bc42..ec97fdb 100644 --- a/Project/Sources/Classes/_DEMO_1_Controller.4dm +++ b/Project/Sources/Classes/_DEMO_1_Controller.4dm @@ -11,7 +11,6 @@ Class constructor // MARK:-Delegates 📦 This:C1470.form:=cs:C1710.formDelegate.new(This:C1470) - // MARK:- This:C1470.form.init() // MARK:-[Standard Suite] @@ -62,6 +61,7 @@ Function handleEvents($e : cs:C1710.evt) End if + // All is OK, so we can validate ACCEPT:C269 //============================================== @@ -82,7 +82,7 @@ Function onLoad() // Set window title This:C1470.form.window.title:="Passkey" - // Set the textbox as password an set a placeholder for it + // Set the textbox as password & set a placeholder for it This:C1470.pwd.setPlaceholder("Please enter your password...") This:C1470.pwd.asPassword:=True:C214 diff --git a/Project/Sources/Classes/_DEMO_menus_Controller.4dm b/Project/Sources/Classes/_DEMO_menus_Controller.4dm index 152d8d9..b6b3358 100644 --- a/Project/Sources/Classes/_DEMO_menus_Controller.4dm +++ b/Project/Sources/Classes/_DEMO_menus_Controller.4dm @@ -79,6 +79,7 @@ Function init() Function handleEvents($e : cs:C1710.evt) $e:=$e || cs:C1710.evt.new() + If ($e.form) // Mark: FORM METHOD diff --git a/Project/Sources/Forms/DEMO_1/form.4DForm b/Project/Sources/Forms/DEMO_1/form.4DForm index 3b26c67..b4f87cc 100644 --- a/Project/Sources/Forms/DEMO_1/form.4DForm +++ b/Project/Sources/Forms/DEMO_1/form.4DForm @@ -3,8 +3,8 @@ "version": "1", "kind": "form" }, - "windowSizingX": "variable", - "windowSizingY": "variable", + "windowSizingX": "fixed", + "windowSizingY": "fixed", "windowMinWidth": 0, "windowMinHeight": 0, "windowMaxWidth": 32767, @@ -12,10 +12,8 @@ "rightMargin": 20, "bottomMargin": 20, "events": [ - "onLoad", - "onValidate" + "onLoad" ], - "windowTitle": "window title", "destination": "detailScreen", "pages": [ { @@ -30,8 +28,6 @@ "width": 315, "height": 17, "events": [ - "onLosingFocus", - "onDataChange", "onAfterEdit" ], "dataSource": "Form:C1466.pwd" @@ -65,16 +61,14 @@ "left": 145, "width": 154, "height": 22, - "events": [ - "onClick" - ], + "events": [], "action": "cancel", "focusable": false } } } ], - "geometryStamp": 41, + "geometryStamp": 43, "method": "formMethod", "editor": { "activeView": "View 1", diff --git a/Project/Sources/folders.json b/Project/Sources/folders.json index d820eb8..a73c9a6 100644 --- a/Project/Sources/folders.json +++ b/Project/Sources/folders.json @@ -7,6 +7,9 @@ ], "forms": [ "Form1" + ], + "classes": [ + "tips" ] }, "♻️ LIBRAIRIES": { diff --git a/README.md b/README.md index daf8a8a..cc4db27 100644 --- a/README.md +++ b/README.md @@ -64,18 +64,37 @@ If (Form.myPassword.catch()) Form.myButton.enable(Form.myPassword.isNotEmpty) ``` What's more, if a 4D command evolves, a simple update to a class function immediately benefits all objects in the project. -## Design +## Where to start -🚧 +1. See the [How it works](#how) section below. +1. I suggest you first look at ***DEMO_1***, which is a simple case, to understand the design. Then you can run and explore the other demos that introduce more complicated or specific uses, I'm trying to show use cases like menu bar management or contextual menus. Other demonstrations will follow (I need to enrich this part), as it's also instructive for optimizing and enriching commands. +1. See the [Documentation](Documentation/Classes/) folder. I suggest you begin with the [`formDelegate` class documentation](Documentation/Classes/formDelegate.md). -## Where to start? +> Please note that not all documentation is available/updated yet. +> *As always, writing documentation is a time-consuming but instructive task, because in a number of cases it leads to changes, since what isn't simply described isn't a good implementation.* -There are a few demonstrations in the repository (I need to enrich this part). I suggest you first look at ***DEMO_1***, which is a simple case, to understand the design. Then, the other demonstrations introduce more complicated or more specific uses, I'm trying to show some use cases like menu bar management or contextual menus. More demonstrations will follow, as it's very instructive for optimizing and enriching commands. +## How does it work +As you can see from the demos included in the project, each demo consists of a form and a class named `__Controller`. which I call the "`dialog class`". (The method with the same name as the form simply displays the dialog) -See the [Documentation](Documentation/Classes/) folder. I suggest you begin with the [`formDelegate` class documentation](Documentation/Classes/formDelegate.md). +![Explorer](README/explorer.png) -> Please note that not all documentation is yet available. As always, writing documentation is a time-consuming but instructive task, because in a number of cases it leads to changes, since what isn't simply described isn't a good implementation. +1️⃣ All forms use the method `formMethod` as the form method. +>This method initializes the `dialog class`, if this is not the case, then calls its `handleEvents($e)` function, giving it the form's event object. +>Also note that there are no object method + +![Form](README/form.png) + +2️⃣ In the` dialog class` constructor, the property `.form` is set as `cs.formDelegate.new(This) `where **This** is the dialog class. + +3️⃣ The` dialog class `define, at least one function: `.handleEvents()` + +```4d +// Class _myDialog_Controller +Class constructor This.isSubform:=False This.toBeInitialized:=False // Instantiate the formDelegate This.form:=cs.formDelegate.new(This) + + This.form.init() // MARK:-[Standard Suite] // === === === === === === === === === === === === === === === === === === === === === Function init() /* Instantiate the widgets we want to manipulate. • Note that the label is not instantiated, as we don't need to act on it. */ This.pwd:=This.form.input.new("Input") // Bottom buttons This.ok:=This.form.button.new("Button") This.cancel:=This.form.button.new("Button1") // === === === === === === === === === === === === === === === === === === === === === Function handleEvents($e : cs.evt) $e:=$e || cs.evt.new() If ($e.form) // <== FORM METHOD Case of //============================================== : ($e.load) This.form.onLoad() //============================================== End case Else // <== WIDGETS METHOD Case of //============================================== : (This.ok.catch($e; [On Clicked])) // Make some validation then accept or not… If (This.pwd.isEmpty || (This.pwd.value="1234")) ALERT("Invalid pasword!") This.pwd.focus() return End if // All is OK, so we can validate ACCEPT //============================================== : (This.pwd.catch()) This.ok.enable(This.pwd.isNotEmpty) //============================================== End case End if // === === === === === === === === === === === === === === === === === === === === === Function onLoad() // Create and install a minimal menu bar cs.menuBar.new().defaultMinimalMenuBar().set() // Set window title This.form.window.title:="Passkey" // Set the textbox as password & set a placeholder for it This.pwd.setPlaceholder("Please enter your password...") This.pwd.asPassword:=True // Distribute bottom buttons according to their label This.form.group.new(This.ok; This.cancel).distributeRigthToLeft() This.ok.helpTip:="Click here to validate your password" This.cancel.helpTip:="Click here to abandon" This.ok.disable() +``` ## Collaborate diff --git a/README/explorer.png b/README/explorer.png new file mode 100644 index 0000000..86bef5e Binary files /dev/null and b/README/explorer.png differ diff --git a/README/form.png b/README/form.png new file mode 100644 index 0000000..1608032 Binary files /dev/null and b/README/form.png differ