View on GitHub

UI-with-Classes

Collection of 4D classes dedicated to user interface management, designed to structure the UI and make code more readable, maintainable, and reusable.

form

The form class is intended to be called as a delegate by a form controller class, as in the code example below line 8.

Hierarchy


Example

// Class _myDialog_Controller
Class constructor
	
	This.isSubform:=False
	This.toBeInitialized:=False
	
	// Instantiate the form
	This.form:=cs.form.new(This)
		
	...
	
	This.form.init()
	
Function init()
	// Instantiate the widgets we want to manipulate.
	This.box:=This.form.Input("Input")
	This.ok:=This.form.Button("Button")
	This.cancel:=This.form.Button("Button1")
	
	// Resize the window
	This.form.window.setRect(400; 600)

	// Set window title
	This.form.window.title:="Passkey"
	
	...
	
Function onLoad()
	
	...
	
	This.form.update()
	
Function handleEvents($e:cs.evt)
	
	...
	
Function update()
	


<hr>

📌 Note: to simplify the distinction between form objects and object type, this documentation uses the term “widget” for all form objects, whether static (a line, a rectangle…) or not (a button, a subform…).

cs.form.new()

cs.form.new ( parent : 4D.class) : cs.form
cs.form.new ( parent : 4D.class ; form : Object) : cs.form

Parameter Type   Description
Parent Object form controller class instance
form Object form object definition
result cs.form New cs.form

Description

cs.form.new() creates & returns a new instance of the class.

This.form:=cs.form.new(This; Try(JSON Parse(File("/SOURCES/Forms/"+Current form name+"/form.4DForm").getText())))

Table of Contents

General Properties

📌 Other properties are described below in the section devoted to them.

Properties Description Type default Writable
.name Current form name Text   x
.isSubform Is the form used as a subform * Boolean False
.toBeInitialized Has the form been initialized * Boolean True
.window Current form window class object cs.window   x
.constraints The constraints manager cs.constraints   x
.fluentUI Windows theme compatibility flag (True when Fluent UI is active) Boolean False

* To be set up by the form controller class

Form widget instantiation functions

In the form controller class, you instantiate the widgets (form objects) you wish to manipulate (i.e. activate, deactivate, move, set a value, color, etc.) using the form.<Type>(<name>) instantiation functions listed in the table below. See the code sample above, lines 16 to 18.

🚨 Please note that the names of these functions start with a capital letter. For backward compatibility reasons, the same functions, without capital, letters are still defined, but should no longer be used, as they may be deleted in the future. If you are concerned, please take time to replace the lines like:
               This.form.<type>.new(“name”)
by
               This.form.<Type>(“name”).

Functions  
.Button (name: Text) → cs.button for a Button, a Check Box or a Radio Button
.ComboBox (name: Text {; data : Object}) → cs.comboBox for a Combo Box
.DropDown (name: Text {; data : Object}) → cs.dropDown for a Drop-down List
.HList (name: Text {; ref : Integer}) → cs.hList for a Hierarchical List
.Input (name: Text) → cs.input for an Input
.Listbox (name: Text) → cs.listbox for a List Box
.Picture (name: Text) → cs.picture for a Static Picture
.Static (name: Text) → cs.static for a Shapes or static widgets like Group Box
.Stepper (name: Text) → cs.stepper for a Stepper
.Subform (name: Text) → cs.subform for a Subform
.TabControl (name: Text {; data : Object}) → cs.tabControl for a Tab Control
.Thermometer (name: Text) → cs.thermometer for a Progress Indicator
.WebArea (name: Text) → cs.webArea for a Web Area

In addition, other handler can be instantiated. For example: a Group allows you to manage several widgets at once, since groups created in design mode cannot be manipulated at runtime.

Functions  
.Group ({name: Text}) → cs.group to manage several widgets at once
.Selector (name: Text) → cs.selector a superclass to manage Dropdown, Combo Box and Tab Control widgets
.Scrollable (name: Text) → cs.scrollable a superclass to manage widgets that accept scrollbars
.Widget.new (name: Text) → cs.widget a superclass to manage all active form widgets

📌 The name parameter is the object name as defined in the form editor.

Each instantiated form object inherits all the properties and functions of its class as you can see in each class documentation.

Standard suite functions

📌 The functions listed in the table below represent the standard suite. They must be defined in the form controller class if you need them, otherwise an alert will be raised if you call one without having defined it.

In the code sample above, line 12, the This.form.init() call explicitly describes that we want to initialize the form, but the initialization code is specific to the form and must therefore be in the class that drives it. This is the role of the Function init() function at line 14.

The formMethod method must be declared as the form method of all forms that are managed in this way. This method initializes the class associated with the dialog, which should be called _<dialogName>_Controller, and calls its handleEvents() function when a form event is generated. The handleEvents() function is therefore part of the standard suite and must be defined in the class associated with the dialog (line 34 of the code sample above).

Functions  
.init() to initialize the dialog
.handleEvents() to manage form events or form objects
.onLoad() to perform initializations when loading the form
.update() to update the user interface
.onOutsideCall() to manage a call performed with POST OUTSIDE CALL
.saveContext() to save the state of a form when it is unloaded, so that it can be restored when it is reloaded
.restoreContext() to restore the context when the form is reloaded
.onBoundVariableChange() for subforms

The minimum suite (init(), onLoad(), handleEvents()) is presented in DEMO_1 into the test UI project of the repository. The other demonstrations introduce the use of the suite’s other functions.

Properties Description Type default Writable
.pageNumber Number of pages in the form Integer   x
.page Current page number Integer   x
.pages A hashmap table* for naming form pages Object {Page_1: 1, Page_2: 2, … , Page_N: N}

📌 The navigation functions apply by default to the current form. So if it’s a sub-form, it’s the sub-form’s page that will be modified, unless you pass the optional parent parameter where allowed.

Functions Action
.setPageNames (names: Collection) Defines the hashmap table* from the collection of names passed
.pageFromName (name: Text) : Integer Returns a page number from its name
.goToPage (page: Integer| Text {; parent : Boolean}) Replaces the currently displayed form page with the form page specified by its page number or name.
.firstPage ({parent: Boolean}) Changes the currently displayed form page to the first form page
.lastPage ({parent: Boolean}) Changes the currently displayed form page to the last form page
.nextPage ({parent: Boolean}) Changes the currently displayed form page to the next form page
.previousPage ({parent: Boolean}) Changes the currently displayed form page to the previous form page

* The hashmap table allows navigation commands to access a page by its name instead of its page number.

Timer

Properties Description Type default Writable
.deferedTimer The last registered deffered action ID Integer  
Functions Action
.setTimer ({tickCount: Integer}) Starts a timer and sets its delay, ASAP if tickCount is omitted
.stopTimer () Disables the timer
.refresh () Starts a timer to be executed as quickly as possible
.deferTimer (id : Integer; tickCount : Integer) Registers the ID of an action to be executed in the next timer cycle
& launch timer ASAP or after tickCount parameter
.clearDeferedTimer () Remove all registered deffered actions and stop the timer

Focus

Properties Description Type default Writable
.focused Name of the object that has the focus in the form Text   x
.entryOrder Entry order of the current form for the current process Collection [ ] x
.highlight Text currently selected, if applicable Text   x
Functions Action
.focus ( widget ) Gives the focus to a widget. widget can be a widget name or a widget object
.removeFocus () Removes any focus in the current form
.focusNext () Go to next focusable widget
.focusPrevious () Go to previous focusable widget
.setEntryOrder (names: Collection) Sets the entry order of the current form for the current process

Events

Properties Description Type default Writable
.events Form event codes Collection Initialy populated according to the events activated for the form & the form objects x
Functions Action
.setEvents (events: Integer|Collection) Define the event(s) for the current form
.appendEvents (events: Integer|Collection) Adds form event(s) for the current form
.removeEvents (events: Integer|Collection) Removes form event(s) for the current form
.postKeyDown (keyCode: Integer {; modifier: Integer }) Posts a keyboard event

Associated Worker

Properties Description Type default Writable
.worker Name or ID of the associated worker Text|Integer Null
Functions Action
.callWorker (method: Text)
.callWorker (method: Text;param: Collection)
.callWorker (method: Text;param;…; paramN)
Assigns a task to the associated worker

Calls

Properties Description Type default Writable
.callback Current callback method’s name Text “formCallBack”
Functions Action
.callMeBack ()
.callMeBack (param: Collection)
.callMeBack (param; paramN)
Call the form using the current callback method
.callMe (method: Text)
.callMe (method: Text; param: Collection)
.callMe (method: Text; param; ; i)
Call the form with the passed method
.callChild (subform: Object|Textmethod: Text)
.callChild (subform: Object|Textmethod: Text; param: Collection)
.callChild (subform: Object|Textmethod: Text; param; paramN)
Executes a project method in the context of a subform
(without returned value)
.spreadToChilds (message : Object{; subforms : Collection}) Execute the message.method into all the subforms of the current forms
.callParent (eventCode: Integer) Sends an event to the subform container

Dimensions & resizing

Properties Description Type default Writable
.rect Form dimensions as an object {width,height Object   x
.horizontallyResizable Can the form be resized horizontally Boolean  
.minWidth The smallest form width allowed (pixels) Integer  
.maxWidth The largest form width allowed (pixels) Integer  
.verticallyResizable Can the form be resized vertically Boolean  
.minHeight The smallest form height allowed (pixels) Integer  
.maxHeight The largest form height allowed (pixels) Integer  
Functions Action
.setHorizontalResising (resizable: Boolean {; min: Integer {; max: Integer}}) Change the form horizontal resizing properties
.setVerticalResising (resizable: Boolean {; min: Integer {; max: Integer}}) Change the form vertical resizing properties

Color scheme

Properties Description Type default Writable
.colorScheme Name of the last updated color scheme Text   x
.darkScheme Is the current color scheme “dark” Boolean   x
.lightScheme Is the current color scheme “light” Boolean   x
.resourceScheme Returns the current scheme suffix Boolean   x
.darkSuffix Suffix used to select the appropriate resource according to the color scheme Text “_dark”
Functions Action
.resourceFromScheme (path: Text) → Text Returns the access path to the given resource path with the dark suffix, if applicable

Subforms

Properties* Description Type default Writable
.container The container class object Object   x
.containerName The name of the container Text   x
.containerValue Value of the container Variant  
.containerInstance The container instance Object   x

* Reading these properties when isSubform = False, generates an error.

Functions* Action
.setContainerValue (value: Variant) Sets the container value
.getContainerValue () → Variant Returns the container value
.callParent (eventCode: Integer) Sends an event to the subform container

* Calling these functions when isSubform = False, generates an error.

Drag & Drop

Functions Action
.beginDrag (uri: Text; data: Variant {; icon: Picture}) Appends data to the pasteboard under the data type specified in uri.
Also sets the drag icon if passed
.getPasteboard (uri: Text) → Variant Returns the data from the pasteboard whose type you pass in uri

Cursor

Functions Action
.setCursor (cursor: Integer|Text) Sets the mouse cursor to the cursor type specified in cursor by its number or name.
.releaseCursor () Restores the standard mouse cursor

Miscellaneous

Functions Action
.getScreenshot ({page:Integer}) : Picture Returns the form as a picture. See FORM SCREENSHOT

Form definition access

Properties Description Type Writable
.formObjects All form objects names Collection x
.staticTexts All static text names Collection x
.staticPictures All static pictures names Collection x
.statics All static form object names (Texts & Pictures) Collection x
.subforms All subform form object names Collection x
.instantiatedWidgets All instantiated widgets objects Collection x
.instantiatedSubforms All instantiated subforms objects Collection x

Class diagram

classDiagram
class form["cs.form"] {
			+cs.static static
			+cs.widget widget
			+cs.button button
			+cs.picture picture
			+cs.dropDown dropDown
			+cs.stepper stepper
			+cs.thermometer thermometer
			+cs.selector selector
			+cs.comboBox comboBox
			+cs.listbox listbox
			+cs.hList hList
			+cs.subform subform
			+cs.webArea webArea
			+cs.window window
			+cs.constraints constraints
			+init()
			+handleEvents(e : cs.evt)
			+onLoad()
			+update()
			+onBoundVariableChange()
			+saveContext()
			+restoreContext()
			+onOutsideCall()
			+focused : Text
			+highlight : Text
			+darkScheme : Boolean
			+lightScheme : Boolean
			+resourceScheme : Text
			+darkSuffix : Text
			+worker : Variant
			+containerName : Text
			+container : Object
			+containerInstance : Object
			+containerValue : Variant
			+events : Collection
			+callback : Text
			+page : Integer
			+formObjects : Collection
			+staticTexts : Collection
			+staticPictures : Collection
			+statics : Collection
			+subforms : Collection
			+instantiatedWidgets : Collection
			+instantiatedSubforms : Collection
			+rect : rect
			+horizontallyResizable : Boolean
			+minWidth : Integer
			+maxWidth : Integer
			+verticallyResizable : Boolean
			+minHeight : Integer
			+maxHeight : Integer
			+removeFocus()
			+focusNext()
			+focusPrevious()
			+setEntryOrder()
			+resourceFromScheme()
			+refresh(tick : Integer)
			+setTimer(tick : Integer)
			+stopTimer()
			+callWorker(method : Text; param 1-N)
			+getContainerValue()
			+setEvents(events)
			+appendEvents(events)
			+removeEvents(events)
			+postKeyDown(key : Integer; modifier : Integer)
			+callMeBack(param 1-N)
			+callMe(method : Text; param 1-N)
			+callChild(subform : Text; method : Text; param 1-N)
			+callParent(event : Integer)
			+setPageNames(names : Collection)
			+goToPage(page : Variant; parent : Boolean)
			+firstPage(parent : Boolean)
			+lastPage(parent : Boolean)
			+nextPage(parent : Boolean)
			+previousPage(parent : Boolean)
			+setCursor(cursor : Variant)
			+releaseCursor(cursor : Variant)
			+beginDrag(uri : Text; data : Variant; icon : Picture)
			+getPasteboard(uri : Text) Variant
			+getSubformInstance(name : Text) Object
			+setHorizontalResising(resize : Boolean; min : Integer; max : Integer)
			+setVerticalResising(resize : Boolean; min : Integer; max : Integer)
		}