Smart Mobile Studio
  • News
  • Forums
  • Download
  • Store
  • Showcases
    • Featured demos
    • The Smart Contest 2013, Round 1 – Graphics
  • Documentation
    • Get the book
    • System requirements
    • Prerequisites
    • Getting started
      • Introduction
      • Application architecture
      • The application object
      • Forms and navigation
      • Message dialogs
      • Themes and styles
    • Project types
      • Visual project
      • Game project
      • Console project
    • Layout manager
    • Networking
      • TW3HttpRequest
      • TW3JSONP
      • Loading files
  • About

All new Smart Mobile Studio

Posted on 23.01.2012 by Jon Lennart Posted in Developers log 4 Comments

For the past week and a half things have been quite calm on our website, this is not due to lack of work but rather focusing on some of the more tricky aspects of the IDE. So here they are in no particular order:

Alternative rendering

As an alternative to Chromium I attempted to wrap the Opera DLL’s last weekend, but the differences between Safari and Opera (both style and javascript wise) were to large – so I decided to drop it. Chrome is the browser most compatible with Safari (they both use the same webkit foundation) and as such we will stick with TChromium. We also had to backtrack to find the most stable version of TChromium since the latest revisions simply don’t work as expected.

Keyword proposal

Keyword proposal now works as expected

Keyword proposal now works as expected

This is an issue that has been driving me nuts for a while, but finally I tracked down the bug (wrong cache pointer .. sigh) – and Smart Mobile Studio now have keyword proposal in the box. We will naturally aim to expand this into the realm of code-completion and other advanced features in the future.

XML file format

In the first versions of the Alpha release we used a custom binary file format. This file format is now replaced by a proper XML format, making it easier to expand the system with new options and data without breaking backwards compatibility. You will need to copy and paste out your units to make the transition though, but it’s a small price to pay for a more versatile system. The new file format also supports external unit files (much like Delphi has by default) and we added a recursive search method to locate implicitly referenced units. Also, a new folder as been added to the mix: “libraries”. If you have made some utility units place those files under IDE/Libraries and the IDE will automatically find them.

What’s next

Once we have completed some of the tickets on fogbugz the final battle begins, namely offscreen rendering of components and the visual form designer. Then we brush up on the look & feel of the IDE and give the standard components more features and bling — then it’s release time.

Crack open the Redbull, im ready to rock 🙂

Variant is your friend

Posted on 12.01.2012 by Jon Lennart Posted in Developers log

Using variants as mediators is now possible under Smart Mobile Studio. This removes some of the burden when interacting with native javascript objects or external libraries:

[sourcecode language=”delphi”]
procedure TMyObject.InvokeByVariant;
var
mSrc: variant;
Begin
//get the browsers window object
asm
@mSrc = window;
end;

//invoke our method
handleCallback(mSrc);
end;

procedure TMyObject.HandleCallback(a:variant);
Begin
// treat "a" as an object
a.alert(‘this is a test’);
end;
[/sourcecode]

Note: Variants are treated as “unknown” by the codegen. It has no compiler operators for it, meaning you cant write “if a<>1 then” or “a:=12”. Variants are primarily used to transport native values and objects between methods dealing with javascript objects or browser objects.

In the above example we simply calls a procedure passing the native browser object “window” as a parameter. In the HandleCallBack method we invoke the alert method of that object. Once again, Smart deals with variants as unknown entities – so there is no checking that “alert” actually exists.

Files, folders and the dreaded javascript filesystem

Posted on 11.01.2012 by Jon Lennart Posted in Developers log
Javascript filesystem is bonkers

The collective wisdom of the WC3 can be questioned from time to time.

One of the trickiest and most frustrating aspects of javascript coding has to be the async file-system. Where opening a file and looping through a read sequence sounds easy enough (and is in most languages) – being async means that everything is handled through events. Why you say? Because javascript is by nature single threaded, so the cpu time has to be divided between all the action that takes place inside the browser. And that includes accessing files and folders.

In short, when you open the filesystem – the actual object you get back is delivered through an event. When you want to read X number of bytes from a file, you invoke it in one place and handle the actual reading someplace else. So it’s not exactly linear and object pascal friendly to say the least.

Using the force, Sith style

To solve this I have come up with the concept of disk actions. A disk action in this case is basically an object that handles everything associated with the action you want to execute (loadfile, savefile, copy etc.) – this gives us the benefit of isolating the code that invokes the filesystem and it’s event handler(s) in one place. And those that want to access the filesystem through Smart Mobile Studio wont have to deal with the ridicules visions of the World Wide Web Consortium (WC3).

My wrapper aims at handling things like this:

[sourcecode language=”delphi”]
FFileSystem:=TW3FileSystem.Create;
try
FFileSystem.open(5 * CNT_MEGABYTE,fstPersistent);
try
FFileSystem.Execute(TW3OpenFileAction.Create
(‘prefs.ini’,IniFileRead);
finally
FFileSystem.close;
end;
finally
FFileSystem.free;
end;

Procedure IniFileRead(sender:TObject;aData:TW3Buffer;
aFilename:String);
Begin
//File is read into a buffer (actually a "blob"
//Use the methods of TW3Buffer and TW3View(ers) to
//access the data in "reader" style
w3_showmessage(aData.toString);
end;
[/sourcecode]

Always been more of an empire man

Always been more of an empire man

But due to the nature of the javascript callback system, we probably have to move several aspects of the above into events. But at least I will isolate the events in one object, making it a hell of a lot easier to work with than native javascript.

For example, “FFileSystem.Execute” wont be a legal call in the above example, because it will be executed before the event which delivers the file-system native object has called us back. To solve this I have some tricks up my sleeve – but I think it’s wise to play it safe when it comes to building a new RTL from scratch. So expect some event management.

The answere is 42

I also built in a fail-safe for error codes. As I was testing the same code in both Chrome, Safari and FireFox – i noticed that the error codes where different between two browsers (which shall remain anonymous but involves a fox and some iron). The error names were the same (e.g: FileError.QUOTA_EXCEEDED_ERR) but the integer values could differ.

So instead of just hard-coding the numbers I used the newly added TW3Dictionary object(s) to map the error codes in the browser to it’s Object Pascal type enumeration. So even if the browser alters the actual error code our code will work just fine.

[sourcecode language=”delphi”]
//Register known errors in the constructor
FErrors:=TW3IntDictionary.Create;
registerError(fseQuotaExceeded);
registerError(fseNotFound);
registerError(fseSecurity);
registerError(fseInvalidModification);
registerError(fseInvalidState);
registerError(fseUnknown);

//Do evil things with butter
Procedure TW3FileSystem.RegisterError(aKind:TW3FileSystemError);
var
mKey: String;
Begin
if supported then
Begin
try
mKey:=IntToStr(ErrorToNative(aKind));
FErrors.Values[mKey]:=ord(aKind);
except
on e: exception do
Raise EW3Exception.CreateFmt(CNT_ERR_METHOD,
[‘RegisterError’,ClassName,e.message]);
end;
end;
end;
[/sourcecode]

Thank god I only have the audio and video objects left to wrap, because I’m getting a bit tired of low level javascript. But the foundation is getting tweaked and polished (Primoz Gabrijelcic have really given it a run for it’s money, testing every avenue and tidbit in the framework. I dont think I have ever seen a person consume and adapt to information that fast. Also the wizard of code which is Eric Grange is ever watchfull and actually knocked out a full game in under a day after release), so when the foundation is done for version 1.0 –  I can fully dedicate myself to high-level component writing.

Having said that — there is plenty of room for you guys to create your own units and start creating components for Smart Mobile Studio!

So far people have created games, advanced mandelbrot explorers, particle systems, hacker group demos and even classes that connect directly to RemObjects services (!) – and we aren’t even out of the alpha phase. Imagine what version 2.0 will look like. Buckle up dorothy because we’re just getting started (!)

Oh almost forgot.. Whenever I have the spare time, I will be implementing a converter for .mod music files (sound-tracker, pro-tracker: those old sample based music files). Im not sure the JS timer system is up for the challenge, perhaps we have to use web-workers (threads) to handle the dispatching – but I really want to add the frosting on the cake later on. No one has ever done anything like this in Javascript – so why not send a spartan to do it 😉

Fair play

And please. Try to avoid copying software. We are a two man company and have dedicated a lot of resources to polling this off. If you use it in some way – please support our work and buy a license when it’s released. If you want your friend to try it out then just ask us and he can register with the alpha team. We hear code written in Smart is already being used in production scenarios, and it’s sort of self-defeating for the community if what we hear is true.

Our prices will be very reasonable. Somewhere between $200 – $400 for the first version which is very humble concidering 6+ months of work has gone into research, figuring out how to do things, building a model and bridging technologies.

Smart Mobile Studio is becoming a weapon of mass construction – ok so let’s show those javascript punters what were made of 🙂

How do i move graphics from the canvas to an image?

Posted on 10.01.2012 by Jon Lennart Posted in Documentation
Generating images offscreen and using it is now a snap!

Generating images offscreen and using it is now a snap!

In alpha release 3 several missing bits and pieces from the HTML5 standard was added to Smart Mobile Studio. One of the key methods that were missing from our canvas implementation was toDataUrl – a function which has it’s opposite in TW3ControlBackground and TW3Image fromURL and LoadFromUrl methods.

So in effect, it is now very simple to transport off-screen graphics (graphics you have created on a canvas) and use it as either a background or as the content of a normal image.

Here is an quick example of how to create a picture dynamically and display it in a TW3Image control. Also notice that you can actually assign the image to the background of any TW3CustomControl descendant.

To run the example create a new visual project and replace the code in Form1 with the following:

[sourcecode language=”delphi”]
unit Form1;

interface

uses w3system, w3ctrls, w3forms, w3graphics,w3application;

type

TForm1=class(TW3form)
private
{ Private methods }
FImage: TW3Image;
FGraph: TW3GraphicContext;
FButton: TW3Button;
procedure HandleButtonClicked(Sender:TObject);
protected
{ Protected methods }
Procedure InitializeObject;override;
Procedure FinalizeObject;override;
Procedure StyleTagObject;override;
procedure resize;Override;
end;

Implementation

//############################################################################
// TForm1
//############################################################################

Procedure TForm1.InitializeObject;
Begin
inherited;
FImage:=TW3Image.Create(self);
FImage.Background.fromColor(clWhite);
FButton:=TW3Button.Create(self);
FButton.OnClick:=HandleButtonClicked;
FButton.Caption:=’Click to generate’;
FGraph:=TW3GraphicContext.Create(NIL);
End;

Procedure TForm1.FinalizeObject;
Begin
FImage.free;
FButton.free;
FGraph.free;
inherited;
End;

procedure TForm1.HandleButtonClicked(Sender:TObject);
var
FCanvas: TW3Canvas;
aFrom: String;
aTo: String;
Begin
FGraph.Allocate(FImage.Width,FImage.Height);
FCanvas:=TW3Canvas.Create(FGraph);
try

// Clear background
FCanvas.fillstyle:=’rgb(0,0,99)’;
FCanvas.fillrectF(0,0,FGraph.Width,FGraph.Height);

// Draw some text on the canvas
FCanvas.font:=’10pt verdana’;
FCanvas.FillStyle:=’rgb(255,255,255)’;
FCanvas.FillTextF(‘This was generated on a canvas!’,10,20,MAXINT);

//You can load it in as a picture
FImage.LoadFromUrl(FCanvas.toDataUrl(”));

//.. or load it as a background to a picture (or control)
//FImage.background.fromUrl(FCanvas.toDataUrl(”));

finally
FCanvas.free
end;
FGraph.release;
end;

procedure TForm1.resize;
var
hd: Integer;
dy: Integer;
Begin
FImage.setBounds(5,5,width-10,(height div 2) + (height div 3) );
hd:=height – (FImage.top + FImage.Height + 5);
dy:=(hd div 2) – (FButton.height div 2);
FButton.setBounds(5,dy + FImage.Top + FImage.height,width-10,FButton.height);
end;

Procedure TForm1.StyleTagObject;
Begin
inherited;
StyleClass:=’TW3CustomForm’;
End;

end.

[/sourcecode]

Articles about Smart

Posted on 07.01.2012 by Jon Lennart Posted in News
Not your father's "hello world"

Not your father's "hello world"

The well known programming guru and author of Omni Thread Library, Primoz Gabrijelcic, have given the alpha version of Smart Mobile Studio a run for it’s money. He has produced two articles (in a planned series of articles) about how to implement a fully operational fractal explorer under Smart.

We consider it an honour to have Primoz giving our system a solid test-drive. Primoz Gabrijelcic is well known in the Delphi community for both his skill and insight into all things technical.

The first article can be found here:

http://www.thedelphigeek.com/2012/01/first-steps-with-smart-mobile-studio.html

And the latest installment can be read here:

http://www.thedelphigeek.com/2012/01/my-first-smart-program.html

A simple sprite-sheet

Posted on 06.01.2012 by Jon Lennart Posted in Developers log

A sprite sheet is basically just an image. But it’s an image that is organized in a special way, usually with a 32×32 or 64×64 pixel grid where each cell contains either a character animation frame – or a background tile. Back in the old Amiga days of 8 bit graphics and hand crafted sprites this was the only way to go.

Since the world of mobile javascript game development is more or less en-par with the old Amiga (in terms of cpu power and restrictions. Which is amazing since the Amiga had a 1hz motorola mc68000 CPU) an example of a spritesheet class might come in handy.

Classical sprite sheet from sega

Classical sprite sheet from sega

A simple spritesheet class

TW3SpriteSheet = class(TObject)
private
  FImage:     TW3Image;
  FReady:     Boolean;
  FColumns:   Integer;
  FRows:      Integer;
  FTotal:     Integer;
  FWidth:     Integer;
  FHeight:    Integer;
  FOnReady:   TNotifyEvent;
  procedure   HandleImageReady(sender:TObject);
  procedure   SetWidth(aValue:Integer);
  procedure   Setheight(aValue:Integer);
  Procedure   ReCalcInfo;
public
  Property    OnReady:TNotifyEvent read FOnReady write FOnReady;
  Property    SpriteWidth:Integer read FWidth write setWidth;
  Property    SpriteHeight:Integer read FHeight write setHeight;
  Property    Ready:Boolean read FReady;
  Procedure   LoadImage(aUrl:String);
  Procedure   Draw(Canvas:TW3Canvas;dx,dy:Integer;FrameIndex:Integer);
  Constructor Create;virtual;
  destructor  Destroy;Override;
end;

constructor TW3SpriteSheet.Create;
begin
  inherited Create;

  FWidth  := 32;
  FHeight := 32;
  FColumns := 0;
  FRows  := 0;
  FTotal := 0;

  FImage := TW3Image.Create(NIL);
  FImage.OnLoad := HandleImageReady;
end;

destructor TW3SpriteSheet.Destroy;
begin
  FImage.onLoad:=NIL;
  FImage.free;
  inherited;
end;

procedure TW3SpriteSheet.setWidth(aValue:Integer);
begin
  FWidth:=w3_ensureRange(aValue,4,MAXINT);
  ReCalcInfo;
end;

procedure TW3SpriteSheet.setheight(aValue:Integer);
begin
  FHeight:=w3_ensureRange(aValue,4,MAXINT);
  ReCalcInfo;
end;

procedure TW3SpriteSheet.ReCalcInfo;
begin
  if FReady then
  begin
    FColumns:=FImage.Width div FWidth;
    FRows:=FImage.Height div FHeight;
    FTotal:=FColumns * FRows;
  end else
  begin
    FColumns:=0;
    FRows:=0;
    FTotal:=0;
  end;
end;

procedure TW3SpriteSheet.HandleImageReady(sender:TObject);
begin
  FReady:=True;
  ReCalcInfo;

  if assigned(FOnReady) then
    FOnReady(self);
end;

procedure TW3SpriteSheet.LoadImage(aUrl:String);
begin
  FReady:=False;
  ReCalcInfo;
  FImage.LoadFromUrl(aUrl);
end;

procedure TW3SpriteSheet.Draw(Canvas:TW3Canvas; dx,dy:Integer; FrameIndex:Integer);
var
  sx,sy:  Integer;
begin
  if  FReady
  and assigned(canvas)
  and (FrameIndex>=0)
  and (FrameIndex<FTotal) then
  Begin
    sx:=FrameIndex mod FColumns;
    sy:=FrameIndex div FRows;
    sx:=sx * FWidth;
    sy:=sy * FHeight;
    canvas.DrawImageEx2F(FImage.tagRef,sx,sy,FWidth,
    FHeight,dx,dy,FWidth,FHeight);
  end;
end;

Using the class

Using the class is simple. Initialize it in TApplication.ApplicationStarting method and load in a picture, like this:

  FSheet := TW3SpriteSheet.Create;
  FSheet.LoadImage('res/sprites.png');

When the actual sprite-sheet image is loaded, the “ready” property will be set to true. So in your PaintView method always check the ready flag before accessing it:

  if FSheet.Ready then
  begin
    FSheet.Draw(Canvas,100,100,10); // draw tile #10
    FSheet.Draw(Canvas,133,100,11); // draw tile #11
    FSheet.Draw(Canvas,166,100,12); // draw tile #12
  end;

Enjoy!

How do i plot pixels on a offscreen bitmap?

Posted on 06.01.2012 by Jon Lennart Posted in Documentation

Just like ordinary Delphi, Javascript has it’s own canvas object. As you can imagine the canvas of the browser is quite different from the good old Delphi TCanvas, but not so alien that it doesn’t have it’s similarities. But you will need to brush up on the documentation from Apple in order to use it.

But HTML5 also have something else up it’s sleeve, namely that you can create off-screen bitmaps (wrapped in the TW3ImageData class from w3graphics.pas). The difference between a Delphi bitmap and a HTML5 bitmap is 3 fold:

  • The bitmap is obtained from the canvas, not the other way around (Delphi’s TBimap has a canvas property)
  • Off-screen bitmaps do not have a canvas, they are in reality DIBS (device independent bitmaps)
  • Off-screen bitmaps are 32bit exclusively (RGBA, 8888 format).

This is actually good news because it means we can create games and multimedia dealing with pixel data rather than the (excuse me) somewhat cumbersome canvas object. Most javascript developers actually avoid this part because they are used to “high level” coding only – but coders coming from the Delphi community have been knocking out low level graphics libraries for ages. So if you have ever played around with DIBS (device independent bitmaps) in Delphi – you should feel right at home.

Here is a quick example of how to plot some pixels off-screen, and copy the results onto the screen (note: this is a game project):

[sourcecode language=”delphi”]
unit Project8;

interface

uses w3system, w3components, w3application,
w3game, w3gameapp, w3graphics, w3components;

type

TApplication=class(TW3CustomGameApplication)
private
{ Private methods }
FBuffer: TW3ImageData;
protected
{ protected methods }
procedure ApplicationStarting;override;
procedure ApplicationClosing;override;
Procedure PaintView(Canvas:TW3Canvas);override;
end;

Implementation

//############################################################################
// TApplication
//############################################################################

procedure TApplication.ApplicationStarting;
Begin
inherited;

//Initialize refresh interval, set this to 1 for optimal speed
GameView.Delay:=20;

(* Create a our "offscreen bitmap" *)
FBuffer:=GameView.Canvas.CreateImageData(32,32);

//Start the redraw-cycle with framecounter active
//Note: the framecounter impacts rendering speed. Disable
//the framerate for maximum speed (false)
GameView.StartSession(true);
End;

procedure TApplication.ApplicationClosing;
Begin
GameView.EndSession;

inherited;
End;

// Note: In a real live game you would try to cache as much
// info as you can. Typical tricks are:
// 1: Only get the width/height when resized
// 2: Pre-calculate strings, especially RGB/RGBA values
// 3: Only redraw what has changed, avoid a full repaint
// The code below is just to get you started

procedure TApplication.PaintView(Canvas:TW3Canvas);
Begin
// Clear background
canvas.fillstyle:=’rgb(0,0,99)’;
canvas.fillrectF(0,0,gameview.width,gameview.height);

// Draw our framerate on the screen
canvas.font:=’10pt verdana’;
canvas.FillStyle:=’rgb(255,255,255)’;
canvas.FillTextF(‘FPS:’ + IntToStr(GameView.FrameRate),10,20,MAXINT);

// plot some pixels
if FBuffer<>NIL then
Begin
FBuffer.setPixelC(0,2,clGreen);
FBuffer.setPixelC(1,2,clGreen);
FBuffer.setPixelC(2,2,clGreen);

FBuffer.setPixelC(0,4,clRed);
FBuffer.setPixelC(1,4,clRed);
FBuffer.setPixelC(2,4,clRed);

// paste graphics to display
Canvas.putImageData(FBuffer,20,20);
end;
End;

end.

[/sourcecode]

The result may not look so impressive right now, but it’s the foundation for what will become a very impressive browser based graphics system:

Pixels galore

Pixels galore

In the future we are going to add a lot more functionality to the TW3ImageData class. Things like line, ellipse, fillrect, circle and flood-fill is already prototyped. But if you feel like playing around with pixels – this is a good start.

Open the file w3graphics.pas and have a look at the methods and properties of TW3ImageData for more information. Also check out this excellent canvas tutorial by Mark Pilgrim.

How do I rotate a control by X degrees?

Posted on 05.01.2012 by Jon Lennart Posted in Documentation

All descendants of TW3Customcontrol, which is the primary object most visual controls derive from, has a property called Angle. This is a floating point property which will rotate your control in whatever angle you define. Please bear in mind that this property will override any webkit rotation in the current style. If you want the stylesheet to retain it’s position, mark the CSS tag with !important;

For instance:

[sourcecode language=”delphi”]
unit Form1;

interface

uses w3system, w3ctrls, w3forms, w3application;

type
TForm1=class(TW3form)
private
{ Private methods }
FButton: TW3Button;
Procedure HandleClick(Sender:TObject);
protected
{ Protected methods }
Procedure InitializeObject;override;
Procedure FinalizeObject;override;
Procedure StyleTagObject;override;
end;

Implementation

//############################################################################
// TForm1
//############################################################################

Procedure TForm1.InitializeObject;
Begin
inherited;
FButton:=TW3Button.Create(self);
FButton.caption:=’Click me’;
FButton.setBounds(100,50,100,28);
FButton.onClick:=HandleClick;
End;

Procedure TForm1.HandleClick(Sender:TObject);
Begin
if FButton.Angle=60 then
FButton.Angle:=0 else
FButton.Angle:=60;
end;

Procedure TForm1.FinalizeObject;
Begin
inherited;
End;

Procedure TForm1.StyleTagObject;
Begin
inherited;
StyleClass:=’TW3CustomForm’;
End;

end.

[/sourcecode]

When you click the button it will toggle between normal (0 deg) and tilted (60 deg), like this:

Best not to over do it

Best not to over do it

How do i create and use a timer?

Posted on 05.01.2012 by Jon Lennart Posted in Documentation

Under Delphi and free-pascal there is a component called TTimer. Under Smart Mobile Studio however all types of timer objects have a slightly different architecture – and also different names (we will probably provide a TTimer alias before release). The class you are looking for is called “TW3EventRepeater”.

To use a timer start by adding the unit “w3time” to your unit’s uses section. Unlike Delphi, TW3EventRepeater derives from TObject rather than TComponent. There is no point in creating a component (which adds quite a bit of overhead) when a normal object will do.

Using the event repeater from a form is a snap:

[sourcecode language=”delphi”]
unit Form1;

interface

uses w3system, w3ctrls, w3forms, w3application, w3time;

type
TForm1=class(TW3form)
private
{ Private methods }
FTimer: TW3EventRepeater;
FCount: Integer;
function HandleTimer(sender:TObject):Boolean;
protected
{ Protected methods }
Procedure FormActivated;override;
end;

Implementation

//############################################################################
// TForm1
//############################################################################

Procedure TForm1.FormActivated;
Begin
FTimer:=TW3EventRepeater.Create(HandleTimer,1000);
end;

function TForm1.HandleTimer(sender:TObject):Boolean;
Begin
result:=False;
inc(FCount);
if FCount>9 then
Begin
TW3EventRepeater(sender).free;
result:=true;
w3_showmessage(‘time is up!’);
end;
end;

end.
[/sourcecode]

As expected the timer kicks in after 10 seconds informing us that the time has expired

The timer works just like we expect

The timer works just like we expect

You may have noticed that the callback was a function and not a procedure? If you return “true” the timer will stop of it’s own accord. Since this is javascript and not winapi you can actually dispose of the timer while the timer is called. Because the timer object does not go out of scope until the function returns.

Add a new form to my application

Posted on 05.01.2012 by Jon Lennart Posted in Documentation

Adding a new form to a visual application is a piece of cake. Start by opening your project (or create a new visual project), then click the “add form” button in the IDE or add form from the project menu.

Adding a new form is very simple

Adding a new form is very simple

This will present you with a brand new unit, ready to be used by your application. Now switch over to your project unit (in this example, the project was automatically called “project7”, and thus the project unit is called “project7″). The project units looks something like this:

[sourcecode language=”delphi”]
unit Project7;

interface

uses w3system, w3ctrls, w3forms, w3application,
form1;

type

TApplication=class(TW3CustomApplication)
private
{ Private methods }
public
{ protected methods }
procedure ApplicationStarting;override;
end;

Implementation

//############################################################################
// TApplication
//############################################################################

procedure TApplication.ApplicationStarting;
var
mForm: TW3CustomForm;
Begin
//Add code above this line
mForm:=TForm1.Create(display.view);
mForm.name:=’Form1′;
RegisterFormInstance(mForm,true);
inherited;
End;

end.
[/sourcecode]

Before you can actually display and work with your form, the application must know about the form’s existance. So we need to register an instance of the form with the form manager inside TApplication (remember to add “form2″ to your uses section). Simply create an instance of your form by copying the code already present. We alter the name ofcourse so we dont get any conflicts, and we send False rather than True as the last parameter:

[sourcecode language=”delphi”]
procedure TApplication.ApplicationStarting;
var
mForm: TW3CustomForm;
Begin
//Add code above this line
mForm:=TForm1.Create(display.view);
mForm.name:=’Form1′;
RegisterFormInstance(mForm,true);

mForm:=TForm2.Create(display.view);
mForm.name:=’Form2′;
RegisterFormInstance(mForm,false);

inherited;
End;
[/sourcecode]

The reason we pass in “false” as the second parameter is because this value defines the “main” form of the application. All visual applications must have a main form, which is also the form the application displays when you start it.

We can now use the methods GotoForm or GotoFormByRef to navigate between forms. Both these commands (which are members of TCustomApplication) takes a second parameter which controls the special effect. As of writing you can only slide the new form in from either the left or right, but more interesting effects are planned.

How do i create a class

Posted on 05.01.2012 by Jon Lennart Posted in Documentation

You can create a class under Smart Mobile Studio the exact same way as you would under Embarcadero Delphi or free-pascal. Just like ordinary object pascal, classes, custom types and functions are stored in a unit file. Below is an example of a very simple class which has one public member:

[sourcecode language=”delphi”]
unit myobject;

interface

uses w3system;

type
TMyObject = Class(TObject)
public
procedure dosomething;
End;

implementation

procedure TMyObject.dosomething;
Begin
w3_showmessage(‘you called me’);
end;

end.
[/sourcecode]

To add a new unit to your project, click the “add unit” button in the IDE, or select add unit from the project menu. You can then proceed to type in the code you want. By default the IDE provides some skeleton code for your unit, so you don’t have to type everything.

To use the unit you have just created – simply add the name of the unit to the uses section in an already existing unit. All unit have a uses section which makes the code in other units visible to that particular unit.

More information

  • Writing a class unit (delphi basics)

Using the TW3HttpRequest object

Posted on 05.01.2012 by Jon Lennart Posted in Developers log 2 Comments

We have received some questions regarding the w3inet.pas unit that ships with the alpha release. Most of the questions is in the line of “why doesn’t this code work” when trying to connect to a server.

The reason you cannot connect to an external host, especially one outside your own domain, is actually a rule imposed on us by the W3C standard (see http://www.w3.org/TR/XMLHttpRequest/ for the documentation). This limitation is called the “same origin” policy, where a website is only allowed to access data and information from the domain it came from. It was this rule that put an effective stop to people stealing content (that was so common in the early days of the Internet).

In other words, you can only use it to access files from your own domain. But, since you are developing on a local machine and not your server this means we have to localize our operations a bit:

  1. Place the file (an XML file for instance) you want to access in your res or lib folder (add it to your project as a resource)
  2. use relative paths when accessing it (instead of “http://domain/path/name” use “/res/mystuff.xml”)
  3. As an alternative, edit your windows host file and point www.yourdomain.com to localhost

Accessing web services

The easiest way to bypass the origin rule is to place your development machine in the domain you want to target, or simply add a line to your host file (we used to do this with our WebSnap services all the time). If these two options are not possible, simply install a public domain proxy on your development machine so that you can control the source.

Future development

Since we have a built in server in our IDE – this issue will be taken care of. We will have a dialog that allows you to define an external service – and then access that as a call to the local server. But for now, the rules of the game is the same as any JavaScript developer have to deal with.

Working with controls, the boxing model

Posted on 05.01.2012 by Jon Lennart Posted in Developers log, Documentation

Smart mobile studio introduces a few minor differences to an otherwise “VCL like” RTL. Just like Delphi you can create visual and non-visual controls, you have the same methods to work with (like resize) and you can move and size your child controls with left, top, width and height properties.

The HTML5 box model can require a bit of work to get right

The HTML5 box model can require a bit of work to get right

One important issue however, is that reading and writing non pascal properties (left, top, width and height being prime examples) relies on your control’s HTML to be visible to the DOM. In short, reading properties in the constructor can cause the browser to report NaN (not a number) as a result. This has nothing to do with our RTL but rather how the browser realizes cascading styles.

Modern HTML5 actually have 3 sets of styles:

  1. A style “class” applied to an element from a style sheet (see “styleClass” property in TW3CustomControl)
  2. Inline styles, which overrides whatever is set in the style sheet
  3. Calculated styles, which is the combined style the browser has compiled from the above. This is why it’s call “cascading” style-sheets, because they flow into each other resulting in a final style.

Since we want our components to reflect “real” values, our component model reads values from the calculated style. If we did not do this – things like margins defined in a css style would be invisible to your controls (and thus size calculations would be wrong).

[sourcecode language=”delphi”]
Procedure TForm1.InitializeObject;
Begin
inherited;
FLabel:=TW3Label.Create(self);
FLabel.left:=10;
FLabel.top:=10;
FLabel.width:=Self.Width – 20;
//Self.Width will return NaN, it should be moved to Resize
End;
[/sourcecode]

So to sum up:

  • Positions (etc) are written as in-line styles but read from calculated styles
  • Calculated styles are only available “post” creation of a control, which means reading position values in the constructor is not the correct way of doing things

Use resize

The proper way of handling a good layout under Smart is to deal with positions under the resize method. This doesn’t require any more code than usual – you just have to put your layout code under resize rather than in the constructor. This is how most languages deal with it (the C# object model is particularly strict about these things).

[sourcecode language=”delphi”]
Procedure TForm1.InitializeObject;
Begin
inherited;
FLabel:=TW3Label.Create(self);
End;

Procedure TForm1.Resize;
Begin
inherited;
FLabel.left:=10;
FLabel.top:=10;
FLabel.width:=Self.Width – 20;
End;
[/sourcecode]

Alpha program

Posted on 02.01.2012 by Smart Mobile Studio Team Posted in Announcements 8 Comments

A very early pre-release (alpha) of OP4JS was released just days before Xmas. To be honest we were pleasantly surprised by the demand for the alpha. We now have close to 100 testers which have committed feature requests, bug reports and fixes. This is invaluable for our work and will shorten development time radically. So a huge thanks to everyone that is contributing (!)

Official name

OP4JS is just a codename or “nickname” for the in-house project. A while back we decided to dub the product with it’s official title: Smart Mobile Studio. While this website (www.op4js.com) will continue to be in use for a long time, we will sooner or later switch to our new domain. The documentation will also use Smart as the product name.

New participants

We don’t want to block people out of the alpha program, but we are reaching the stage where we have to stop taking on new users. There are still a few slots open but the alpha group is just about full.

Having said that, our beta program will begin as soon as we have ironed out bugs and implemented the improvements and features in the ticket system.  If you missed the alpha then you are more than welcome to join our beta program.

 

Sincerely

The Smart Mobile Team

release Stable release

OP4JS: Happy new year

Posted on 01.01.2012 by Jon Lennart Posted in Developers log

I want to thank everyone that has taken the time to check out the alpha release, and wish everyone a happy new year! Thanks to your help we have a list of roughly 50 reports on things that needs to be fixed or changed – and they will all be addressed asap. Tomorrow the holidays is officially over in Norway and it’s back to work for all of us.

I am also amazed at how many demo’s we have seen already, considering that an Alpha is very much work in progress. Eric Grange knocked out a clone of the retro game missile command (low frame-rate video). On my iPad it runs at 230 frames per second. This is actually to fast to play 🙂 Primoz Gabrijelcic also made a nice fractal explorer as well which can be seen here.

Have a happy new year!

delphi graphics javascript OP4JS

Pages

  • About
  • Feature Matrix
  • Forums
  • News
  • Release History
  • Download
  • Showcases
    • The Smart Contest 2013, Round 1 – Graphics
  • Store
  • Documentation
    • Creating your own controls
    • Debugging, exceptions and error handling
    • Differences between Delphi and Smart
    • Get the book
    • Getting started
      • Introduction
      • Local storage, session storage and global storage
      • Application architecture
      • The application object
      • Forms and navigation
      • Message dialogs
      • pmSmart Box Model
      • Themes and styles
    • Layout manager
    • Networking
      • Loading files
      • TW3HttpRequest
      • TW3JSONP
    • Prerequisites
    • Real data, talking to sqLite
    • System requirements
    • Project types
      • Visual project
      • Game project
      • Console project

Archives

  • December 2019
  • December 2018
  • November 2018
  • July 2018
  • June 2018
  • February 2018
  • September 2017
  • April 2017
  • November 2016
  • October 2016
  • September 2016
  • April 2016
  • March 2016
  • January 2016
  • October 2015
  • September 2015
  • July 2015
  • April 2015
  • January 2015
  • December 2014
  • October 2014
  • September 2014
  • August 2014
  • July 2014
  • June 2014
  • March 2014
  • February 2014
  • January 2014
  • December 2013
  • November 2013
  • October 2013
  • August 2013
  • July 2013
  • June 2013
  • May 2013
  • April 2013
  • March 2013
  • February 2013
  • January 2013
  • December 2012
  • November 2012
  • August 2012
  • July 2012
  • June 2012
  • May 2012
  • April 2012
  • March 2012
  • February 2012
  • January 2012
  • November 2011
  • October 2011
  • September 2011

Categories

  • Announcements (25)
  • Developers log (119)
  • Documentation (26)
  • News (104)
  • News and articles (16)

WordPress

  • Register
  • Log in
  • WordPress

Subscribe

  • Entries (RSS)
  • Comments (RSS)
  • Prev
  • 1
  • …
  • 10
  • 11
  • 12
  • 13
  • Next
© Optimale Systemer AS