Morfik 07 - Creating a Custom Control

From Morfikwiki.com

Jump to: navigation, search

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.

Figure 1 – The FormList control at run time.

Figure 2 – The FormList control at design time

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.

Figure 4 – the FormList control icon for the AppsBuilder control toolbox.

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.

Figure 5 – The AppsBuilder toolbar with the FormList control highlighted.

[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.

Personal tools