From 9359002ae6e72e9e02e02519d7353190e6621974 Mon Sep 17 00:00:00 2001 From: Vincent de Lachaux Date: Fri, 30 Aug 2024 19:19:15 +0200 Subject: [PATCH] Demo tabs with object or list as datasource --- UI/Project/Sources/Classes/tabControl.4dm | 3 + UI/Resources/en.lproj/syntaxEN.json | 4 +- .../Classes/_DEMO_TAB_CONTROL_Controller.4dm | 72 ++++++++++++ .../Sources/Classes/_HDI_Controller.4dm | 7 +- .../Forms/DEMO_TAB_CONTROL/form.4DForm | 109 ++++++++++++++++++ test UI/Project/Sources/dependencies.json | 66 ++++++++++- test UI/Project/Sources/folders.json | 11 +- test UI/Resources/en.lproj/HDI.xlf | 15 +++ test UI/Resources/fr.lproj/HDI.xlf | 15 +++ test UI/Resources/github.svg | 3 + test UI/Resources/local.svg | 3 + 11 files changed, 303 insertions(+), 5 deletions(-) create mode 100644 test UI/Project/Sources/Classes/_DEMO_TAB_CONTROL_Controller.4dm create mode 100644 test UI/Project/Sources/Forms/DEMO_TAB_CONTROL/form.4DForm create mode 100644 test UI/Resources/github.svg create mode 100644 test UI/Resources/local.svg diff --git a/UI/Project/Sources/Classes/tabControl.4dm b/UI/Project/Sources/Classes/tabControl.4dm index a9ba0f0..05de867 100644 --- a/UI/Project/Sources/Classes/tabControl.4dm +++ b/UI/Project/Sources/Classes/tabControl.4dm @@ -115,9 +115,12 @@ Function goToPage() Else $page:=This:C1470.pageNumber + //This.data.index:=$page-1 End if + This:C1470.pageNumber:=$page + If (Value type:C1509(OBJECT Get subform container value:C1785)#Is undefined:K8:13) FORM GOTO PAGE:C247($page; *) diff --git a/UI/Resources/en.lproj/syntaxEN.json b/UI/Resources/en.lproj/syntaxEN.json index 64fe796..bb2aac7 100644 --- a/UI/Resources/en.lproj/syntaxEN.json +++ b/UI/Resources/en.lproj/syntaxEN.json @@ -224,11 +224,11 @@ }, "evt": { "new()": { - "Syntax": "**.new**( *e* : cs.ui.evt )", + "Syntax": "**.new**( *e* : Object )", "Params": [ [ "e", - "cs.ui.evt", + "Object", "->" ] ], diff --git a/test UI/Project/Sources/Classes/_DEMO_TAB_CONTROL_Controller.4dm b/test UI/Project/Sources/Classes/_DEMO_TAB_CONTROL_Controller.4dm new file mode 100644 index 0000000..948d9e4 --- /dev/null +++ b/test UI/Project/Sources/Classes/_DEMO_TAB_CONTROL_Controller.4dm @@ -0,0 +1,72 @@ +property form : cs:C1710.ui.form +property backButton; cancel; ok : cs:C1710.ui.button + +Class constructor + + This:C1470.isSubform:=True:C214 + + // MARK:-Delegates 📦 + var $form : Object + $form:=Try(JSON Parse:C1218(File:C1566("/SOURCES/Forms/"+Current form name:C1298+"/form.4DForm").getText())) + This:C1470.form:=cs:C1710.ui.form.new(This:C1470; $form) + + This:C1470.form.init() + + // MARK:-[Standard Suite] + // === === === === === === === === === === === === === === === === === === === === === === === === +Function init() + + // MARK: Top tabs with an object + This:C1470.TOP:=This:C1470.form.tabControl.new("tabControl1"; {\ + values: ["Page 1"; "Page 2"]; \ + index: 0}) + + // MARK: Bottom tabs with a list + var $list : Integer:=New list:C375 + APPEND TO LIST:C376($list; "Page 1"; 1) + SET LIST ITEM PROPERTIES:C386($list; 0; True:C214; Plain:K14:1; "path:/RESOURCES/local.svg") + APPEND TO LIST:C376($list; "Page 2"; 2) + SET LIST ITEM PROPERTIES:C386($list; 0; True:C214; Plain:K14:1; "path:/RESOURCES/github.svg") + + This:C1470.BOTTOM:=This:C1470.form.tabControl.new("tabControl"; $list; 2) + // Note that the tab control is initialized to display page 2 at startup. + // ⚠️ This is a list of choices - Don't forget to call This.tabControl.clearList() to clear the memory. + + // === === === === === === === === === === === === === === === === === === === === === === === === +Function handleEvents($e : cs:C1710.ui.evt) + + $e:=$e || cs:C1710.ui.evt.new() + + // MARK:Form Method + If ($e.objectName=Null:C1517) // <== FORM METHOD + + Case of + + //______________________________________________________ + : ($e.pageChange) + + // Synchronize TOP with BOTTOM (for demo) + This:C1470.BOTTOM.pageNumber:=This:C1470.form.page + + //______________________________________________________ + : ($e.unload) + + This:C1470.BOTTOM.clearList() // ⚠️ Its a choiceList + + //______________________________________________________ + End case + + return + + End if + + // MARK: Widget Methods + Case of + + //============================================== + : (This:C1470.BOTTOM.catch($e)) + + This:C1470.BOTTOM.goToPage() + + //============================================== + End case \ No newline at end of file diff --git a/test UI/Project/Sources/Classes/_HDI_Controller.4dm b/test UI/Project/Sources/Classes/_HDI_Controller.4dm index eb8ddc3..cb4d8e9 100644 --- a/test UI/Project/Sources/Classes/_HDI_Controller.4dm +++ b/test UI/Project/Sources/Classes/_HDI_Controller.4dm @@ -59,6 +59,11 @@ Function init() form: "DEMO_SEARCH"; \ comments: Get localized string:C991("desc_5")}) + This:C1470.demos.push({\ + name: Get localized string:C991("title_6"); \ + form: "DEMO_TAB_CONTROL"; \ + comments: Get localized string:C991("desc_6")}) + This:C1470.sidebar:=This:C1470.form.listbox.new("sidebar") // Mark:Detail panel @@ -226,7 +231,7 @@ Function _sidebarManager($e : cs:C1710.ui.evt) This:C1470.editClass.enable(This:C1470.controllers.includes("[class]/_"+$o.form+"_Controller")) // Place the run button - This:C1470.run.moveVertically(This:C1470.desc.coordinates.top+This:C1470.desc.getBestHeight()+20-This:C1470.run.coordinates.top) + This:C1470.run.moveVertically(This:C1470.desc.coordinates.top+This:C1470.desc.getBestHeight()+100-This:C1470.run.coordinates.top) End if diff --git a/test UI/Project/Sources/Forms/DEMO_TAB_CONTROL/form.4DForm b/test UI/Project/Sources/Forms/DEMO_TAB_CONTROL/form.4DForm new file mode 100644 index 0000000..9064b75 --- /dev/null +++ b/test UI/Project/Sources/Forms/DEMO_TAB_CONTROL/form.4DForm @@ -0,0 +1,109 @@ +{ + "$4d": { + "version": "1", + "kind": "form" + }, + "windowSizingX": "fixed", + "windowSizingY": "fixed", + "windowMinWidth": 0, + "windowMinHeight": 0, + "windowMaxWidth": 32767, + "windowMaxHeight": 32767, + "rightMargin": 20, + "bottomMargin": 20, + "events": [ + "onLoad", + "onClick", + "onUnload", + "onPageChange" + ], + "destination": "detailScreen", + "pages": [ + { + "objects": { + "tabControl": { + "type": "tab", + "text": "Tab control", + "top": 127, + "left": 17, + "width": 530, + "height": 118, + "dataSource": "formGetInstance.BOTTOM.dataSource", + "events": [ + "onClick" + ] + }, + "ok": { + "type": "button", + "text": "OK", + "top": 265, + "left": 459, + "width": 88, + "height": 25, + "events": [ + "onClick" + ] + }, + "cancel": { + "type": "button", + "text": "Cancel", + "top": 265, + "left": 351, + "width": 88, + "height": 25, + "events": [ + "onClick" + ], + "defaultButton": false + }, + "tabControl1": { + "type": "tab", + "text": "Tab control", + "top": 15, + "left": 17, + "width": 530, + "height": 92, + "dataSource": "formGetInstance.TOP.dataSource", + "events": [], + "action": "gotoPage" + } + } + }, + { + "objects": { + "Static Picture2": { + "type": "picture", + "top": 155, + "left": 236, + "width": 90, + "height": 90, + "picture": "/RESOURCES/local.svg", + "pictureFormat": "scaled" + } + }, + "entryOrder": [] + }, + { + "objects": { + "Static Picture3": { + "type": "picture", + "top": 155, + "left": 235, + "width": 90, + "height": 90, + "picture": "/RESOURCES/github.svg", + "pictureFormat": "scaled" + } + } + } + ], + "geometryStamp": 662, + "editor": { + "activeView": "View 1", + "defaultView": "View 1", + "views": { + "View 1": {} + } + }, + "method": "formMethod" +} \ No newline at end of file diff --git a/test UI/Project/Sources/dependencies.json b/test UI/Project/Sources/dependencies.json index c3d445d..f97de91 100644 --- a/test UI/Project/Sources/dependencies.json +++ b/test UI/Project/Sources/dependencies.json @@ -1,5 +1,69 @@ { "dependencies": { - "UI": {} + "UI": {}, + "4DPop": { + "github": "vdelachaux/4DPop", + "version": "latest" + }, + "4DPop AppMaker": { + "github": "vdelachaux/4DPop-AppMaker", + "version": "latest" + }, + "4DPop Git": { + "github": "vdelachaux/4DPop-Git", + "version": "latest" + }, + "4DPop Macros": { + "github": "vdelachaux/4DPop-Macros", + "version": "latest" + }, + "4DPop QuickOpen": { + "github": "vdelachaux/4DPop-QuickOpen", + "version": "latest" + }, + "4DPop XLIFF Pro": { + "github": "vdelachaux/4DPop-XLIFF-Pro", + "version": "latest" + }, + "4DPop Bookmarks": { + "github": "vdelachaux/4DPop-Bookmarks", + "version": "latest" + }, + "4DPop ColorChart": { + "github": "vdelachaux/4DPop-ColorChart", + "version": "latest" + }, + "4DPop Commands": { + "github": "vdelachaux/4DPop-Commands", + "version": "latest" + }, + "4DPop Constants Editor": { + "github": "vdelachaux/4DPop-Constants-Editor", + "version": "latest" + }, + "4DPop Image Buddy": { + "github": "vdelachaux/4DPop-Image-Buddy", + "version": "latest" + }, + "4DPop KeepIt": { + "github": "vdelachaux/4DPop-KeepIt", + "version": "latest" + }, + "4DPop Pasteboard": { + "github": "vdelachaux/4DPop-Pasteboard", + "version": "latest" + }, + "4DPop Rulers": { + "github": "vdelachaux/4DPop-Rulers", + "version": "latest" + }, + "4DPop sqlSchemas": { + "github": "vdelachaux/4DPop-sqlSchemas", + "version": "latest" + }, + "4DPop Window": { + "github": "vdelachaux/4DPop-Window", + "version": "latest" + } } } \ No newline at end of file diff --git a/test UI/Project/Sources/folders.json b/test UI/Project/Sources/folders.json index f83bbbb..183e565 100644 --- a/test UI/Project/Sources/folders.json +++ b/test UI/Project/Sources/folders.json @@ -51,13 +51,22 @@ "_DEMO_SEARCH_Controller" ] }, + "DEMO_Tab_Control": { + "forms": [ + "DEMO_TAB_CONTROL" + ], + "classes": [ + "_DEMO_TAB_CONTROL_Controller" + ] + }, "HDIs": { "groups": [ "DEMO_1", "DEMO_constraints", "DEMO_CSS", "DEMO_Menus", - "DEMO_Search" + "DEMO_Search", + "DEMO_Tab_Control" ] }, "MAIN": { diff --git a/test UI/Resources/en.lproj/HDI.xlf b/test UI/Resources/en.lproj/HDI.xlf index cba2528..6b6156a 100644 --- a/test UI/Resources/en.lproj/HDI.xlf +++ b/test UI/Resources/en.lproj/HDI.xlf @@ -115,6 +115,20 @@ You can define : Search box Search box + + Tab controls + Tab controls + + + This dialog shows a very simple implementation of tabs. + - The data source for the top tabs is an object. Operation is fully managed by 4D with an automatic action. + - The data source for the bottom tabs is a hierarchical list that can be used to display icons, which is not possible with an object. In this case, you must call the goToPage() function on click and don't forget to call the .clearList() function when the form is unloaded. + - Note that the contructor of the tabControl class accepts a parameter to display a specific page at startup. + This dialog shows a very simple implementation of tabs. + - The data source for the top tabs is an object. Operation is fully managed by 4D with an automatic action. + - The data source for the bottom tabs is a hierarchical list that can be used to display icons, which is not possible with an object. In this case, you must call the goToPage() function on click and don't forget to call the .clearList() function when the form is unloaded. + - Note that the contructor of the tabControl class accepts a parameter to display a specific page at startup. + @@ -217,4 +231,5 @@ You can define : + diff --git a/test UI/Resources/fr.lproj/HDI.xlf b/test UI/Resources/fr.lproj/HDI.xlf index 2dbd34d..e701d65 100644 --- a/test UI/Resources/fr.lproj/HDI.xlf +++ b/test UI/Resources/fr.lproj/HDI.xlf @@ -114,6 +114,20 @@ Vous pouvez définir : Search box Boîte de recherche + + Tab controls + Onglets + + + This dialog shows a very simple implementation of tabs. + - The data source for the top tabs is an object. Operation is fully managed by 4D with an automatic action. + - The data source for the bottom tabs is a hierarchical list that can be used to display icons, which is not possible with an object. In this case, you must call the goToPage() function on click and don't forget to call the .clearList() function when the form is unloaded. + - Note that the contructor of the tabControl class accepts a parameter to display a specific page at startup. + Cette boîte de dialogue présente une implémentation très simple d'onglets. + - La source de données pour les onglets du haut est un objet. Le fonctionnement est entièrement géré par 4D au moyen d'une action automatique. + - La source de données pour les onglets du bas est une liste hiérarchique utilisée ici pour afficher des icônes, ce qui n'est pas possible avec un objet. Dans ce cas, il faut appeler la fonction goToPage() lors du clic et ne pas oublier d'appeler la fonction .clearList() lors du déchargement du formulaire. + - Notez que le contructeur de la classe tabControl accepte un paramètre pour afficher une page spécifique au démarrage. + @@ -216,4 +230,5 @@ Vous pouvez définir : + diff --git a/test UI/Resources/github.svg b/test UI/Resources/github.svg new file mode 100644 index 0000000..b0e4699 --- /dev/null +++ b/test UI/Resources/github.svg @@ -0,0 +1,3 @@ + + + diff --git a/test UI/Resources/local.svg b/test UI/Resources/local.svg new file mode 100644 index 0000000..7a376b1 --- /dev/null +++ b/test UI/Resources/local.svg @@ -0,0 +1,3 @@ + + +