Selection by a ListBox and RadioButtons

This demonstration is based on our Oxygene example showing selection in an Android application. In Version 3.0 of Smart Mobile Studio a RadioGroup component is available and different code is needed for the listbox. See below the new code. In Version 2.1 of Smart Mobile Studio it was not possible to drop a RadioButton onto the form, so we created our own from the closely related CheckBox. The conversion required:
  1. changing identifiers;
  2. Changing the line in StyleTagObject to w3_setProperty(Handle, 'type', 'radio');
  3. Changing HandleLabelClick so that a click can select a button but not deselect it.

The ListBox can contain different types of visual component and a Label was a convenient choice for us.

The Smart Pascal code of the main unit and the RadioButton unit and the XML code of the form follow the working demonstration. If the program does not work in your current browser, try another such as Chrome. If you see no display at school, the security system might have blocked it. You can try instead this direct link to the program running on its own page.

SelectionDemo.html

Code of the Main Unit

unit Form1;

interface

uses 
  SmartCL.System, SmartCL.Graphics, SmartCL.Components, SmartCL.Forms, 
  SmartCL.Fonts, SmartCL.Borders, SmartCL.Application, SmartCL.Controls.Label,
  SmartCL.Controls.Listbox, System.Colors, System.Types, RadioButton;

type
  TForm1 = class(TW3Form)
  private
    {$I 'Form1:intf'}
    const Colours: array[0..4] of TColor = [clRed, clOrange, clYellow, clGreen, clBlue];
    const strColours: array[0..4] of string = ['Red', 'Orange', 'Yellow', 'Green', 'Blue'];
    rbSmall, rbMedium, rbLarge: TW3RadioButton;
  protected
    procedure InitializeForm; override;
    procedure InitializeObject; override;
  end;

implementation

procedure TForm1.InitializeForm;
begin
  inherited;
  rbSmall := new TW3RadioButton(self);
  rbSmall.SetBounds(10, 230, 120, 50);
  rbSmall.Checked := False;
  rbSmall.Caption := 'Small text';
  rbSmall.OnClick := procedure(sender: TObject)
    begin
      W3Label1.Font.Size := 10;
      rbMedium.Checked := False;
      rbLarge.Checked := False;
    end;

  rbMedium := new TW3RadioButton(self);
  rbMedium.SetBounds(10, 260, 120, 50);
  rbMedium.Checked := False;
  rbMedium.Caption := 'Medium text';
  rbMedium.OnClick := procedure(sender: TObject)
    begin
      W3Label1.Font.Size := 14;
      rbSmall.Checked := False;
      rbLarge.Checked := False;
    end;

  rbLarge := new TW3RadioButton(self);
  rbLarge.SetBounds(10, 290, 120, 50);
  rbLarge.Checked := True;
  rbLarge.Caption := 'Large text';
  rbLarge.OnClick := procedure(sender: TObject)
    begin
      W3Label1.Font.Size := 18;
      rbSmall.Checked := False;
      rbMedium.Checked := False;
    end;
end;

procedure TForm1.InitializeObject;
begin
  inherited;
  {$I 'Form1:impl'}
  W3Label1.Caption := 'Please select text colour and size.';
  W3Label1.Font.Color := clRed;
  W3Label1.Font.Size := 18;
  W3ListBox1.ItemClass := TW3Label;
  for var i := 1 to 5 do
    W3ListBox1.Add;
  W3ListBox1.Styles.SelectedColor := clLightBlue;
  W3ListBox1.SelectedIndex := 0;
  W3ListBox1.EnableAnimation := false;
  W3ListBox1.OnSelected := procedure (sender: TObject; idx: integer)
    begin
      W3Label1.Font.Color := Colours[idx];
    end;
  for var i := 0 to 4 do
    TW3Label(W3ListBox1.Items[i]).Caption:= strColours[i];
end;
 
initialization
  Forms.RegisterForm({$I %FILE%}, TForm1);
end.

Code of RadioButton Unit

{ **************************************************************************** }
{ Adapted from CheckBox in                                                     }
{                                                                              }
{ Smart Mobile Studio - Runtime Library                                        }
{                                                                              }
{ Copyright © 2012-2014 Optimale Systemer AS.                                  }
{                                                                              }
{ **************************************************************************** }

unit RadioButton;

interface

uses
  System.Types, SmartCL.System, SmartCL.Components, SmartCL.Controls.Label;

type
  TW3RadioCheckMark = class(TW3CustomControl)
  protected
    procedure setWidth(aValue: Integer); override;
    procedure setHeight(aValue: Integer); override;
    function makeElementTagObj: THandle; override;
    procedure StyleTagObject; override;
    function getChecked: Boolean; virtual;
    procedure setChecked(const aValue: Boolean); virtual;
  published
    property Checked: Boolean read getChecked write setChecked;
  end;

  TW3RadioButton = class(TW3CustomControl)
  private
    FLabel: TW3Label;
    FMark: TW3RadioCheckMark;
    procedure HandleLabelClick(Sender: TObject);
  protected
    function getCaption: String;
    procedure setCaption(aValue: String);
    function getChecked: Boolean;
    procedure setChecked(aValue: Boolean);
    function getEnabled: Boolean; override;
    procedure setEnabled(aValue: Boolean); override;
    procedure InitializeObject; override;
    procedure FinalizeObject; override;
    procedure Resize; override;
  public
    property Label: TW3Label read FLabel;
    property CheckMark: TW3RadioCheckMark read FMark;
  published
    property Caption: String read getCaption write setCaption;
    property Checked: Boolean read getChecked write setChecked;
  end;

implementation

{ **************************************************************************** }
{ TW3RadioCheckMark                                                            }
{ **************************************************************************** }

procedure TW3RadioCheckMark.setWidth(aValue: Integer);
begin
//
end;

procedure TW3RadioCheckMark.setHeight(aValue: Integer);
begin
//
end;

function TW3RadioCheckMark.getChecked: Boolean;
begin
  Result := w3_getPropertyAsBool(Handle, 'checked');
end;

procedure TW3RadioCheckMark.setChecked(const aValue: Boolean);
begin
  w3_setProperty(Handle, 'checked', aValue);
end;

function TW3RadioCheckMark.makeElementTagObj: THandle;
begin
  Result := w3_createHtmlElement('input');
end;

procedure TW3RadioCheckMark.StyleTagObject;
begin
  inherited;
  w3_setProperty(Handle, 'type', 'radio');
end;

{ **************************************************************************** }
{ TW3RadioButton                                                               }
{ **************************************************************************** }

procedure TW3RadioButton.InitializeObject;
begin
  inherited;
  FLabel := TW3Label.Create(Self);
  FMark := TW3RadioCheckMark.Create(Self);
  FLabel.Caption := 'Radio Button';
  FLabel.Container.OnClick := HandleLabelClick;
end;

procedure TW3RadioButton.FinalizeObject;
begin
  FMark.Free;
  FLabel.Free;
  inherited;
end;

function TW3RadioButton.getEnabled: Boolean;
begin
  Result := FMark.Enabled;
end;

procedure TW3RadioButton.HandleLabelClick(Sender: TObject);
begin
  if FLabel.Enabled then
    if not Checked then
      setChecked(true);
end;

function TW3RadioButton.getChecked: Boolean;
begin
  Result := FMark.Checked;
end;

procedure TW3RadioButton.setChecked(aValue: Boolean);
begin
  FMark.Checked := aValue;
end;

procedure TW3RadioButton.setEnabled(aValue: Boolean);
begin
  FMark.Enabled := aValue;
  FLabel.Enabled := aValue;
end;

function TW3RadioButton.getCaption: String;
begin
  Result := FLabel.Caption;
end;

procedure TW3RadioButton.setCaption(aValue: String);
begin
  FLabel.Caption := aValue;
end;

procedure TW3RadioButton.Resize;
var
  dx, dy: Integer;
begin
  inherited;

  dy := (ClientHeight div 2) - (FMark.Height div 2);
  FMark.MoveTo(0,dy);

  dx := FMark.Left + FMark.Width + 1;

  FLabel.SetBounds(dx, 0, ClientWidth - dx, ClientHeight);
end;

end.

XML Code of Form

<SMART>
  <Form version="2" subversion="1">
    <Created>2014-10-23T20:06:13.174</Created>
    <Modified>2014-10-24T11:12:26.382</Modified>
    <object type="TW3Form">
      <Caption>W3Form</Caption>
      <Name>Form1</Name>
      <object type="TW3Label">
        <Caption>W3Label</Caption>
        <Width>296</Width>
        <Left>8</Left>
        <Height>48</Height>
        <Name>W3Label1</Name>
      </object>
      <object type="TW3ListBox">
        <Width>296</Width>
        <Top>48</Top>
        <Left>8</Left>
        <Height>176</Height>
        <Name>W3ListBox1</Name>
      </object>
    </object>
  </Form>
</SMART>

Selection Using Version 3 of Smart Mobile Studio

See below a single project file that compiled to output an HTML file with the functionality of the demo near the top of this page.

<SMART>
  <Project version="3" subversion="0">
    <Name>SelectionDemo</Name>
     <VendorSpecific>
      <Apple>
        <FormatDetection>1</FormatDetection>
        <StatusBarStyle>default</StatusBarStyle>
        <WebAppCapable>1</WebAppCapable>
      </Apple>
      <ChromeApp>
        <Kiosk>0</Kiosk>
        <KioskOnly>1</KioskOnly>
        <OfflineEnabled>1</OfflineEnabled>
      </ChromeApp>      
    </VendorSpecific>
    <Options>
      <Compiler>
        <Assertions>1</Assertions>
        <Optimize>1</Optimize>
        <HintsLevel>1</HintsLevel>
      </Compiler>
      <Codegen>
        <Obfuscation>0</Obfuscation>
        <RangeChecking>0</RangeChecking>
        <InstanceChecking>0</InstanceChecking>
        <ConditionChecking>0</ConditionChecking>
        <LoopChecking>0</LoopChecking>
        <InlineMagics>1</InlineMagics>
        <IgnorePublishedInImplementation>0</IgnorePublishedInImplementation>
        <EmitSourceLocation>0</EmitSourceLocation>
        <EmitRTTI>0</EmitRTTI>
        <Devirtualize>1</Devirtualize>
        <MainBody>1</MainBody>
        <CodePacking>0</CodePacking>
        <SmartLinking>1</SmartLinking>
        <Verbosity>1</Verbosity>
      </Codegen>
      <ConditionalDefines>
        <HandleExceptions>1</HandleExceptions>
        <AutoRefresh>0</AutoRefresh>
        <LegacySupportForIE>0</LegacySupportForIE>
      </ConditionalDefines>
      <Linker>
        <SourceMap>0</SourceMap>
        <CompressCSS>0</CompressCSS>
        <GenerateAppCacheManifest>1</GenerateAppCacheManifest>
        <GenerateChromeAppManifest>0</GenerateChromeAppManifest>
        <GenerateFireFoxManifest>0</GenerateFireFoxManifest>
        <GenerateWebAppManifest>1</GenerateWebAppManifest>
        <GenerateWidgetPackageConfigXML>0</GenerateWidgetPackageConfigXML>
        <GenerateCordovaConfigXML>0</GenerateCordovaConfigXML>
        <ExternalCSS>1</ExternalCSS>
        <Theme>default.css</Theme>
        <CustomTheme>0</CustomTheme>
        <EmbedJavaScript>1</EmbedJavaScript>
      </Linker>
      <Output>
        <JavaScriptFileName>main.js</JavaScriptFileName>
        <HtmlFileName>SelectionDemo.html</HtmlFileName>
        <OutputFilePath>www\</OutputFilePath>
      </Output>
      <Import />
      <Execute>
        <ServeManifest>0</ServeManifest>
        <Server>1</Server>
        <LoadCustomFile>0</LoadCustomFile>
        <PauseAfterExecution>0</PauseAfterExecution>
        <ExecuteType>0</ExecuteType>
      </Execute>
      <WebFonts>
        <usewebfonts>1</usewebfonts>
        <webfontitem>
          <fontname>Ubuntu</fontname>
          <fonturl>https://fonts.googleapis.com/css?family=Ubuntu</fonturl>
        </webfontitem>
      </WebFonts>
    </Options>
    <Files>
      <File type="main">
        <Name>SelectionDemo</Name>
        <Source>
          <![CDATA[uses SmartCL.System, Unit1, Form1;

{$IFDEF SMART_INTERNAL_HANDLE_EXCEPTIONS}
try
{$ENDIF}
  var Application := TApplication.Create;
  Application.RunApp;
{$IFDEF SMART_INTERNAL_HANDLE_EXCEPTIONS}
except
  on e: Exception do
    ShowMessage(e.Message);
end;
{$ENDIF}]]>
        </Source>
      </File>
      <File type="unit">
        <Name>Unit1</Name>
        <Source>
          <![CDATA[unit Unit1;

interface

uses
  Pseudo.CreateForms, // auto-generated unit that creates forms during startup
  System.Types, SmartCL.System, SmartCL.Components, SmartCL.Forms, 
  SmartCL.Application;

type
  TApplication  = class(TW3CustomApplication)
  end;

implementation

end.]]>
        </Source>
      </File>
      <File type="form">
        <Name>Form1</Name>
        <Source>
          <![CDATA[
unit Form1;

interface

uses 
  System.Types, System.Types.Convert, System.Objects, System.Time,
  System.IOUtils, System.Device.Storage,
  SmartCL.System, SmartCL.Time, SmartCL.Graphics, SmartCL.Components,
  SmartCL.FileUtils, SmartCL.Device.Storage, SmartCL.Forms, SmartCL.Fonts,
  SmartCL.Theme, SmartCL.Borders, SmartCL.Application, SmartCL.Controls.ListBox,
  SmartCL.Controls.Label, System.Colors, SmartCL.Controls.RadioGroup, SmartCL.Controls.RadioButton;

type
  TForm1 = class(TW3Form)
  private
    {$I 'Form1:intf'}
    const Colours: array[0..4] of TColor = [clRed, clOrange, clYellow, clGreen, clBlue];
    const strColours: array[0..4] of string = ['Red', 'Orange', 'Yellow', 'Green', 'Blue'];
  protected
    procedure InitializeObject; override;
  end;
  
implementation

procedure TForm1.InitializeObject;
begin
  inherited;
  {$I 'Form1:impl'}
  W3Label1.Caption := 'Please select text colour and size.';
  W3Label1.Font.Color := clRed;
  W3Label1.Font.Size := 18;
  for var i := 0 to 4 do
    W3ListBox1.AddItem(strColours[i]);
  W3ListBox1.SelectedIndex := 0;
  W3ListBox1.OnSelected := procedure (sender: TObject; idx: integer)
    begin
      W3Label1.Font.Color := Colours[idx];
    end;
  W3RadioGroup1.Add('Small');
  W3RadioGroup1.Add('Medium');
  W3RadioGroup1.Add('Large');
  W3RadioGroup1.ItemIndex := 2;
  W3RadioGroup1.OnClick := procedure (sender: TObject)
    begin
      W3Label1.Font.Size := 10 + W3RadioGroup1.ItemIndex * 4;
    end;
end;

initialization
  Forms.RegisterForm({$I %FILE%}, TForm1);
end.    
]]>
        </Source>
        <Design>
          <![CDATA[<?xml version="1.0" encoding="utf-16"?>
<Form version="3" subversion="0">
  <object type="TW3Form">
    <Caption>W3Form</Caption>
    <Name>Form1</Name>
      <object type="TW3ListBox">
        <Width>296</Width>
        <Top>48</Top>
        <Left>8</Left>
        <Height>176</Height>
        <Name>W3ListBox1</Name>
      </object>
        <object type="TW3Label">
        <Caption>W3Label</Caption>
        <Width>296</Width>
        <Left>8</Left>
        <Height>48</Height>
        <Name>W3Label1</Name>
      </object>
        <object type="TW3RadioGroup">
        <Width>110</Width>
        <Left>10</Left>
        <Height>60</Height>
        <Top>230</Top>        
        <Name>W3RadioGroup1</Name>
      </object>      
  </object>
</Form>]]>
        </Design>
        <AutoCreate>
          <IsAutoCreate>1</IsAutoCreate>
          <IsMainForm>1</IsMainForm>
          <Order>1</Order>
        </AutoCreate>
      </File>
    </Files>
    <Target>Browser</Target>
    <Generator>Visual Components Project</Generator>
  </Project>
</SMART>
Programming - a skill for life!

How to use a range of visual components such as edit boxes, combo boxes, grids and charts on one or multiple forms (including a modal form)