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

Category Archives: Developers log

Thinking ahead

Posted on 01.02.2012 by Jon Lennart Posted in Developers log 3 Comments

I have to come up with some names for the different technologies soon. Smart now have two terms for compiler and also two levels of RTL: the low level RTL that is a part of Eric’s compiler, and a high level RTL which is our “VCL” clone. Im thinking of naming our component library the VJL (visual javascript library), and instead of refering to the compiler infrastructure as “the compiler”, it is more fitting to call it “the build tool”.

One vs. many

As the test group knows, the build-tool takes your source-code, invoked the compiler and finally glues everything together into a final, solid HTML5 document. Since our system was originally designed for iOS development only, and since Smart components (including forms, which is our version of pages in a way) are purely javascript based – a fully operational “app” really only needs one HTML file.

In Alpha 2 i removed the injection of code directly into the document.body section and introduced “Application.Display.View” to the VJL. The reason for this was make the application regard “the screen” abstractly. So by altering what “display.view” points to – you can make your apps live inside any DIV you wish.

A couple of testers have reported back that it could be handy to separate the RTL from the program code. There are a number of scenarios where you might, for example, want to run multiple Smart apps on the same document. If you run a website and want to get rid of Flash for instance, it would be nice to code the new banner in Smart and also host a game or a cool menu written in Smart as well.

Having talked it over with Eric it became clear that this should be reasonable to achieve, but it will come at a price: namely that it defeats the latest compiler switch named “smart linking”. When you smart link your apps, only the code you have used is included in the final binary (in our case “binary” is javascript). It’s the same technique Delphi and C++ uses to make programs as small as possible.

So if we include the feature then it will disable the smart linking option. I am experimenting with this now, by dumping the entire RTL into a separate file. If it doesn’t produce any negative side effects (except a small speed penalty and some bloat) then I’ll include it as an option. Eric might slap me over the head for playing around with this – but it would (in my view) complete the parallel of “Delphi” for javascript.

Reusable libraries

One of my long term goals is to add a new project type to Smart for writing libraries. Which would be the javascript incarnation of DLL’s. Since we have our own IDE we could generate a class-map for the library – which you could then import later so the Smart IDE can keep track of what the libraries export. A bit like a Windows TLB file when working with COM objects.

We should be able to poll this off by isolating the compiled code in it’s own name-space. It would then have it’s own RTL and library – but due to the nature of Javascript, it should actually work πŸ™‚ It would mean a little tweak to the RTL but we are constantly tweaking anyhow.

Why are libraries important? Components, that’s why. By pre-compiling and obfuscating your code – you could write and sell your own components. The other benefits are self evident I think.

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 πŸ™‚

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!

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]

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

OP4JS: Project file format

Posted on 29.11.2011 by Jon Lennart Posted in Developers log 3 Comments
Embed or reference, now you chose

Embed or reference, now you chose

In the olden days of 16 bit computing, most programming languages saved their projects in a single binary format. In short: all the files pertaining to your project was housed in a single file. The benefits were of-course that making backups was easier, and it was also easier to keep track of a project.

This is something that I have really missed in the age of modern computing. I have had some experiences with Delphi where i misplaced packages and source files and actually lost quite a bit of work. I don’t blame Delphi for this of-course, it has been completely my own fault and it all has to do with keeping 5 Mac’s and 3 PC’s in sync πŸ˜›

But still, i do miss being able to save an entire project – and I mean everything – in a single file. It was so easy when sending a project to a friend to just ship one single file (today we use SVN naturally but still), and also so much easier when making backups. You have a projects folder that contain X number of project-files, rather than a folder containing thousands of files, including the SVN revisions.

You can clearly see what file is on disk and which is resident

You can clearly see what file is on disk and which is resident by it's glyph

With OP4JS I’m bringing this old trend back. So you can finally mix and match between the “normal” way of organizing your project (one file per unit + project file + dependencies) or the old school “packaged” way (all files stored inside the project file). You can also keep some files resident and others external. Good if you want to share a unit with someone or just downloaded something from the net.

Import versus reference

Under vanilla Delphi you don’t import files, you reference them (explicit or implicit). I made a small twist to this concept so that if your project contains a file with the same name as an RTL file – it will always use that instead. If you chose to open an RTL file you are always given the option to create a duplicate – inside the project file. That way you can create your very own version of the RTL file without screwing up the system. It’s also invaluable during the development of new RTL files and bug-fixing the system.

Or good fun if you want to “mod” the RTL πŸ™‚

delphi OP4JS

Asm sections? You betcha!

Posted on 28.11.2011 by Jon Lennart Posted in Developers log 6 Comments
OP4JS about to go Alpha

OP4JS about to go Alpha

I posted a picture of the OP4JS pre-Alpha testbed to my Facebook group, and a member found it interesting that it had an ASM section in the code. How can there be an ASM section in a system that targets JavaScript you wonder?

Well, assembler for OP4JS is basically what assembler would be to a real Delphi application. In this case: raw JavaScript. Eric Grange, my friend and author of our compiler, has done a great job on transposing classical Object Pascal terminology onto the (let’s face it) bewildering typology of JavaScript.

Take this simple procedure for instance:

procedure TMyObject.Testing;
var
  mRef: TObject;
begin
  mRef := tagRef;
  asm
    (@mRef).style.width=100 + "px";
  end;
end;

What we do here is to first get a handle to the our tag (the tagRef is a public property of TW3TagObject, the class TW3CustomControl inherits from). We then enter the ASM section, use that reference to access and alter the width style property. Ofcourse you dont have to deal with this stuff unless you want to, because OP4JS will ship with a rich set of controls ready to be used. And rolling your own controls is so simple it’s almost ridicules.

The squiglies

But why the @ prefix you wonder? Well, when we obfuscate our code (make it unreadable, or less “stealable” for the average hacker), all the names of variables and methods are altered. As such, the compiler needs to be able to quickly figure out if you are using a JS based variable or an Object Pascal variable. So all Object Pascal variables have to be prefixed with the @ character. Due to the nature of Javascript you also need to isolate direct references to object fields and native fields inside ( [ .. ] ) sections, like in this example:

asm
  (@self.FWidth) = parseInt( (@mRef).style.width );
end;

Where did my pointers go?

JavaScript don’t have pointers, at least not in the proper sense of addresses and memory buffers. What it does have are object references and data references (it also has a weak reference counted garbage collector). So under OP4JS we dont have a type called “pointer” because it would screw up the reality of compiling to JavaScript. Instead, TObject serves the function of a universal object reference, and variant serves as a universal data reference. Variants are special however, because we dont have any operators dealing with it directly (so you cant write: A:=1 + someVariant). The variant type is just used to transport data from one method to another.

But, all the standard types are there: string, boolean, float, integer and so on. You also have records, interfaces and enumerations to play with. It really is a neat system once you get the hang of it.

  function getSomeData: Variant;
  begin
    asm
      /* return a data structure */
      @result = {first:"hello",second:"hello2"}
    end;
  end;

  procedure handleSomeData(aValue: Variant);
  begin
    asm
      /* access the data structure passed in */
      alert(@aValue.first); //will show "hello"
    end;
  end;

Super simple custom control

To demonstrate how extremely simple it is to create your own controls under OP4JS, let’s make a scroll-text. As you probably know HTML have a tag called marquee that scrolls text in a variety of ways. It has been called an evil tag because it consumes a lot of CPU speed (and that part is very true), but just for the hell of it – let’s make a super-simple OP4JS version of it:


unit myscroller;

interface

uses w3system, w3components;

type

TW3Marquee = Class(TW3CustomControl)
private
  FText:    String;
  procedure SetText(aValue:String);
public
  Property  Text:String read FText write SetText;
End;

implementation

procedure TW3Marquee.SetText(aValue:String);
Begin
  //Keep the text
  Ftext:=aValue;

  // Cheat and inject the tag into our innerHTML
  // This works because TCustomControl has already created
  // a tag for us. So we just inject the content
  innerHtml:='<marquee style="'
  + 'font-family: verdana;'
  + 'width: 100%;'
  + 'height: 100%;'
  + '-webkit-marquee-increment:3px;'
  + '-webkit-marquee-speed:fast;'
  + '-webkit-marquee-direction:backwards;'
  + '-webkit-marquee-repetition:infinite;'
  + '">' + FText + '</marquee>';
end;

end.

Naturally this is just a quick example. A fully functional and quality control would have a slightly different layout. There we would isolate the marquee in it’s own tag object. But the approach is perfectly valid, although a bit slap-dash πŸ™‚

OP4JS does not work by injecting text into the DOM, that is to slow. We create tag objects via the Javascript API and access our objects by reference. This is why OP4JS apps are much faster than those produced by other JS compilers. We try to avoid the use of getElementById() because it results in poor performance.

Console and gaming applications under OP4JS

Posted on 10.11.2011 by Jon Lennart Posted in Developers log 5 Comments
A simple console app

A simple console app

OP4JS is getting near to completion for each day that passes. We are currently implementing the final project types which are: console and gaming. Yes you read right – console.

Console

A console application under OP4JS is basically a visual project, but where an instance of TW3Console occupies the majority of the screen. It is meant for testing purposes (for now) where you want a quick and easy project type just to test out theories and play around with routines that doesn’t require forms.

We do have more plans for the console in future versions of OP4JS:

  • Command registration (think TActions but with params)
  • Built in REST command for testing http services
  • Pipe output to email

At present the console application supports WriteLn() which outputs both to the screen and to the actual console javascript object. This is handy because it means you can use XCode to see the output “live” if you want to (or any other remote debugger).

Gaming

The generic gaming project type is very simple, basically it puts safari mobile into full-screen, plasters a canvas in the view-port and uses a high-speed timer to force maximum redraw-rate. It is up to you to load in pictures and draw them using the methods in the canvas object.

Since i have coded a lot of 2d platform games earlier, you can expect to see a game library coming out as soon as the product has shipped. In fact it’s one of the things i’m eagerly looking forward to working on.

 

Console HTTP Log OP4JS REST

Hardware accelerated webkit animations

Posted on 30.10.2011 by Jon Lennart Posted in Developers log

Working with hardware accelerated webkit animations under vanilla Javascript can be daunting. First of all it takes a while to understand the interrupt driven nature of the webkit engine (or “trigger” based is perhaps a more familiar word to us Delphians) and secondly because there are actually two types of animations (transitions), explicit and non-explicit (animations), which adds to the complexities.

Under OP4JS we have started out by supporting animations only, which basically means that you can trigger a pre-defined animation using either TNamedAnimation or any of our ready-made animation classes. If you wish you can trigger non-explicit animations (or transitions) as much as you like, but you will have to set the tag properties and css values yourself. The heart of our animation system resides in the W3Effects.pas file that is going to ship with the RTL – and you can expect it to grow once we start to issue updates and service packs.

Let me show you how easy it is to setup a hardware acellerated animation and play it:

[sourcecode language=”delphi”]
Procedure TForm1.HandleEffectDone(Sender:TObject);
Begin
TW3NamedAnimation(sender).free;
end;

Procedure TForm1.MoveHeader;
Begin
FEffect:=TW3NamedAnimation.Create;
FEffect.AnimationName:=’HEADER-MOVE’;
FEffect.Duration:=0.80;
FEffect.ExecuteEx(FHeader,NIL,HandleEffectDone);
end;
[/sourcecode]

And in our CSS file we define our animation (this will be automated in a future version of OP4JS):

[sourcecode language=”CSS”]
@-webkit-keyframes HEADER-MOVE {
from {
left: 100%;
top: 0px;
} to {
left: 0px;
top: 0px;
}
}
[/sourcecode]

Voila. That’s all it takes to make a control references byΒ FHeader (or any control you want) to fly across the top of the screen using hardware acceleration (when available, not all platforms supports it directly and resort to software).

Keep it simple

It’s easy to go overboard with effects like this so try to keep in mind that every phone model is unique and have different performance levels. I am currently using 2 hardware accelerated “movers” to navigate between forms, and the difference between the iPhone 3GS and 4G is quite dramatic. It seems 3GS does not support hardware unless your control is placed directly on the document. So while it’s easy to spin things around – we must be prudent in when we use these things. Nothing is worse than an app where the effects get in the way of the actual substance.

 

Animations CSS3 hardware OP4JS webkit

TApplication coming to a close

Posted on 28.10.2011 by Jon Lennart Posted in Developers log
Always when you least need it

Always when you least need it

Yes, I know. This month was meant to be a very active time for OP4JS but sadly Norwegian weather brings with it complications like colds and the flu. So in short i have spent nearly 3 weeks off the grid with nothing but fevers, allergies and sneezing. So to those of you eagerly awaiting the Alpha release of OP4JS I am sad to inform you that we might have to push the date forward to make up for lost time.

Be that as it may my health is finally picking up after the onslaught of germs, viruses and weather up here – so for the past week I have been eagerly working on the object model, in this case: TApplication.

Much like under Objective C (which is the official language you use to create iOS applications, although you can now use alternatives) TApplication is the root controller object. It is in charge of creating a visible screen, kick-starting your application code, which in turn creates forms and register them, which is ultimately injected into the viewport. The viewport (or visible area) being a child object of TScreen – the place where forms do their thing.

Why go to so much trouble you ask? Well, it has to do with several aspects of HTML5 but first and foremost it deals with clipping and scrolling. You want your forms to slide in without problems under any webkit based browser (be it Safari Mobile or Chrome for Android). Secondly, we are trying to avoid having different TApplication models for each of our project types. We are currently aiming for 3 project types:

  • Graphical application (“form” based”)
  • Console application (for test purposes)
  • Game application
The nested layout made visible

The nested layout made visible

TApplication have to be dynamic enough to suit all 3 variations – and we also want to safeguard ourselves for the future where more project types come into play (libraries being on top of the list).

It also have to manage the forms you add to your application correctly, which means taking care of transitions, pre-positioning forms prior to movement and many more details. But thankfully we found a solution that is simple, elegant and robust. And no external dependency either. We might even drop jQuery soon because quite frankly: we dont need it.

On your right is view of how we organize things. The white color is from the actual HTML5 document, the red color is TScreen – which in turn has a child TCustomControl called viewport (green).

The benefits of this layout is that you can (if you want to) add a global header directly to the TScreen object. So instead of each form descending from TW3HeaderForm (which as the TW3Header control built into it) you can just create one header for the whole app. Of-course this means that your forms have to change the title and deal with the back and next buttons directly – but that’s just as easy as it would be in ordinary Delphi.

The second benefit is more or less the same, except for the footer. Many native apps have main view controller that introduces a fixed header and footer, typically containing a tab-bar at the bottom and a toolbar on top. We want to support this because it solves a lot of problems (and also makes you apps faster. The less objects the faster it runs, that’s how it works in Delphi as well).

Well — I better get back to work!

Upcoming features

Snippets and comments, simple but effective

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

The OP4JS IDE (integrated development environment) aims to be simple, neat and clean. There are two reasons for this: First of all there is no point trying to catch up with products that have been in development for nearly two decades – and secondly because we don’t necessarily agree with the route some companies have taken with regards to their IDE’s.

Delphi 7, the most popular IDE ever

Delphi 7, the most popular IDE ever

If you ask a Delphi developer what his all-time favorite IDE is, chances are he is going to put the finger somewhere between Delphi 5 and Delphi 7. The environments back then were responsive, lightweight and easy to work with. The interface was so intuitive that even without formal training it required little effort to learn how to use the it. For me personally Delphi 7 is the undisputed king of IDE’s with one exception, like XCode it was a multi windowed environment which is a feature that messes up your work-space.

So for our IDE we turned the idea on it’s head. Since we are starting from scratch – why not use this opportunity to simplify things again? We have neither the time or manpower to catch up with the likes of Delphi, XCode or MonoDevelop. But what we do have is a keen eye on details and a desire to keep things effective.

Back to basics

What are the basics of a good IDE? What do we need to get our work done quickly and efficiently? What do I need?

  • Tabbed source editing
  • Syntax highlighting
  • Method proposal (press “.”)
  • Parameter hints
  • Project tree-view
  • Unit tree-view
  • Property inspector
  • Form designer
  • A snippet library
  • A proper note system
  • A help system designed for human beings
  • CTRL + mouse to quickly locate a symbol (or equivalent functionality)

Text matters

Use notes as your scrap book

Use notes as your scrap book

If you are anything like me you probably have a desktop littered with notes, books, gadgets and coffey mugs. Once a week I give my desk a run over, clean out the thrash and try to organize my notes in a logical, easy to use fashion. I also have a couple of huge whiteboards with important things kept in check by magnets. Fact is, text matters. It is through words that we formulate and transfer ideas.

Sadly the important of text and keeping our ideas organized havent really been implemented in most development environments. Delphi has a skinny “to do” list which is added to the project. I know a couple of people that use it – but let’s be honest: it’s pretty meager stuff. I mean, if I want to generate some form of documentation from my source-code, wouldn’t it be better to keep my notes in one place and my code in another? I’m not suggesting that we should stop commenting code, far from it, I’m simply saying that code-comments is more than enough for the code part. Adding documentation, ideas, who-did-what, credits and examples in the code is a bit excessive.

In short, OP4JS supports comments for every element belonging to the project. You can even comment on images if you like. But it’s not a simple text field or a memo – it’s a full editor. The view will actually split to make room for your notes and as such you can jot down everything (or just use it as a scrap-book when trying out new ideas). The comment editor has proven instrumental when porting Javascript to Object Pascal, because I can paste the JS code in the comment editor and convert it method by method with both sources in plain view. It’s also very handy when it comes to keeping track of who did what and where you last worked, just in case you forget between sessions.

Snippets as a resource

A snippet is just a piece of code that you use often or that you found online. Handy enough to keep but not essential enough to deserve it’s own unit. I haven’t really used snippets before but after implementing it – it’s quite addictive (!) Whenever I go online to search for a solution or study a particular task – the snippet library functions as my extended clipboard, if that makes any sense.

Snippets is an underestimated resource

Snippets is an underestimated resource

borland delphi ide

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
  • …
  • 6
  • 7
  • 8
Β© Optimale Systemer AS