Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Reputation Activity

  1. Like
    Czar reacted to jarto in components lose name - little IDE bug   
    Thank you. I'll add this to my work list.
  2. Like
    Czar reacted to Christian in TIniFile Question   
    omg, sorry i suppose i found the problem.
    ini := TIniFile.Create; ini.loadFromUrl('res/apps.ini', procedure() begin writeln(ini.ReadString('0','Url','')) end); ini.free Ini.free is executed before the value has been loaded. Sorry for the circumstances. 
  3. Like
    Czar reacted to jarto in Editing "Color" as a property   
    We are working on replacing the Object Inspector with a better one.
  4. Like
    Czar reacted to lynkfs in fetching files   
    There are afaik 3 ways to read external files directly from the client :
    using ajax / xmlhttprequest using the filereader using the fetch api 1: get xmlhttprequest
      var FHttp := TW3HttpRequest.Create;   FHttp.OnDataReady := lambda writeln(FHttp.responsetext); end;   FHttp.open('GET','res/textfile.txt');   FHttp.send(); 2: file input
      W3EditBox1.InputType := itFile;   W3EditBox1.Handle.ReadyExecute( procedure ()     begin       W3EditBox1.OnChanged := procedure(sender:TObject)         begin           var reader: variant;           asm @reader = new FileReader(); end;           reader.onload := lambda writeln(reader.result); end;           reader.readAsText(W3EditBox1.handle.files[0]);         end;     end); 3: fetch api
    var window   external 'window':   variant; window.fetch('res/textfile.txt')   .then(function(response:variant):variant begin     result := response.text();   end)   .then(procedure(myText:variant) begin     writeln(myText);   end); these fetch calls return a promise and the promise returns a response
    The fetch api is a mechanism which can replace the usual ajax calls. This api is primarily designed to act on network events. (see this post), but works for simple file fetching as well
    4: Variations of the above, see f.i. this one using webworkers
      var FileReader : variant := new JObject;   asm @FileReader = new Worker('filereader.js'); end;   FileReader.onmessage := procedure(e: variant)   begin     writeln(e.data);   end;   FileReader.postMessage('res/textfile.txt');     //read file through webworker (filereader.js)
    demo / project  (demo output is to console : ctrl+shift+i)
  5. Like
    Czar reacted to IElite in Radiogroup - change items text   
    W3RadioGroup1.RadioButtons[0].Label.Caption:= 'it does not work';
  6. Like
    Czar reacted to lynkfs in php   
    A web application ends up being encoded in html, js and css.
    php is a language which can be used to create these components, but more importantly can also be used within all 3 of these types of files.
    That gives some interesting possibilities.
    To make that happen, php needs to be activated serverside. Many server hosting environments come with php pre-installed.
    Activating php so that it can be used at the time of serving regular .html, .js or .css files by the browser depends on the type of server.
    Regular unix based servers make use of a .htaccess file which needs a line like
    AddHandler application/x-httpd-php5 .html .htm Windows servers have another mechanism
    1 - Using php within Smart
    Php can be invoked like this, where the php statements are inclosed in a <?php block.
    asm     var i = 0;     i = <?php echo 35; ?>;     alert(i); end; A practical use would be to include server side scripts normally accessed through a POST request (which eliminates a server round trip as well).
    The below code reads a MySqL database at form init
    procedure TForm1.InitializeForm; begin   inherited;   // this is a good place to initialize components var response : variant := new JObject; asm @response = <?php $link = mysql_pconnect("...domain...", "...user...", "...password...") or die("Could not connect"); mysql_select_db("...database...") or die("Could not select database"); $sql_statement = 'Select * from FishFacts'; $arr = array(); $rs = mysql_query($sql_statement); while($obj = mysql_fetch_object($rs)) { $arr[] = $obj; } echo '{"rows":'.json_encode($arr).'}'; mysql_close($link); ?>; end;   writeln(response.rows[0].Common_Name);   //Clown Triggerfish
    2 - Using php within Html files
    A (possibly) usefull example scenario would be to separate web-pages into a header.html, a regular Smart index.html and a footer file.
    php has an include mechanism, which can be used like so
    <body> <?php include "header.html" ?>   <script type="text/javascript">    /* This prevents the window being moved by touches,       to give the impression of a native app */     document.ontouchmove = function(e) { e.preventDefault(); }       </script>     <script type="text/javascript" src="main.js.php"></script> </body>
    3 - Using php within css files
    Similarly stylesheets can be scripted, something like this snippet where, within the stylesheet, the current date is checked which sets an image url
    <?php   $month = date('m');  $day = date('d');  if($month=='12' && $day=='25') {     $logoSrc = 'images/holidayLogo.png';  } else {     $logoSrc = 'images/logo.png';  } ?> h1 {  background: url(<?=$logoSrc?>) no-repeat; } Demo (of 1 and 2)
  7. Like
    Czar reacted to lynkfs in window component   
    demo works ok here
    The javascriptisch events used are
      //Move window   Header.handle.onmousedown := procedure(e: variant)   begin     Header.handle.style.cursor := 'move';     var saveX := e.clientX;     var saveY := e.clientY;     Header.handle.onmousemove := procedure(e: variant)     begin       self.left    := self.Left - (saveX - e.clientX);       self.top     := self.top - (saveY - e.clientY);       PrevSize     := TRect.CreateSized(left, top, width, height);       saveX := e.clientX;       saveY := e.clientY;     end;   end;   //   Header.handle.onmouseup := procedure(e: variant)   begin     Header.handle.onmousemove := null;                       //nullify mousemove     Header.handle.style.cursor := 'default';   end;   //   Header.handle.onmouseleave := procedure(e: variant)   begin     self.Parent.handle.onmousemove := header.handle.onmousemove;     self.Parent.handle.onmouseup   := procedure(e: variant)     begin       self.parent.Handle.onmousemove := null;     end;   end; will be interesting to compare using eventmanager. I agree that will probably be a better solution
  8. Like
    Czar reacted to jarto in window component   
    Something like this:
    var saveX, saveY: Integer; Header.OnMouseDown:=procedure(Sender: TObject; Button: TMouseButton; shiftState: TShiftState; x, y: integer) begin var Ctrl:=TW3CustomControl(Sender); Ctrl.Cursor:=crMove; saveX:=x; saveY:=y; end; Header.OnMouseMove:=procedure(Sender: TObject; ShiftState: TShiftState; x, y: integer) begin var Ctrl:=TW3CustomControl(Sender); if Ctrl.Cursor=crMove then begin Ctrl.MoveTo(Ctrl.Left-(saveX-x),Ctrl.Top-(saveY-y)); PrevSize:=Ctrl.BoundsRect; saveX:=x; saveY:=y; end; end; Header.OnMouseUp:=procedure(Sender: TObject; Button: TMouseButton; shiftState: TShiftState; x, y: integer) begin var Ctrl:=TW3CustomControl(Sender); Ctrl.Cursor:=crDefault; end;  
  9. Like
    Czar reacted to warleyalex in window component   
    OFF TOPIC -  "SMS Component design"
    Just things that crosses my mind, and I want to discuss. Please don’t see that as an attack to someones's work. 
    I really like SMS and the new possibilities.  We all want the best possible development experience result. 
    While the visual widgets/UI in SMS still is customizable (by user and developer). 
    I often spend more time on UI parts to realize the look and feel i want to have. I have to say here, one think that is very frustating for me is the SMS form designer
    I've spent a few minutes reflecting on this RAD approach and its form designer to create web app.
    Just drop components onto a form and set up at the objector inspector, the events and the properties. 
    All of the above is great and it will no doubt give us the same benefits as Delphi developers currently enjoy. 
    The compiler will auto generate the components for you, such as: 
    var    btn1: TButton;  btn1 := TButton.Create(Self);  btn1.Width := 121;  btn1.Top := 16;  btn1.Left := 536;  btn1.Height := 25;  btn1.Name := 'btn1';  btn1.OnClick := Self.btn1Click;  The UI part could be implemented on  top of TCustomComponent, both visual or non-visual components could be used. 
    "the window component" - it's great candidate hein! ...but what I really don't like this approach is when i.e. you
    drop "a visual component" onto form, you see "rectangule" drawing which represents the component itself you dropped.
    I can't seem to find anyway how to get the "live preview" on the SMS designer on those components I've created. 
    other thing is the "objector inspector" support for some custom properties.
    For instance, if the user choose 'Material' from the list, the Material CSS style should be applied to the component.
    type    TCustomStyle = array[1..3] of string; const    CustomStyle : TCustomStyle = ('iOS','Android','Material'); type   TMystyle  = (cssIOS, cssAndroid, cssMaterial); TToggleComponent = class(TW3CustomControl)   private     fMyStyle: TMystyle;     fCustomStyle : TCustomStyle;   published     property Mystyle: TMystyle Read fMyStyle Write fMyStyle default cssAndroid;     property CustomStyle: TCustomStyle Read fCustomStyle Write fCustomStyle; ...when I see at Object Inspector the property MyStyle : 0 (set to zero?). For the boolean type it shows the dropdown list.
    How can I create  a property of type String that will show a combo box in the object inspector with a predefined set of values the user could choose?
    This is very frustating for me It seems there's just a bit too much work involved to meet even baseline expectations. 
  10. Like
    Czar reacted to jarto in window component   
    @warleyalex Yeah, well, the problem you experience is because the current Object Inspector lacks features. We're in the process of replacing it with a better component, which should let you edit more properties. For example sets.
    The Object Inspector also needs a lot of work. The current design was based on the idea that we'd get the Chromium to render us a live preview that we could use to make the controls look realistic. However, there was some changes in Chromium that broke that feature. So we're currently thinking about what'd be the best way to proceed. Basically: Should we try to improve the current one or replace it with something better.
  11. Like
    Czar reacted to lynkfs in window component   
    Just in case anyone has a need for a window component.
    (multiple windows, movable, resizable, bringtofront, minimise, close, maximise)
  12. Like
    Czar got a reaction from jarto in UI layout   
    Loving the update. Only had a little play but it seems to be working as expected
  13. Like
    Czar reacted to lynkfs in css grid   
    Started to do some experiments with CSS Grid
    Basically CSS Grid is a grid component built into all modern browsers, including mobile. The good thing about it is it can be used as a simple grid, as a layout mechanism for forms or other components and can be used to be responsive to screen sizes.
    1) A simple grid.
     Since this is based on css, it can only be teased into life by manipulating the stylesheet. Either by just adding css to it manually or doing it in code :
    //add some styles in code   var s1 := #'   .TGrid {     display: grid;     grid-template-columns: repeat(3, auto);     grid-gap: 0.8em;   }';   document.styleSheets[document.styleSheets.length-1].insertRule(s1, 0); // s1 := #' .afirst { grid-column: 1; }'; document.styleSheets[document.styleSheets.length-1].insertRule(s1, 0); This snippet adds a grid class to the stylesheet and a class for the first column in this grid
    Fill up the grid, in plain html here, by adding cells as children :
      var s := '<div class="TGrid" id="mygrid">';                 for var i := 0 to 100 do begin     s := s + '<div class="afirst">row ' + inttostr(i+1) + '</div>'';   end;   s := s + '</div>';  
    This can be made into a regular component :
    var MyCSSGrid : TCSSGrid := TCSSGrid.Create(self);   MyCSSGrid.SetBounds(50,50,500,200);   MyCSSGrid.NrofColumns := 4;   For var i := 1 to 1000-1 do begin     MyCSSGrid.AddCell('row ' + inttostr(i), 1); //column 1     For var j := 2 to 4 do begin       MyCSSGrid.AddCell('cell[' + inttostr(i) + ',' + inttostr(j) + ']', j); //column 2-4     end;   end;   MyCSSGrid.Show;  
    A demo of such a component with 4 columns and 1000 rows
  14. Thanks
    Czar reacted to lynkfs in reCaptcha   
    Its actually simpler than I thought - the Google documentation is esoteric at best
    the reCaptcha widget produces some sort of response when the user clicks the checkbox (g-rechapta-response). This response is POST-sent (either by form or by xmlhttprequest) to a back-end server side script.   this script queries the "https://www.google.com/recaptcha/api/siteverify" url, which gives a response either ok or not ok This server-side script can be f.i. node.js or php based
    In php something like this (recaptchajax.php)
    <?php $secret="6Lf8I....secret key.....BrulLk"; $response=$_POST["captcha"]; $verify=file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret={$secret}&response={$response}"); $captcha_success=json_decode($verify); if ($captcha_success->success==false) { //This user was not verified by recaptcha. echo 'false'; } else if ($captcha_success->success==true) { //This user is verified by recaptcha echo 'true'; } ?> and the invocation, with a proper POST xmlhttprequest :
    unit Form1; interface uses System.Types, System.Types.Convert, System.Objects, System.Time, System.IOUtils, System.Device.Storage, SmartCL.System, SmartCL.Time, SmartCL.Graphics, SmartCL.Components, SmartCL.FileUtils, SmartCL.Device.Storage, SmartCL.Forms, SmartCL.Fonts, SmartCL.Theme, SmartCL.Borders, SmartCL.Application, SmartCL.Controls.Panel, SmartCL.Net.Http, ECMA.Json, SmartCL.Controls.Button; type TForm1 = class(TW3Form) private {$I 'Form1:intf'} protected procedure InitializeForm; override; procedure InitializeObject; override; procedure Resize; override; procedure RetrieveCaptcha(Sender: TW3HttpRequest); Button1 : TW3Button; end; var grecaptcha external 'grecaptcha': Variant; implementation { TForm1 } procedure TForm1.InitializeForm; begin inherited; // this is a good place to initialize components Var Captcha : TW3Panel := TW3Panel.Create(self); Captcha.SetBounds(50, 100, 304+4, 78+4); Button1 := TW3Button.Create(self); Button1.SetBounds(50, 200, 100, 30); Button1.Caption := 'submit'; var Script := browserapi.document.createElement('script'); Script.src := 'https://www.google.com/recaptcha/api.js'; browserapi.document.head.appendChild(Script); Script.onload := procedure begin Captcha.innerHTML := '<div class="g-recaptcha" data-sitekey="6Lf8I6....site key.....WY5hq"></div>'; Button1.onclick := procedure(sender:TObject) begin var FHttp := TW3HttpRequest.Create; FHttp.OnDataReady := RetrieveCaptcha; FHttp.open("POST","https://www.lynkfs.com/Experiments/reCaptcha/www/lib/recaptchajax.php"); FHttp.RequestHeaders.Add("Content-type","application/x-www-form-urlencoded"); var mycaptcha := "captcha=" +grecaptcha.getResponse(); FHttp.send(mycaptcha); end; end; end; procedure TForm1.RetrieveCaptcha(Sender: TW3HttpRequest); begin writeln(JSON.parse(Sender.ResponseText)); //console : either 'true' or 'false' If JSON.parse(Sender.ResponseText) = true then Button1.Caption := 'OK'; If JSON.parse(Sender.ResponseText) = false then Button1.Caption := 'Spam'; end; procedure TForm1.InitializeObject; begin inherited; {$I 'Form1:impl'} end; procedure TForm1.Resize; begin inherited; end; initialization Forms.RegisterForm({$I %FILE%}, TForm1); end. Demo url as before
  15. Like
    Czar reacted to lynkfs in reCaptcha   
    this is a finnicky api, which needs multiple steps to figure this out.
    Step1 : display the captcha widget
    It is not just the case of adding the 'https://www.google.com/recaptcha/api.js' file to the index/template file, as it clashes with a standard smart project. Don't know why, something to do with timing
    So workaround #1 : read the api file in code (maximum control) and set up a TPanel as the widget control
    procedure TForm1.InitializeForm; begin   inherited;   // this is a good place to initialize components   Var Captcha : TW3Panel := TW3Panel.Create(self);   Captcha.SetBounds(50, 100, 304+4, 78+4);   var Script := browserapi.document.createElement('script');   Script.src := 'https://www.google.com/recaptcha/api.js';   browserapi.document.head.appendChild(Script);   Script.onload := procedure   begin     writeln('loaded');     Captcha.innerHTML := #'       <form action="?" method="POST">         <div class="g-recaptcha" data-sitekey="6Lf8I...site key ...WY5hq"                                  data-callback="mycallback"></div>         <br/>         <input type="submit" value="Submit">       </form>     ';   end; end; The captcha widget is 304 * 78, so we'll embed it in a standard T(W3)Panel.
    The innerHtml solution is not very elegant (but works). I'll see if this can be changed to a normal post xmlhttprequest later.
    Demo so far
  16. Like
    Czar got a reaction from IElite in reCaptcha   
    I am trying to implement a "i am not a robot" into my website
    Basic HTML/JS looks like the following with a second step required to validate it server side.
    <script src="https://www.google.com/recaptcha/api.js"></script> HTML:
    <div class="g-recaptcha" data-sitekey="YOUR_KEY" data-callback="correctCaptcha"></div> JS:
    var correctCaptcha = function(response) { alert(response); }; I thought I could manage getting it to wok in SMS but I got very lost. I couldn't find examples that seemed to be a parallel challenge.
    It would be great to have some clear tutorial or case study to show how it is possible to integrate JS
    and or it would be good to a have google recaptcha component
    info link: https://stackoverflow.com/questions/27902539/how-can-i-validate-google-recaptcha-v2-using-javascript-jquery
  17. Like
    Czar reacted to lynkfs in Responsive Design   
    Responsive design in essence consists of 2 measures :
    style all components as best as possible depending on screen size (larger buttons on mobile, proportional font sizing etc) tweak the layout of forms so that it works best on any given screen size 1) Screen size dependent styling can be done in code and/or is done as other frameworks do by including media queries in the stylesheet. Media queries basically activate different parts of a stylesheet depending on the actual screen size. Smart doesn't implement this in its shipped stylesheets, but there is no reason it can't be done. Just a bit of work.
    2) Tweaking the form layout in Smart is possible by
    doing it in code depending on screensize and orientation - a bit of a pain really using the Layout Manager using some css grid framework or ui kit. For website development I've used the Frow framework quite a bit, but there are many others. using anchors and the CSS grid (which is basically the topic of this post) The new anchors are fantastic, but don't really help in responsive design. Browser window resizing doesn't proportionally resize anchored components. That is unless they are dimensioned depending on screen size beforehand :
      var W3Panel0 : TW3Panel := TW3Panel.Create(self);   W3Panel0.Left   := trunc(browserapi.window.innerWidth*0.05);   W3Panel0.Top    := trunc(browserapi.window.innerHeight*0.05);   W3Panel0.Width  := trunc(browserapi.window.innerWidth*0.9);   W3Panel0.Height := trunc(browserapi.window.innerHeight*0.10);   W3Panel0.Anchors := [akLeft, akRight, akTop];   //   var W3Panel1 : TW3Panel := TW3Panel.Create(self);   W3Panel1.Left   := trunc(browserapi.window.innerWidth*0.05);   W3Panel1.Top    := trunc(browserapi.window.innerHeight*0.15);   W3Panel1.Width  := trunc(browserapi.window.innerWidth*0.9);   W3Panel1.Height := trunc(browserapi.window.innerHeight*0.70);   W3Panel1.Anchors := [akLeft, akRight, akTop, akBottom];   W3Panel1.NativeScrolling := true;   //   var W3Panel2 : TW3Panel := TW3Panel.Create(self);   W3Panel2.Left   := trunc(browserapi.window.innerWidth*0.05);   W3Panel2.Top    := trunc(browserapi.window.innerHeight*0.85);   W3Panel2.Width  := trunc(browserapi.window.innerWidth*0.9);   W3Panel2.Height := trunc(browserapi.window.innerHeight*0.10);   W3Panel2.Anchors := [akLeft, akRight, akBottom]; As an example the code above produces a header (always on top), a footer (always on the bottom) and a scrollable body inbetween with some proportional margins.

    The good thing is it works well on all screen sizes, and even on orientation changes, without having to code anything else.
    Instead of using a grid system with media queries, or doing it in code, it is also possible to use the built-in css grid to get a responsive design. Much easier, see article. If I just plonk the css and html of the first example in that article into the structure above, this is how it ends up looking :
    Resize browser window to see this in effect (or see it in the responsinator)
    Not the end-all of all possible responsive design options, but it may fit the bill sometimes.
    Note  : the built-in chrome browser doesn't understand the css grid, so execute from file or server.
  18. Like
    Czar reacted to jarto in Development updates   
    New update available in the development-channel:
    Anchors and Align-support to the RTL. Bug fix to BoundsRect Please note that anchors can only be set in code at the moment. The next step is to add support for setting the anchors and align in the IDE's designer as well. Currently Align actually can be set in the Object Inspector, but the designer does not show the result by aligning components.
  19. Like
    Czar reacted to jarto in UI layout   
    The development-channel contains a new update that adds Align and Anchor-support in the RTL. We still have some work to do to get the Visual Designer and Object Inspector to support these properly. While we work on that, you can still use these by setting anchors in code. Align can actually be set in the Object Inspector, but do note that setting the alignment does not make any visual changes in the Visual Designer.
    I'm going to be travelling for a bit more than a week.. During that time I'll be able to participate in this forum but can't make any changes or bug fixes. If you happen to find situations when Anchors and Align does not work properly, please post examples. I'll be happy to have a look when I return from my trip.
  20. Thanks
    Czar reacted to jarto in Request for feedback: Changing class names in the RTL   
    As you all know, almost all classes in Smart Mobile Studio are named TW3Something. For example: TW3Button, TW3Panel etc. The decision to do that was done during the first stages of development of Smart Mobile Studio. However, there's no technical reason why the "W3" has to be there. So basically, we could rename all the components and classes to be more compatible with Delphi and making code sharing and porting easier.
    I wrote a program yesterday evening that analyzed and renamed all the classes and records that start with TW3 in the RTL. There are 849 of them to be precise. The app also renamed themes and the IDE code, so that I was able to compile a new IDE and make my first app with TForm and TButton etc. It all worked nicely, except that the chart component is causing a bit of trouble. It's using TPanel and a couple of other classes that would cause conflicts.
    I'd be able to add remapping functions to the IDE so that you could load an old project and all the TW3Whatever-classes would be converted to TWhatever. But if you have your own components using names like TPanel, TButton, TList, TStringList, they would cause trouble. Question is: Do you have them and how much of code like this do you have?
    Any thoughts?
  21. Haha
    Czar got a reaction from jarto in UI layout   
  22. Like
    Czar reacted to jarto in UI layout   
  23. Like
    Czar got a reaction from lynkfs in UI layout   
    Being able to make more complex UI that works on all devices will make life much much easier
    Looking forward to finished product.
  24. Haha
    Czar reacted to DavidRM in UI layout   
    Now add some TW3Labels to your layout demo and experience Real Pain. 😉
  25. Like
    Czar reacted to jarto in UI layout   
    Working on this now. Align in the RTL is at pretty good shape already.
  • Create New...