Jump to content


Popular Content

Showing content with the highest reputation since 04/21/2018 in all areas

  1. 6 points

    Smart Mobile Studio 3.0 is released!

    One year of hard work, lots of changes, new features and bug fixes. But here it is! Release announcement: https://smartmobilestudio.com/2018/07/20/smart-mobile-studio-3-0-released/ Most of you have already been using beta-versions, that are really, really close to this release. The last bit was to fix the cors-problem in the Images and to add the Smart Desktop source code to the Featured Demos. We've also set up a live demo of the Desktop to showcase what Smart Mobile Studio and JavaScript can do: desktop.smartmobilestudio.com Big thanks to everybody here, who have helped by testing, suggesting improvements and reporting bugs.
  2. 5 points

    Smart Mobile Studio 3.0.1 is released!

    Smart Mobile Studio 3.0.1 is released This is the first release since 3.0. Biggest new feature is TW3LeafletMap, which lets you use OpenStreetMap. As it does not need API keys (like TW3GoogleMaps), it’s really fast and easy to use: – Create a project – Add a TW3LeafletMap -control on the form – Set AutoCreateMap to true on the map control Changes since 3.0 8.11.2018 RTL: – EventManager: – Add procedure AllowDefaultAction, that can be called from OnClick when the default action should happen. For example: To let the virtual keyboard to pop up from OnTouch. – Bug fixes: – Native scrolling was prevented if scrolling was done from an unknown element. – Prevent an extra OnClick from being fired on mobile devices. – TW3ListView: Bug fix to resizing of items. – Bug fixes to GeoLocation. Also update the Geolocation demo. – Deprecate PhoneGapAPI’s JGeolocation functions. SmartCL.GeoLocation.pas should be used instead. – Fix slider so that OnMouseDown, OnMouseUp and OnMOuseMove can be used. – TW3TabControl Tab’s OnShow was sent twice for the first tab – SmartCL.RegEx moved to System.RegEx. Also fixed TW3RegEx.Exec to return a proper empty array instead of nil. – Bug fix to Chart: TSeriesData.Refresh now also updates the X axis – TW3Grid: – Added TW3ImageColumn – Add Alignment-property to TW3ColumnHeader – Added a new OnCellControlCreated-event, which fires when a button, toggle, progress bar or image is created. Makes it possible to change properties of the control easily. – Added support for OpenStreetMap using the Leaflet library: – New control: TW3LeafletMap – New featured demo: LeafletMap IDE/Compiler: – Fixed search path compilation issues – Relative and absolute paths are working now – Compiler is updated when search path is modified in options – $I will look for include file in the project folder first – $R supports absolute paths, wildcards, folder name extension and ($Libraries) macro – Fix exceptions in Search – Upgrade to UPX 3.95 23.7.2018 – SmartCL.Effects: Properly handle padding and margins while doing effects. 22.7.2018 – Fix to css-files for selected text in TW3Edit and TW3Memo Release notes and installers: https://smartmobilestudio.com/2018/11/08/smart-mobile-studio-3-0-1-released/ Note that you can also use SmartUpdate to keep your portable installation up to date. Instructions on using that are in the link above.
  3. 5 points

    Font Demo

    in project options add a webfont (see https://jonlennartaasenden.wordpress.com/2017/10/04/webfonts-in-smart-mobile-studio/) W3Memo1.Font.Name := 'Tangerine'; W3Memo1.Font.Style := [fsItalic]; W3Memo1.Font.Size := 48; W3Memo1.Font.Weight := 'bold'; In this case I added Font 'Tangerine' (see also https://developers.google.com/fonts/docs/getting_started)
  4. 4 points


    Google has implemented a new service : web.dev Basically this measures some indicators of any url using their LightHouse tool. These indicators are grouped into Performance, Accessibility, Best Practices and SEO I created a minimal SMS project with only a single image on a form and run the test : https://web.dev/measure and url : https://www.lynkfs.com/Experiments/lighthouse/www/ This gives scores of 95 / 27 / 77 / 89 for Performance, Accessibility, Best Practices and SEO respectively There are a couple of really simple things which will up these scores considerably. Scores were upped to 96 / 74 / 92 / 100 when doing this : Best Practices from 77 to 92 : 1) in project options/linker unclick 'generate cache manifest' (deprecated) Performance from 95 to 96 : 1) in project options/linker unclick 'store CSS as a separate file' (95 to 96) 2) add async to <script async src="lib/polyfill.custom.events.js" type="text/javascript"></script> in the index.html template SEO from 89 to 100 : 1) add meta description tag to the head of index.html <meta name="Description" content="Put your description here."> Accessability from 27 to 74 : 1) add alt attribute to images, even if only '' : W3Image1.handle.setAttribute('alt', ''); (27 to 58) 2) add lang="en" to html element in index.html template : <html lang="en"> (58 to 74) 3) tabindex=1 for TW3Display and TW3DisplayView. Should be 0 ? run test again on url : https://www.lynkfs.com/Experiments/lighthouse2/www/ to see these results All of the above could be made part of the standard settings for a new visual project
  5. 4 points

    console override

    redirecting 'console.log' or 'writeln' output proves to be very simple : have a form with a Memo component : procedure TForm1.InitializeObject; begin inherited; {$I 'Form1:impl'} W3Memo1.Text := 'Console.log : ' + #10; browserapi.console.log := procedure(text:variant) begin W3Memo1.Text := W3Memo1.Text + #10 + text; end; writeln('aaa'); browserapi.console.log('bbb'); end; all subsequent calls to writeln and/or console.log are now redirected to the Memo component.
  6. 4 points

    console override

    This mechanism can be used to redefine more built-in functions. Funny. The code below redefines 'ShowMessage' to redirect its contents to a Memo : procedure TForm1.InitializeObject; begin inherited; {$I 'Form1:impl'} W3Memo1.Text := 'ShowMessage : ' + #10; browserapi.window.alert := procedure(text:variant) begin W3Memo1.Text := W3Memo1.Text + #10 + text; end; ShowMessage('ccc'); browserapi.window.alert('ddd'); end; or combine the two and redefine 'ShowMessage' to redirect its contents to the 'Writeln' function, which in its turn is redirected to the Memo : procedure TForm1.InitializeObject; begin inherited; {$I 'Form1:impl'} W3Memo1.Text := 'Console.log : ' + #10; //WriteLn redirects to Memo browserapi.console.log := procedure(text:variant) begin W3Memo1.Text := W3Memo1.Text + #10 + text; end; //ShowMessage redirects to WriteLn browserapi.window.alert := procedure(text:variant) begin writeln(text); end; writeln('aaa'); browserapi.console.log('bbb'); ShowMessage('ccc'); browserapi.window.alert('ddd'); end;
  7. 4 points

    Development updates

    17.11.2018 RTL: Changes to handling of Cursor: Style definitions moved from basic html elements to control styles GetCursor and SetCursor can now be overridden Bug fixes to how many controls handle cursor. Especially TW3Label. Themes: Add missing styles TW3CheckBox, TW3CheckMark, TW3RadioButton, TW3RadioToggle and TW3RadioGroup Two new backgrounds: TW3DecorativeListItemBackground and TW3TransparentBackground RTL optimizations to creation of controls, GetBoundsRect, SetBounds, MoveTo and SetSize. Bug fix to SmartCL.Graphics.pas: Changing of canvas font, size and styles did not work. Bug fix to System.DateUtils.DecodeDate. IDE: Delete key works now Search dialog and other dialogs. Bug fix: Internal Browser Window showed only a white screen if Execute was clicked while it was open. Compiler: Now(), EncodeDate() and EncodeTime() returns now the same values as Delphi and FPC All time/date -functions fixed to work with the new TDateTime-values
  8. 4 points

    DayOf reporting false value

    I dug around and found out that I actually can fix those "buggy" functions in the compiler without having to upgrade to a newer version of DWScript. I only have IncMonth to fix any more. The root cause of the problem is the way javascript dates work. When you build a date from day, month and year, the result depends on your time zone. I guess it builds the date as UTC and then views it from your location. So, while it's 01.12.2018 at 00:00:00 in London, it's still 30.11.2018 in USA. And when you call DayOf on that, you get 30 instead of 1. This affects about 10 other functions as well, including FormatDateTime and DateTimeToStr and TimeToStr. I'll make sure to test this all properly and then release an update. Once it's done, I'm super happy to get rid of these problems.
  9. 4 points


    I'm sad to see Jon leave his baby like this, but I do respect his decision. What I can say is, that SMS is not dying here. I've been waiting a few weeks already to push a new update, but have not been able to get any answers from Jon, if he'd also want to include some changes. I believe things look worse to you guys than they really are. A lot of RTL work and especially bug fixes was done by me during the last year and almost all the IDE improvements and bug fixes by Primoz. Jon did pretty much all the NodeJS work, so we'll miss him most there. If I look at this optimistically, Jon's donating his shares to two young and talented Delphi programmers is a very nice thing and may give them a possibility to spend more time on SMS. But hey, hang on there and lets hope that this divorce will not be too ugly.
  10. 4 points
    I'd rather do it like Delphi and Lazarus: Keycode as a var parameter and setting it to #0 would cancel. However, that would break backwards compatibility of SMS code just as any other new parameters would do. If you guys don't see it as a big problem, we could do it in a future version. Let me know what your thoughts are.
  11. 4 points

    Scroll bar bug

    This was a weird bug that required changes in SynEdit code itself. May be a Delphi bug even. But I got it fixed and it will be in 3.0
  12. 4 points
    @rshotbolt Here are some resources that might help you out. I like the first one as it explains the precedence and how each overrides the others. Playing with the design 03.06.2013 https://smartmobilestudio.com/2013/06/03/playing-with-the-design/ Smart Mobile Studio and CSS: part 1 October 9, 2017 https://jonlennartaasenden.wordpress.com/2017/10/09/smart-mobile-studio-and-css-part-1/ Smart Mobile Studio and CSS: part 2 https://jonlennartaasenden.wordpress.com/2017/10/11/smart-mobile-studio-and-css-part-2/ Smart Mobile Studio and CSS: part 3 https://jonlennartaasenden.wordpress.com/2017/10/12/smart-mobile-studio-and-css-part-3/ Smart Mobile Studio and CSS: part 4 https://jonlennartaasenden.wordpress.com/2017/10/18/smart-mobile-studio-and-css-part-4/ Themes and styles https://smartmobilestudio.com/documentation/getting-started/themes-and-styles/ Working with controls, the boxing model 05.01.2012 https://smartmobilestudio.com/2012/01/05/working-with-controls-the-boxing-model/ Hidden stylesheets with Smart Pascal August 13, 2014 https://jonlennartaasenden.wordpress.com/2014/08/13/hidden-stylesheets-with-smart-pascal/ HTML5 Attributes, learn how to trigger conditional styling with Smart Mobile Studio November 8, 2017 https://jonlennartaasenden.wordpress.com/2017/11/08/html5-attributes-learn-how-to-trigger-conditional-styling-with-smart-mobile-studio/
  13. 3 points

    component creation

    Let me start by commenting on Jon's blog post. For the most part it's accurate, but he makes a small mistake with the "common mistake": ObjectReady() calls ReadySync() which actually does check if the child elements are ready. So, when you override ObjectReady(), the child controls you created in InitializeObject should also be ready. And when ObjectReady() happens, it also triggers the first Resize for the component. Let me comment on these three lines: Users don't need to write as complex checking routines as ReadySync() is. Let the RTL take care of that. It does it very well. However, do always check your controls in Resize(). Minimum is to check that they are not nil. And if you want to be extra sure, check the ready state too. And by far the best way to do this all is pretty simple: In your Resize() procedure, always check if your controls are ready If they are not, call Self.Invalidate(). Do not call Resize() directly or via TW3Dispatch as Jon suggests. Think about Invalidate() as a request for a new Resize(). It calls an internal procedure in the RTL called ResizeWhenReady() and it does exactly what it says: It will call Resize() with a short delay and it will check that any new child components you added after the previous resize are also ready. The delay helps to minimize the number of Resize()-calls and it simply makes sense to not let a Resize() happen before your child components are ready. I think Jon is explaining how the RTL did work before I got involved. It makes sense to rely on ObjectReady() when you have a simple, static control but when you have a control like TW3ListBox, it does not work at all as the TW3ListBox dynamically creates new child components while you use the control.
  14. 3 points

    Development updates

    Now it should be possible for everyone to use SmartUpdate with the development-channel.
  15. 3 points


    I would have a look at fully developed open source calendar js libraries which can be embedded in your sms app as is (i.e. https://fullcalendar.io/) make your own based on an opensource css-only component. These components usually have no js component at all, just html and css. The css bit you can copy into your stylesheet if you like the look and feel and the html can be used to recreate the logic behind it all. (i.e. https://freefrontend.com/css-calendars/) make your own from scratch my personal approach would be the middle one (unless you find a js library which does exactly what you need) cheers
  16. 3 points
    Recently Microsoft Security Essentials has detected a Trojan:Win32/Azden.B!cl. in Smart Mobile Studio v3.0 smartms.exe binary, and this detection has been removed form malware definitions. Big&Many Thanks to jarto how to submit files to Microsoft in order to remove false malware detection. Report from Microsoft Submission details smartms.exe Submission ID: 43e9c4db-2060-431a-a8d8-17bbddecf3be Status: Completed Submitted by: i**********@msn.com Submitted: Oct 2, 2018 4:44:50 PM User Opinion: Incorrect detection Analyst comments: Hello Kosta ***, Thank you for your inquiry. We have reviewed the file and we have removed the detection. Please try the following steps to clear cached detections and obtain the latest malware definitions. 1. Open command prompt as administrator and change directory to c:\Program Files\Windows Defender 2. Run “MpCmdRun.exe -removedefinitions -dynamicsignatures” The latest definition is available for download here: https://www.microsoft.com/en-us/wdsi/definitions Best regards, Windows Defender Response Thank you jarto Thank you lennart. Best regards Kosta.
  17. 3 points

    Send an email ?

    This is a 2-step process 1) see this post and follow at least the first steps. Basically establish the link between your app, googles api's and your gmail account. For option 2a(below) you need at least an api-key and clientId, for option 2b you need the full oauth2 gamut including tokens 2) then do one of the following 2a) make use of Googles javascript client library for gmail <!DOCTYPE html> <html> <head> <title>Send email using gmail API</title> <meta charset='utf-8' /> </head> <body> <p>Send email using gmail API.</p> <!--Add buttons to initiate auth sequence and sign out--> <button id="authorize-button" style="display: none;">Authorize</button> <button id="signout-button" style="display: none;">Sign Out</button> <div id="content"></div> <script type="text/javascript"> var apiKey = '********2qOeiRlg2humU4YifLyNqt2TrWR2kGk'; var discoveryDocs = ["https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest"]; var clientId = '********7354-7kp9br0phbsdfkcsilu660u7uq9p6tqs.apps.googleusercontent.com'; var scopes = 'https://www.googleapis.com/auth/gmail.send'; var authorizeButton = document.getElementById('authorize-button'); var signoutButton = document.getElementById('signout-button'); function handleClientLoad() { // Load the API client and auth2 library gapi.load('client:auth2', initClient); } function initClient() { gapi.client.init({ apiKey: apiKey, discoveryDocs: discoveryDocs, clientId: clientId, scope: scopes }).then(function () { // Listen for sign-in state changes. gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus); // Handle the initial sign-in state. updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get()); authorizeButton.onclick = handleAuthClick; signoutButton.onclick = handleSignoutClick; }); } function updateSigninStatus(isSignedIn) { if (isSignedIn) { authorizeButton.style.display = 'none'; signoutButton.style.display = 'block'; makeApiCall(); } else { authorizeButton.style.display = 'block'; signoutButton.style.display = 'none'; } } function handleAuthClick(event) { gapi.auth2.getAuthInstance().signIn(); } function handleSignoutClick(event) { gapi.auth2.getAuthInstance().signOut(); } // Load the API and make an API call. Display the results function makeApiCall() { const message = "From: lynk@gmail.com\r\n" + "To: nico@hotmail.com\r\n" + "Subject: Subject of this email\r\n\r\n" + "with body text here"; // The body needs to be base64url encoded. const encodedMessage = btoa(message) //but google style, replacing a couple of characters extra const reallyEncodedMessage = encodedMessage.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '') gapi.client.gmail.users.messages.send({ userId: 'me', resource: { raw: reallyEncodedMessage } }).then(function () { console.log("done!")}); } </script> <script async defer src="https://apis.google.com/js/api.js" onload="this.onload=function(){};handleClientLoad()" onreadystatechange="if (this.readyState === 'complete') this.onload()"> </script> </body> </html> 2b) or make an ajax call (post) to https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send and attach a "raw" parameter in the request body with the base64 encoded email as above. I'll "Smart" both of these up a bit when time permits
  18. 3 points
    New update available with SmartUpdate in both alpha- and beta-channels. The update contains lots of bug fixes to the IDE. Some are smaller, but the most important deals with debugging and breakpoints. With this update, breakpoints finally work as they should. The changes to background compilation also makes the IDE a lot smoother to use. We also went through all the demos, fixed and improved a bunch of them and added two new ones. Before updating, please delete the "Featured Demos" -folder to make sure that no old demos will remain after the update. Changelog: 15.7.2018 RTL: - ShowModal: Trigger a cancel if the user clicks on the opaque background. - Bug fixes to Scrollbars - Changed padding in all themes. - Previously all controls had default padding (usually 2px), including div. - Now only known controls have the default padding. - Bug fix to TW3Image.LoadFromStream() IDE: - Bug fixes and improvements to background compilation. - Fixes problems with setting breakpoints in the SMS IDE. - If debugging with breakpoints, code obfuscation and packing is switched off. - If execute was set to a browser, instead of embedded Chrome, closing the debugger window caused an exception. - Fix "code painting bug while scrolling" in SynEdit. - Color picker to work with styled application. Demos: - Added: - https server demo - ThemeView demo - Bug fixes and improvements to many demos.
  19. 3 points

    compiled procedures

    Every now and then (not often) it is worthwhile to check what a compiled function actually looks like. An easy way to do that is to use the toString method function test(a:string): string; begin result := 'Da'+a; end; Procedure TForm1.ListProc; begin console.log(test('da')); //"Dada" asm console.log( (@test).toString() ); end; //lists compiled external function 'test' asm console.log( (this.ListProc).toString() ); end; //lists compiled procedure TForm1.ListProc asm console.log( (this.@InitializeForm).toString() ); end; //lists compiled procedure TForm1.InitializeForm end; which results in "Dada" function test(a) { return "Da"+a; } function (Self) { console.log( test("da") ); console.log( (test).toString() ); console.log( (this.ListProc).toString() ); console.log( (this.InitializeForm).toString() ); } function (Self) { TW3Form.InitializeForm(Self); }
  20. 3 points
    WebWorkers and Flow Based Programming It has been a while since I got as excited as I was when I read J.Morrison's book "Flow-Based Programming: A New Approach to Application Development - 2nd edition". This post is not meant to give an overview of FBP, but if someone is interested, the first edition of his book is available online for free. FBP utilises independantly running processes which are wired together in an assembly line type of arrangement. The main advantages are that each process runs on demand rather than on availability, components can easily be re-wired to implement changes in requirements and there are possibilities for extensive component re-use. I was in the process of porting this framework to Smart, when I realised that javascript and concurrently running processes is not an easy match. Basically all js code in the browser executes in the same thread, and time-slicing mechanisms like setTimeout (used in the framework I was porting) doesn't enable real concurrent processing. However there are 2 exceptions to escape the single-threadedness : IFrames and webworkers. Both implement runtimes separate from the main thread and have their own heap, stack and message handling mechanism. The similarities between the FBP and shared webworker specs are (more than) striking, so this post is about having a go at implementing FBP using webworkers. Technically - processes (fbp) can be implemented through shared webworkers - connections between processes (fbp) can be implemented using channels (webworker to webworker, buffered) - ports (fbp) can be implemented using ports (webworker) - reading/writing of information packets's (fbp) can be implemented using messaging (webworker) - information packet handling (fbp) can be implemented using the transferable interface (webworker) The demo chosen is a variation of the 'Galaxy Clock' project in the featured-demo's section. The variation being that the 'single motor' driving the 3 hands of the clock (hr, min, sec) is replaced by 3 separate 'motors', each driving one of the hands and each one operating in its own thread. The architecture of this demo : a scheduler webworker receives the current local time when a button is clicked in the main program. It transfers the time-elements to each of the other web-workers through the channels created. These other webworkers in their turn update the main project at appropriate intervals. The result of this rather peculiar architecture. The hr/min/sec displays are purposely not synchronised and are all running at 10x normal clock-speed.
  21. 3 points
    Thank you. I just updated the download -page to point to the latest beta-download. Also added instructions on how to do a portable installation.
  22. 3 points

    Smart Mobile Studio 3.0.0 beta2 is released

    Good news: A new update is available in the alpha- and beta-channels. Run SmartUpdate in the portable installation to get it. I spent some time digging deep into the IDE bugs and found and fixed three Designer bugs. Two of the bugs happened if you removed a control that had subcontrols. The cleanup was not done properly, which resulted in the IDE referring to freed objects. The third designer bug happened when you were drawing a new component into another one, which was not active in the designer. At that point the parent component was moving at the same time as you were drawing the rubberband rectangle for the new component. Happy to see that one gone. The update also contains a possibility to move the black console window's position in the integrated debugger. Just right click on the console and select "Toggle Console Position".
  23. 3 points
    in the smartcl.system unit you'll find the browserapi classes. use them like var URL := browserapi.window.location.href; or alternatively, I usually set a snippet like below in an interface section var document external 'document': variant; var window external 'window': variant; var console external 'console': variant; which gives me references to these objects without having to rely on asm sections : var URL := window.location.href;
  24. 3 points

    Grid, listbox or listview responsive

    I am working on a new grid, which is built on TW3ListBox. Do you need the columns to be resizable by the user (mouse and touch) or is code enough?
  25. 3 points


    It took me a while to get my head around the concept of webhooks. These have been around for 10 years or more but there is almost no to-the-point info or 'webhook-for-dummies' article on the web available. Webhooks are basically a notification system between disparate systems or servers, where the notifications are based on Http (XmlHttpRequests), so no messaging protocols or middleware software necessary. Like this : In this example there is a service which exposes changes in stock-prices. This service also has an api which allows applications to subscribe to this service (1). Subscription involves providing the url of the application-server. When a stock-price change event occurs, the service POST's a HttpRequest to the url of the server with a payload of the new price (2a) The server responds with a simple OK (2b) and initiates an action towards the client. This action can be maybe sending an email, or just sending a socket-message to the client (3) which allows the client to update its db or user-interface Setting this up in SMS takes a bit of effort as the servers need to have publicly accessible urls. Meaning nodejs servers have to be hosted somewhere (Heroku, Google Cloud). Doable I think.