Archive
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
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.
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]
Recent
The vatican vault
- January 2022
- October 2021
- March 2021
- November 2020
- September 2020
- July 2020
- June 2020
- April 2020
- March 2020
- February 2020
- January 2020
- November 2019
- October 2019
- September 2019
- August 2019
- July 2019
- June 2019
- May 2019
- April 2019
- March 2019
- February 2019
- January 2019
- December 2018
- November 2018
- October 2018
- September 2018
- August 2018
- July 2018
- June 2018
- May 2018
- April 2018
- March 2018
- February 2018
- January 2018
- December 2017
- November 2017
- October 2017
- August 2017
- July 2017
- June 2017
- May 2017
- April 2017
- March 2017
- February 2017
- January 2017
- December 2016
- November 2016
- October 2016
- September 2016
- August 2016
- July 2016
- June 2016
- May 2016
- April 2016
- March 2016
- January 2016
- December 2015
- November 2015
- October 2015
- September 2015
- August 2015
- June 2015
- May 2015
- April 2015
- March 2015
- February 2015
- January 2015
- December 2014
- November 2014
- October 2014
- September 2014
- August 2014
- July 2014
- June 2014
- May 2014
- April 2014
- March 2014
- February 2014
- January 2014
- December 2013
- November 2013
- October 2013
- September 2013
- August 2013
- July 2013
- June 2013
- May 2013
- February 2013
- August 2012
- June 2012
- May 2012
- April 2012
You must be logged in to post a comment.