Home > Delphi, OP4JS > Writing a Facebook clone with Smart Mobile Studio – Part 1

Writing a Facebook clone with Smart Mobile Studio – Part 1

In this tutorial we are going to explore how to use Smart Mobile Studio to write a small but flattering Facebook clone – cleverly nicknamed CaseBook (Sort of works if you think about it, for a while *smile* ). It will demonstrate just how easy it is to make such applications when you have the right tools.

If this is the first time you check out out Smart Mobile Studio, you will probably need to brush up a bit on what exactly our technology does and what your options are.

A few words about Smart Mobile Studio

Smart Mobile Studio

Smart Mobile Studio

In short, Smart Mobile Studio is an Object Pascal Compiler. Instead of producing machine-code it generates high-quality JavaScript, meaning that you can execute your pascal apps in any HTML5 compliant browser. The system was architected to target mobile devices. It represents a short-cut to delivering “apps”, since using technology like Cordova (Phonegap) allows you to compile HTML5 into real executable code for iOS, Android and blackberry — all in one go.

It comes with a huge collection of ready-made classes and controls, ready to be augmented – extended and used. The RTL (run-time library) was especially architected for mobile devices, but is perfectly suited for full-screen browser experiences as well.

Smart Pascal is also a great Adobe Flash replacement. You can write complex, object-oriented apps, commercials, games or anything you want – and simply embed your program inside  a DIV tag on your website. No dependencies, no plugins or browser extension – and you don’t even need a server to run your apps. They are fully self-sustained JavaScript modules.

If you know Delphi, then Smart Pascal will be like second nature to you. It bridges the rich world of HTML5 and agile JavaScript with the technically superior Object Pascal. The best of both worlds.

If you want to know “how” this is possible (you nerd) then visit wikipedia for the low-down. If you dont care and just want to code – continue reading.

Visit the Smart Mobile Studio website or check out the Wikipedia article for more information.

Setting a goal

Right. Before we start to write code it’s good practice to mentally go through what we want to achieve, and even spend a little time writing it out. Let’s start with a superficial “pow-wow-whatever” of what we are going to build:

  • Write a mobile application inspired by Facebook
  • The application deals with cases rather than news-posts
  • Each case can be commented on
  • Each case is represented as a small post, containing ingress (header image + text)
  • Each case item has a body of text, but is truncated if it covers more than 50% of the display
  • Each case item has a footer with like, comment and other buttons

Now let’s break this into tasks so we can get started:

  • Case items should be touch-scrollable, case display must inherit from TW3ScrollControl
  • Case items are composite, containing sub controls, must inherit from TW3CustomControl
  • The application will need at least 3 different forms:
    • Main form (user profile)
    • Case display form
    • Comment form

If this was a complete, fully functional application we would of-course need more forms, like editing a case, assigning users to a case, security and access rights – and much more. We would also need a web-service and proper database binding. But for our little tutorial the above is enough to get us started and it will demonstrate just how effective Smart Mobile Studio is.

Using Smart Pascal

Ok, start up Smart Mobile Studio and create a new visual project. Feel free to add 2 extra forms to the application (commentform and msgform), then save the project in it’s own folder called “casebook” on your hard disk. Next, add a new unit to the project and call it msgutils.pas and save that as well.

If you start up facebook on your iPhone or Android device, the application starts on your profile. Displaying posts that you yourself have posted earlier, as well as your picture, a header and whatever secondary name you have added (or a sub-title). You also have a slim toolbar with icons for posting a new message, checking personal messages and so on. This form is simply “the main form”.

If you click the “home” button on Facebook, you are brought to a second form which display a scrolling list of messages posted by everyone in your circle. Friends, groups you are a member of, pictures people have posted — depending on the security settings people apply to what they post, these things show up here.

What we need first of all is to be able to scroll up and down a list of messages. For this we will derive our control from the scrolling window class in unit w3scroll.pas. This base-class includes touch sensitivity with a scroll-indicator that fades in and out – so it’s almost perfect.

The class TW3ScrollControl has a property called Content, which is a TW3CustomControl based visual control. You populate this control with your own components, re-size it and you can scroll around it using touch. In our case we want a vertical list of “news” items (case items) so we need a function to measure the total height of whatever content is there already – so we know what position to inject new case-items. To simplify adding case-items we also isolate the construction of these in its function.

Ok, let’s write some code.

unit msgutils;

interface

uses W3System, W3Graphics, W3Components, w3image, w3label, w3toolbar,w3Scroll;

type

TCaseBookMsgBox = Class(TW3CustomControl)
private
  FGlyph:   TW3Image;
  FCaption: TW3Label;
  FDesc:    TW3Label;
  FBar:     TW3Toolbar;
protected
  procedure Resize;Override;
  procedure InitializeObject; override;
  procedure FinalizeObject; override;
public
  Property  Title:TW3Label read FCaption;
  Property  Description:TW3Label read FDesc;
  property  Glyph:TW3Image read FGlyph;
  Property  Toolbar:TW3Toolbar read FBar;
End;

TCaseBookMsgList = Class(TW3ScrollControl)
public
  function  calcContentHeight:Integer;
  function  AddItem(aCaption,aDescription:String):TCaseBookMsgBox;
End;

implementation

(* Some constants to simplify layout of case-items *)
const
  CNT_IMG_SIZE  = 24;
  CNT_BAR_SIZE  = 26;
  CNT_SPACE     = 2;

//#############################################################################
// TCaseBookMsgList
//#############################################################################

function  TCaseBookMsgList.AddItem
          (aCaption,aDescription:String):TCaseBookMsgBox;
var
  dy: Integer;
Begin
  (* create our "news item" control *)
  result:=TCaseBookMsgBox.Create(self.Content);
  result.Color:=clWhite;

  (* set properties for title and text *)
  result.Title.Caption:=aCaption;
  result.Description.Caption:=aDescription;

  (* calculate the height of all case-items being displayed *)
  dy:=calcContentHeight;

  (* position our "news item" at the bottom of the content page *)
  result.SetBounds(CNT_SPACE,dy,clientwidth-4,100);

  (* re-size the content to include the newly created control *)
  Content.Height:=dy + 100 + CNT_SPACE;
end;

function TCaseBookMsgList.calcContentHeight:Integer;
var
  dy: Integer;
  y:  Integer;
  mChildren:  TW3ComponentArray;
begin
  (* Look through all child controls of our content page
     and sum up the size of each + spacing *)
  dy:=0;
  mChildren:=Content.GetChildrenSortedByYPos;
  if mChildren.Length>0 then
  begin
    for y:=mChildren.Low to mChildren.High do
    Begin
      if (mChildren[y] is TCaseBookMsgBox) then
      begin
        inc(dy,TW3CustomControl(mChildren[y]).Height);
        if dy>0 then
        inc(dy,8) else
        inc(dy,CNT_SPACE);
      end;
    end;
  end;
  result:=dy;
end;

//#############################################################################
// TCaseBookMsgBox
//#############################################################################

procedure TCaseBookMsgBox.InitializeObject;
Begin
  inherited;
  (* create our glyph image *)
  FGlyph:=TW3Image.create(self);
  FGlyph.setSize(CNT_IMG_SIZE,CNT_IMG_SIZE);

  FCaption:=TW3Label.Create(self);
  //FCaption.Background.FromColor(clRed);
  FCaption.Font.Name:='Helvetica';
  FCaption.Font.Size:=16;
  FCaption.StyleClass:='';

  FDesc:=TW3Label.Create(self);
  FDesc.Font.Name:='Helvetica';
  //FDesc.Background.FromColor(clCyan);
  FDesc.StyleClass:='';

  FBar:=TW3Toolbar.Create(self);
  FBar.Background.FromColor(rgbToColor(230,230,230));
  FBar.StyleClass:='';
end;

procedure TCaseBookMsgBox.FinalizeObject;
Begin
  FGlyph.free;
  FCaption.free;
  FDesc.free;
  FBar.free;
  inherited;
end;

procedure TCaseBookMsgBox.Resize;
var
  dx,dy: Integer;
Begin
  inherited;
  (* Resize can be called by the browser before the
     JS prototype is complete. So we always check
     all control references before we use them *)
  if assigned(FGlyph)
  and assigned(FCaption)
  and assigned(FBar)
  and assigned(FDesc) then
  Begin
    FGlyph.SetBounds(CNT_SPACE,
      CNT_SPACE,
      CNT_IMG_SIZE + CNT_SPACE,
      CNT_IMG_SIZE + CNT_SPACE);

    dx:=FGlyph.BoundsRect.right + CNT_SPACE;
    FCaption.SetBounds(dx,
      CNT_SPACE,
      clientwidth-(dx + CNT_SPACE) ,
      CNT_IMG_SIZE + CNT_SPACE );

    dy:=clientheight - FCaption.BoundsRect.Bottom;
    dec(dy,CNT_BAR_SIZE);
    dec(dy,CNT_SPACE * 3);

    FDesc.SetBounds(CNT_SPACE,FCaption.boundsrect.bottom + CNT_SPACE,
      clientWidth-(CNT_SPACE * 2),
      dy);

    dy:=FDesc.boundsrect.bottom + CNT_SPACE;
    FBar.setBounds(CNT_SPACE,dy,clientwidth- (2 * CNT_SPACE),
      CNT_BAR_SIZE);

  end;
end;

end.

The class TCaseBookMsgBox is the visual representation of a “news item” (read: case item). Just like on FaceBook when you post something, the news-item has a thumbnail of your profile picture, a short title, your message (either in full or truncated) and a footer. The footer has the “like”, “share” and other buttons on it.

If you look at the code I just wrote you will notice that our item contains child controls which match this.

Having a look at it

Doesnt look like much does it? Yet what we have here is a fully touch-enabled scrolling list which can be CSS3 styled and made to look like the bomb. But before we style this puppy with bling, let’s start with the basics and simply make it visible. So while we work we add this little gem to our main-form until it’s ready to be used by both the main-form and our “news” form.

Casebook first look

Casebook first look

In our main-form I went into the designer and dropped a TW3HeaderControl, then I just adopted the resize method of the form to position the scrolling list. Here is the code so far:

procedure TForm1.InitializeForm;
begin
  inherited;
  FMsgList:=TCaseBookMsgList.Create(self);
  FMsgList.Background.FromColor(RGBToColor(190,190,190));
  FMsgList.Content.Height:=200;
  FMsgList.Content.Background.FromColor(RGBToColor(200,200,200));

  w3_callback( procedure ()
    begin
      Resize;
      FMsgList.AddItem('Anonymous','This is the first<br>line of stuff');
      FMsgList.additem('Anonymous','This is the second<br>case post, simple and easy to work with');
    end,
    100);
end;

procedure TForm1.Resize;
var
  mRect:  TRect;
begin
  inherited;
  if assigned(FMsgList)
  and assigned(w3Headercontrol1) then
  Begin
    mRect:=clientRect;
    mRect.top:=w3HeaderControl1.Height + 2;
    FMsgList.SetBounds(mRect);
  end;
end;

Adding some bling

The next step is to be a bit more detailed. A facebook post actually have 3 labels in the header. First is your name, secondly the title of your post, and on the line below it is the timestamp (e.g: “anonymous posted on thursday 5’th”). So the next step is to fill in the blanks and also populate our toolbar at the bottom. We want a “like” button, a comment button and a share button. We also want word-wrapping inside the labels – and the navigation from mainform to “news” form and “comment” form should work as expected.

For this example we will continue to use the TW3HeaderControl and just style that when all the logic is in place. Facebook has a cooler looking header, but ultimately it’s more or less the same as the classical iOS header.

Next time

Object Pascal has a bright future — but we need to educate more developers about what is out there. I’m by definition an older programmer, so if you have 15+ years of coding behind you – you are in good company. I can deliver a Facebook prototype in under 6 days – server included. That either means that I am a superman coder, or that the way I work and the tools I use gives me an edge. Follow the next tutorial and find out just how awesome Smart Pascal is and what it can do for HTML5!

[to be continued]

 

Advertisements
  1. June 20, 2014 at 10:12 pm

    Great, Jon .. I´m looking material for learn Smart MobileStudio but I have found almost nothing … no tutorial, a few videos and the product does not help. Have a site you can indicate me? I will use your site for learning something. Hugs

    • Jon Lennart Aasenden
      June 21, 2014 at 10:34 am

      The best way to learn SMS (I presume you are coming from a Delphi or FreePascal background) is to get a couple of books:
      1. Javascript, the good parts
      2. A smart book -http://www.smartprogrammer.org/

      You dont have to be a JS expert, as long as you know the basics: exceptions, if/then/else and all the “ordinary JS stuff” then that will help you so much more.

      Secondly, have a look at w3system.pas and w3components.pas

      These two units are the heart of SMS.
      Here you find all the classes that makes a rather messy environment of the browser – into an object oriented, fully compartmentalized Object Pascal environment. Just like Delphi the first thing to be created when you run your code is TApplication. Which in turn creates your forms (and so on).
      These two units implement the basic custom controls and component framework — which was made as identical to delphi as JS allows them to be. So TCustomControl is here named TW3CustomControl. This means you can re-use a lot of your delphi skills directly without modification.

      But yes. Just like C# and other popular “mobile” languages (mono for iOS/Android) you are expected to write code. Drag & Drop design is nice — but ultimately it’s faster and more efficient to work with the classes and create your own controls.

      I will be writing a lot of articles on smart, and also a tutorials — so you will find a lot by searching this blog (OP4JS is the project codename, search that) — and also a lot of articles on the SMS website — except the website really is a mess. It will be replaced as soon as possible.

      I had an accident 2 years ago that sadly stopped me from finishing what I started. But now i’m back and things will happen again.

  1. No trackbacks yet.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: