December 23, 2013

Smart Mobile Studio 2.0 beta 2

Today we have released new beta version of Smart Mobile Studio 2.0. Most of the annoying bugs are now fixed and we also added few new features and a new grid component!

Fixes

  • No AV for event “building” (on component/event double click) anymore
  • Copy, Cut & Paste were not working (properly) in Visual Designer
  • RTL indexing
  • Better [CTRL]+[DOWN] (go to implementation), sometimes navigated to a slightly wrong position
  • Removed some memory leaks
  • Fixed Unicode issue in visual designer
  • Some preferences were not saved properly
  • Command line compiler now works with missing templates

Changes

  • Command line compiler is purely command line now (smaller size)
  • Faster loading of visual designer (delayed loading of ‘Live Preview’)
  • Improved ‘File’ menu structure
  • Menu item ‘Preferences’ moved to ‘Tools’
  • Improved ‘Options’ dialog (compiler tab)

New Features

  • Added package for Grid
  • Added ‘Save As…’
  • [ALT] + [DOWN] will cycle through components in visual designer
  • Added some WordStar editor commands, but yet partly occluded by IDE shortcuts

October 20, 2013

New ways to run a project

In case you’re not following blogs on the Smart Mobile Studio site, I’d like to point out that I’ve written a blog about improvements in the upcoming 2.0 version, specifically about the enhanced support for executing your applications.

Read it here!

September 05, 2013

Smart 1.1.2

In case you have missed the official announcement – Smart 1.1.2 was released few days ago.

A Smart Book was also updated. There are only few small changes relating to new compiler features and to fixed bugs in TW3Label and TW3Checkbox.

July 19, 2013

Creating Splash Screen

This article will show how to create a splash screen which is displayed over the main form. It was designed for Smart 1.1.2 and may not work with older versions.

Start by creating a new visual project. Add another form which will contain the splash screen. Rename it to something sensible (say, SplashForm).

In reality you cannot rename it in the Smart IDE as rename function is broken in the 1.1.2 beta. As a temporary workaround you can open the .opp file in the Notepad (make a backup copy first!) and rename all occurrences of ‘Form2’  to ‘SplashForm’.

Edit the main unit to create the new form.

uses 
w3system, w3components, w3forms, w3application, form1,
SplashForm;

type
TApplication = class
(TW3CustomApplication)
private
FForm1:
TForm1;
FSplashForm:
TSplashForm;
public
procedure ApplicationStarting; override
;
end
;

implementation

{ TApplication}

procedure
TApplication.ApplicationStarting;
begin
FForm1 :=
TForm1.Create(Display.View);
FForm1.Name := 'Form1'
;
RegisterFormInstance(FForm1,
True);

FSplashForm :=
TSplashForm.Create(Display.View);
FSplashForm.Name := 'SplashForm'
;
RegisterFormInstance(FSplashForm, False);

inherited
;
end
;

Show the splash screen when the main form is activated for the first time. The best place for that is in the overridden FormActivated method.

type
TForm1=class
(TW3form)
private
FFirst:
boolean;
{$I 'Form1:intf'}
public
procedure FormActivated; override
;
protected
procedure InitializeObject; override
;
end
;

implementation

{ TForm1}

procedure
TForm1.FormActivated;
begin
if FFirst then
begin
FFirst :=
false;
Application.ShowModal('SplashForm', 'SplashPanel', ''
);
end
;
end
;

procedure
TForm1.InitializeObject;
begin
inherited
;
{$I 'Form1:impl'}
W3Label1.Font.Size := 24
;
FFirst :=
true;
end
;

Now you only have to design the splash screen. Place all components on a panel named SplashPanel (as this name is used in the ShowModal call) and write a simple FormActivated method which will close the splash screen after three seconds.

uses 
w3system, w3graphics, w3components, w3forms, w3fonts,
w3borders,
w3application, w3panel, w3label,
w3time;

type
TSplashForm=class
(TW3form)
private
{$I 'SplashForm:intf'}
public
procedure FormActivated; override
;
protected
procedure InitializeObject; override
;
end
;

implementation

{ TSplashForm}

procedure
TSplashForm.FormActivated;
begin
TW3EventRepeater.After(3000, lambda Application.HideModal(mrOK); end
);
// do program initialization here
end
;

procedure
TSplashForm.InitializeObject;
begin
inherited
;
{$I 'SplashForm:impl'}
W3Label1.Font.Size := 24
;
end
;

If you want to do any slow initialization (such as loading resources from the server), the FormActivated method is the proper place for it.


Run and the splash screen will be displayed over the main form.


image


The splash screen will disappear after three seconds and you’ll be able to use the program.


image



You can test the program here or download it from here.

July 04, 2013

Smart 1.1.2

Next version of Smart Mobile Studio was released as a beta yesterday. It should be pretty much close to the release version (except for the bugs that will be found by first users) so you can use it in your normal development workflow.

Still, this is a beta and it has problems that we didn’t find in internal testing. Make sure that you read the Installation section of the release document (linked above) before installing it as the installer will kill your snippets file. (Stupid oversight for which I apologize.)

The official document contains a pretty long list of changes so go there if you want to know everyhing. Here I will just sum up the features that I find most important.

Smart is now much more version control friendly. Source files inside the .opp project are not stored anymore in the BASE64 encoding but use much more diff-friendly CDATA format. For example, a file that was previously stored as

        <files>
            <file clsid="TIDEProjectFileSource">
                <name>ApplicationShutdown</name>
                <created>2012-08-18T11:14:02Z</created>
                <notes/>
                <source>dW5pdCBBcHBsaWNhdGlvblNodXRkb3duOw0KDQppbnRlcmZhY2UNCg0KdXNlcyANCiAgdzNzeXN0
ZW0sIHczY3RybHMsIHczY29tcG9uZW50cywgdzNmb3JtcywgdzNhcHBsaWNhdGlvbiwgZm9ybTE7
DQoNCnR5cGUNCiAgVEFwcGxpY2F0aW9uID0gY2xhc3MoVFczQ3VzdG9tQXBwbGljYXRpb24pDQog
IHByaXZhdGUNCiAgICBwcm9jZWR1cmUgSGFuZGxlQmVmb3JlVW5sb2FkKFNlbmRlcjogVE9iamVj
dCk7DQogICAgcHJvY2VkdXJlIEhhbmRsZVVubG9hZChTZW5kZXI6IFRPYmplY3QpOw0KICBwdWJs
aWMNCiAgICBwcm9jZWR1cmUgQXBwbGljYXRpb25TdGFydGluZzsgb3ZlcnJpZGU7DQogICAgcHJv

would now be saved as

      <file clsid="TIDEProjectFileSource">
        <name>ApplicationShutdown</name>
        <created>2012-08-18T11:14:02.000Z</created>
        <notes></notes>
        <source>
          <![CDATA[unit ApplicationShutdown;

interface

uses
  w3system, w3ctrls, w3components, w3forms, w3application, form1;

type
  TApplication = class(TW3CustomApplication)
  private
    procedure HandleBeforeUnload(Sender: TObject);
    procedure HandleUnload(Sender: TObject);

Handling of ‘external’ (not stored in the .opp) units and forms was also much improved and all newly created units and forms can now be external by default (there’s a Preference setting for that).

Compiler was improved again (go Eric!). I especially like the sort and map support for dynamic arrays and improvements in the for in support. Sets will also come handy, I’m sure.

Some long standing bugs in the RTL (like the inability of TW3Label to be displayed in a disabled state) have finally been fixed. Otherwise, RTL didn’t change a lot. Oh, there’s a new Android Holo theme (CSS) which give the application much more ‘androidish’ look. The old Android theme (which was just renamed iOS theme) is also installed but you can safely ignore it.

I am a great fan of the new IDE behaviour where editing state (open tabs, bookmarks) is stored in the project file and is restored on load. Editing and code navigation has also been improved – see the changelog for more details.

The last great addition, built-in diff viewer, was shamelessly copied from the Andreas Hausladen’s great DDevExtensions. (Well, the idea was copied. Implementation is our own.) When a file that is open in Smart Mobile Studio is modified externally, a ‘change’ dialog will pop up.

image

You can select a file (or even a form) and click Compare to run a diff engine based on the TDiff component, written by Angus Johnson.

image

You can also configure an external diff/merge tool such as TortoiseMerge or WinMerge.

All in all, 1.1.2 will be a very strong release which should ease waiting on the next big release, 1.2 (due in Autumn).

April 27, 2013

A Smart Book Covers Smart 1.1

I have just published an update to the A Smart Book. Added were 38 pages covering Smart 1.1 – language changes, new controls and RTL additions.

Read more or get the book.

April 23, 2013

New in Smart 1.1: Modal Dialogs

Besides the new compiler and a bunch of new components, Smart 1.1 also includes support for modal dialogs. There is also a new demo ModalDialog which shows how to use the new feature. Today I’ll walk you through this demo.

April 20, 2013

New in Smart 1.1: HTML Elements

Smart Mobile Studio 1.1 contains many new controls which I hope to describe in the following days. Today I’ll start with a group of three controls which allow the programmer to insert specific HTML elements (a.k.a. tags) on a Smart form.

image

April 10, 2013

New in Smart 1.1: Bugs and Omissions

The 1.1 edition generally works very well but there are still few glitches. At the moment I am aware of two problems which can both be fixed by editing the RTL code.

April 02, 2013

New in Smart 1.1: Properties with Anonymous Storage

When a property is backed directly by a field (without a getter and/or a setter) and this field is never accessed directly, the code can be further simplified by dropping the field declaration altogether.

An example of such code would be:

type
TMyClass =
class
private
FData:
integer;
public
property Data: integer read FData write
FData;
end
;

This code can be simplified to:

type
TMyClass =
class
public
property Data:
integer;
end
;

Smart will still create a field inside the TMyClass object, but this field will be aonymous and not accessible directly from the code.

Note: This type of properties cannot be used in external classes and lasses inheriting from the JObject class.

March 25, 2013

New in Smart 1.1: Property Expression

Smart Pascal supports properties just the same as Delphi and Free Pascal do. Properties are supported in classes, records, interfaces and in helpers (helper classes and records). In addition to the standard syntax, Smart Pascal supports property expressions which help you write more compact code.

Property expressions can be used in two ways – by providing a backing storage (typically a field or property containing the data) or by providing a modifying expression (an expression that modifies and returns/stores data). In both cases, property expressions are introduced by an opening parenthesis and ended by a closing parenthesis.

The simplest way to explain the functioning of this language extension is through examples. The following example defines a form containing two labels, W3lblTask and W3lblDetail. The form also defines two properties. Property Task provides access to the W3lblTask.Caption and property Detail provides access to the W3lblDetail.Caption.

type
TToDoListTemplate=class
(TW3form)
private
{$I 'ToDoListTemplate:intf'}
protected
procedure InitializeObject; override
;
public
property Task: string read
(W3lblTask.Caption) write (W3lblTask.Caption);
property Detail: string read
(W3lblDetail.Caption) write (W3lblDetail.Caption);
end
;

Equivalent code in a “classic” style would be quite longer.

type
TToDoListTemplate=class
(TW3form)
private
{$I 'ToDoListTemplate:intf'}
function GetDetail: string
;
function GetTask: string
;
procedure SetDetail(value: string
);
procedure SetTask(value: string
);
protected
procedure InitializeObject; override
;
public
property Task: string read GetTask write
SetTask;
property Detail: string read GetDetail write
SetDetail;
end
;

function TToDoListTemplate.GetDetail: string
;
begin
Result :=
W3lblDetail.Caption;
end
;

function TToDoListTemplate.GetTask: string
;
begin
Result :=
W3lblTask.Caption;
end
;

procedure TToDoListTemplate.SetDetail(value: string
);
begin
W3lblDetail.Caption :=
value;
end
;

procedure TToDoListTemplate.SetTask(value: string
);
begin
W3lblTask.Caption :=
value;
end
;

In the example above, (W3lblTask.Caption) and (W3lblDetail.Caption) provide a backing storage; a place where the data is stored. We can, however, do more and write a full expression inside the property expression-wrapping brackets. In case of a getter (read access) this expression must return a result and in case of the setter (write access) this expression should be a statement setting the value of the property. The setter can use a pseudo-parameter Value holding the value that was assigned to the property in the code.

I've said should be a statement because the compiler is not really fussy and will handle any expression in the setter. This allows for weird tricks where the assignment to a property produces a side effect.

The second example defines a TAngle record which holds one value (angle) stored in radians and exposes it through two properties, Radians returning the value in radians and Degrees returning the value in degrees. Conversion between radians and degrees is done inside property expressions.

type
TAngle =
record
FAngleRad:
float;
property Radians: float read FAngleRad write
FAngleRad;
property Degrees: float read (Radians/Pi*180
) write (Radians := Value/180*Pi);
end
;

Equivalent code in “classic” style would again be longer.

type
TAngle =
record
FAngleRad:
float;
functon GetDegrees:
float;
procedure SetDegrees(Value:
float);
property Radians: float read FAngleRad write
FAngleRad;
property Degrees: float read GetDegrees write
SetDegrees;
end
;

function TAngle.GetDegrees:
float;
begin
Result := Radians/Pi*180
;
end
;

procedure TAngle.SetDegrees(Value:
float);
begin
Radians := Value/180
*Pi;
end
;

March 22, 2013

New in Smart 1.1: Lambdas

Version 1.1 introduced more compact syntax for closures, similar to the C#'s syntax with an extra lambda keyword thrown at the front. Two different types of `lambda` closures are supported -- functions and statements.

Lambda Functions

Lambda functions are used when the code expects an anonymous function and when the code implementing this function is short. The syntax for lambda functions is:

lambda (parameter_list) => expression

The lambda keyword is followed by an optional parameter list, => and an expression returning a result of the appropriate type.

For example, the following code creates an event that is called every five seconds.

var repeater := TW3EventRepeater.Create(
  function (Sender: TObject): boolean
  begin
    Result := MyFunction;
  end,
  5000);

Anonymous method calls some function in the code and returns its result. (False will trigger another event after the timeout (5000 ms) and True will stop the repeater.)

Let's rewrite this code using a lambda function.

var repeater := TW3EventRepeater.Create(lambda (Sender) => MyFunction, 5000);

As you can see, there's no need to declare the parameter (Sender) type and the function result type; Smart will detect them automatically. Even more, as we don't use the Sender parameter, we can drop the parameter list and use an even shorter form.

var repeater := TW3EventRepeater.Create(lambda => MyFunction, 5000); 

Lambda Statements

The statement form is used when you want to put more than one statement inside the lambda. The syntax for lambda statement is:
lambda (parameter_list)  statement;  [statement;]  [...]
  [statement;]
end

A lambda statement can also implement a function; in that case you should return the result in a normal Delphi way by assigning to a Result pseudo-variable.

Following example sets up a repeater that calls a method MyProc every three seconds.

var repeater := TW3EventRepeater.Create(lambda => MyProc; Result := false; end, 5000);

You can use variables inside a lambda statement, but only if they are declared inline.

Lambdas are an excellent addition to the language, as they provide for a more compact code. For example, in Smart 1.0 the W3Layout unit used the following code:

ResizeChildren(FClientArea.Height, [TAlign.Top, TAlign.Bottom],
  function (layout: TLayoutImpl): Variant
  begin
    Result := layout.GetConfig.GetHeight;
  end,
  procedure (layout: TLayoutImpl; value: integer)
  begin
    layout.GetConfig.Height(value);
  end);

In Smart 1.1, this was simplified to:

ResizeChildren(FClientArea.Height, [TAlign.Top, TAlign.Bottom],
  lambda (layout) => layout.GetConfig.GetHeight,
  lambda (layout, value) layout.GetConfig.Height(value) end);

Lambdas are also very helpful when defining event handlers.

W3btnOK.OnClick := lambda Application.HideModal(mrOK); end;

January 23, 2013