Morfik 07 - Creating a Custom Control
From Morfikwiki.com
This chapter is a general description of how to create a basic, browser side, custom control in Morfik and how to use it in the Morfik IDE.
The way controls are created within the Morfik Framework is not yet completely defined. Currently, there is a clear separation between what is a built-in control and a custom control. Though changes may come into effect in the future, the code you write by following the practices described here should not require major adjustments to remain compatible.
Contents |
[edit] What is a Custom Control?
In Morfik, a custom control is a user-built control which can be added to the Morfik WebOS AppsBuilder IDE. Custom controls are composed of three files: a code module (.mmd) a property definition file (.cta) and an icon (.bmp) which will be used to represent the control in the IDE’s toolbox.
[edit] Getting Started
The first step of creating a Morfik custom control is to create a code module. You should working on a .mxp project which does not embed all project modules in a single file, since you will need to move the files for the control to a specific location, when you are ready to test it.
Once you have created a code module, you can start to go about the business of creating the control itself. All custom control classes must be descendants of TAdaptedControl.
This sample is a control called FormList. It presents the user with a vertical list of buttons which when clicked open a specific form within a specific SubForm control. Though the control can easily be extended, it should suffice for the purpose of understanding how to start writing controls.
In listing 1, you can see the full browser side source code for the FormList control.
Listing 1 – Browser side code for the FormList control.
(**
* Unit containing sample custom controls.
* The purpose of these controls is to demonstrate the steps required
* for creating a browser-only control.
*
* Copyright 2006, 2007 by Morfik Technology
*)
Unit MyCustomControls;
Interface
Uses
SystemClasses,
SystemUtilities,
SystemControls,
SystemControlsSTD,
SystemDOM,
SystemDOMHtml;
Type
(**
* Button control descendant. Adds a simple string member variable to hold
* the name of the form which is to be opened as a result of the click on
* a button.
*)
MyButton = class(button)
TheForm: string;
end;
(**
* The FormList class is a simple sample control. The purpose of this sample
* is to demonstrate the steps required for creating a browser-only control.
*)
FormList = Class(AdaptedControl)
Protected
Buttons: List of MyButton;
FormNames: TParameters;
(**
* Holds the full description of the SubForm where to open the forms.
* ex: Index:SubForm1
*)
TheSubForm: string;
(**
* Creates the necessary buttons, as per the values specified in the
* configuration['forms'] property.
*)
Procedure CreateButtons;
Public
(**
* Initializes the class member variables: Buttons and FormNames.
*)
Constructor CreateID(aID: String; aOwner : TAbstractControl); override;
(**
* Frees all the Button and the List objects contained in member
* variables.
*)
Destructor Destroy; override;
(**
* Initializes the DOM objects corresponding to each of the Morfik
* Button objects.
*)
Function SetupDOMHandle(H : THTML_ElementExt); Override;
(**
* Default event handler for all the buttons. Opens the corresponding
* form in the Configuration['SubForm'] property.
*)
Procedure ButtonClick(Event: TDOMEvent);
End;
Implementation
Constructor FormList.CreateID(aID: String; aOwner : TAbstractControl);
Begin
Inherited CreateID(aID, aOwner);
Buttons.Init;
FormNames := TParameters.Create;
End;
(**
* Applies the standard Morfik Formatting to a button. Buttons are
* initially created with the platform-specific look, by the browser.
*)
Procedure SetMorfikFormatting(B: Button);
begin
With B.Attrs do
begin
BorderStyle := bsSingle;
BorderColor := $c0c0c0;
Color := $f6f4f4;
with Font do
begin
Name := 'Verdana';
Height := 9;
Style := [];
Color := $0000cc;
end;
end;
end;
Procedure FormList.CreateButtons;
var
Btn: MyButton;
Index: integer;
VC: integer;
Begin
TheSubForm := Configuration['Sub_Form'];
FormNames.AddList(Configuration['Forms']);
VC := 10;
for Index := 0 to FormNames.Items.Count -1 do
begin
Btn := MyButton.CreateID(FormNames.Items[Index].Name, Self);
With Btn do
begin
TheForm := FormNames.Items[Index].Value;
OnClick := GetMethodPointer(Self, @ButtonClick);
Attrs.Left := 10;
Attrs.Top := VC;
Attrs.Text := FormNames.Items[Index].Name;
end;
SetMorfikFormatting(Btn);
Buttons.Add(Btn);
VC := VC + 35;
end;
End;
Procedure FormList.ButtonClick(Event: TDOMEvent);
begin
OwnerForm.OpenForm(MyButton(GetEventSource(Event)).TheForm, TheSubForm, '');
end;
Function FormList.SetupDOMHandle(H : THTML_ElementExt);
var
Index: integer;
Begin
Inherited SetupDOMHandle(H);
CreateButtons;
If Buttons.Count > 0 then
For Index := 0 to Buttons.Count-1 do
begin
Button(Buttons.Items[Index]).CreateDOMObject;
Button(Buttons.Items[Index]).Caption := TParameter(FormNames.Items[Index]).Name;
end;
End;
Destructor FormList.Destroy;
begin
FormNames.Free;
FreeObjectList(Buttons);
Inherited Destroy;
end;
End.
In figures 1 and 2 you can see the FormList control at run time and design time, respectively. In Figure 1, the "My Page 2" button has been clicked and has displayed the corresponding form, within the SubForm Control.
In order to achieve the effect shown in this figures it is necessary to create a project with four forms, in addition to the Index form. Each of these forms will be associated with one of the buttons.
The buttons and their relationship to the forms is defined through the Configuration[’Forms’] property. To reproduce this example a line such as follows must be entered in the properties window.
"My Page 1=form1", "My Page 2=form2", "My Page 3=form3", "My Page 4=form4"
In this sample, within the CreateButtons method of the FormList class, you can see how basic attributes, such as positioning, are set for the button. You can also see how to programmatically assign a method as an event handler. This is done through a call to GetMethodPointer. Lets explore this code a bit more through the comments which have been introduced in Listing 2.
Listing 2 – CreateButtons method of the FormList class.
Procedure FormList.CreateButtons;
var
Btn: MyButton;
Index: integer;
VC: integer;
Begin
TheSubForm := Configuration['Sub_Form'];
FormNames.AddList(Configuration['Forms']);
VC := 10;
for Index := 0 to FormNames.Items.Count -1 do
begin
{ Instanciate the MyButton objects.}
Btn := MyButton.CreateID(FormNames.Items[Index].Name, Self);
With Btn do
begin
{ Get the name of the Form which should be associated with this button.}
TheForm := FormNames.Items[Index].Value;
{ Assign a common event handler to all buttons.}
OnClick := GetMethodPointer(Self, @ButtonClick);
{ Set positioning attributes.}
Attrs.Left := 10;
Attrs.Top := VC;
{ Sets the “text” of the button which will identify it in the HTML code.}
Attrs.Text := FormNames.Items[Index].Name;
end;
{ Applies a series of interface formatting changes to make the button more
“Webish”. Buttons are created by the browser with the original host OS look.}
SetMorfikFormatting(Btn);
{ Adds the button to the buttons list.}
Buttons.Add(Btn);
{ Increments the vertical coordinates in order to prepare for the next button.}
VC := VC + 35;
end;
End;
You may have noticed that the method in Listing 2 calls a procedure called SetMorfikFormatting. This procedure applies several formatting changes to the respective button, giving a it a more "webish" look, since the browser, by default creates buttons with the look and feel of the underlying host platform. You can see the code for this procedure with detailed comments in Listing 3.
Listing 3 – SetMorfikFormatting procedure.
Procedure SetMorfikFormatting(B: Button);
begin
With B.Attrs do // with button.Attrs attributes do
begin
BorderStyle := bsSingle; //Set the border type
BorderColor := $c0c0c0; //Set the border color
Color := $f6f4f4; //Setting the button’s background color.
with Font do // with button.Attrs.font do
begin
Name := 'Verdana'; //Set typeface
Height := 9; //Set size
Style := []; //Clear any possible stile, (ex.: bold, italic, etc
Color := $0000cc; //Set font color to a nice red tone.
end;
end;
end;
[edit] Creating and Using Control Properties
All Adapted controls have a Configuration property, which holds the properties which have been defined by the control’s creator. You can access the values of these properties as shown below:
S := Configuration['Forms'];
This code snippet retrieves the value of the user defined Forms property of the FormList control.
[edit] Defining Properties
The properties you will add to your control are added through a property definition file (.cta). This file is an INI format file, which is quite easy to create with any text editor. In listing 4, you can see the contents of the MyCustomControl.cta file.
The Adapter section identifies this control set. A single module can contain several controls. The Controls section, lists the controls which are contained in this control set.
Listing 4 – Property definition file for the FormList control.
[Adapter]
ID=129A38A4-1076-454E-B7A9-AFBDECEF9CEA
Publisher=Morfik Technology Pty Ltd
Version=1.0.0.0
Description=Morfik Sample Custom Controls
Resources=_Resources
[Controls]
C1=FormList
[FormList]
ClassName=FormList
DisplayName= Form List Control
ModuleName=MyCustomControls
BitmapName=FormList.bmp
Grouped=0
[FormList.Properties]
Property1=Forms
Property2=Sub_Form
[FormList.Forms]
Type=String
[FormList.Sub_Form]
Type=String
After the Controls section you will have a section named after each control in the control set. In this example we have the FormList section. Following that, you will have a section which actually defines the properties of a single control. That section must always be named in a manner that follows the "ControlName.Properties" pattern.
After the property list, a section for each of the properties will need to be included. These sections are named following the "ControlName.PropertyName" pattern.
It is very important to note that the user defined properties, within the configuration property is not yet available within the control’s constructor. You can, however, safely use this property within the SetupDOMHandle method. In this example, this property is used extensively within the CreateButtons procedure.
In the MyCustomControls.cta file, we can see that there is only one control listed: FormList and it has two properties listed: Forms and SubForm.
Figure 3 – Configuration with custom properties for the FormList control in the properties window of the AppsBuilder IDE
[edit] Adding the Control to the Morfik IDE
In order to have a custom control appear in the AppsBuilder toolbox, it is necessary to take just a few simple few steps.
First you need to locate the folder on your computer where the AppsBuilder is installed and under that, find the /System/Adapters folder. Inside the Adapters folder you need to create a new folder with the name of your control set.
Once the folder has been created all that remains to be done is to copy your module (.mmd file), property definition (.cta file) and bitmap files into it. Once that is done, the Morfik IDE will pickup the new control set and display its controls in the toolbox the next time it is restarted.
In Figure 4 you can see the small icon that was created to represent the FormList control within the Morfik AppsBuilder IDE.
In Figure 5, you can see the Morfik toolbox with the FormList control appearing on it. On the form itself, when you place the FormList control, you get a hashed rectangle which will occupy the area allocated for the control, as can be seen in Figure 2.
[edit] Wrapping it up
As you can see by this example, creating controls for Morfik WebOS AppsBuilder, while not totally trivial, is a task which should be within reach of most people who want to try.




