Jump to content

lynkfs

Moderators
  • Content Count

    740
  • Joined

  • Last visited

  • Days Won

    146

Reputation Activity

  1. Like
    lynkfs reacted to DavidRM in Node.JS Game Loop   
    Here is my Smart Mobile Studio adaptation of the Node.JS "node-gameloop" module.
    My primary modification was some code to make the *next* interval line up with the desired number of ms per tick. I also tightened the window for choosing SetTimeout vs SetImmediate.
    I needed this to provide the beating heart of Paintball Net's simulation engine. Which, sure, only beats 10 times per second, but I wanted it to be as accurate as possible. ūüôā
    -David
    unit UPBNGameGameLoop; interface uses System.Types, System.Types.Convert, System.Time, System.Streams, System.Reader, System.Writer, System.Device.Storage, SmartNJ.System, SmartNJ.Streams, SmartNJ.Device.Storage, SmartNJ.Application, NodeJS.Core; var GameLoopActive: boolean; type TGameLoopCallback = procedure(delta: float); procedure StartGameLoop(update: TGameLoopCallback; msInterval: integer); procedure StopGameLoop; implementation procedure SetImmediate(const Entrypoint: TProcedureRef); external 'setImmediate'; const Seconds2Nano = 1e9; Nano2Seconds = 1 / Seconds2Nano; MS2Nano = 1e6; Nano2MS = 1 / MS2Nano; var _loopProc: TGameLoopCallback; _loopLengthHR: float; _loopPrevHR, _loopTargetHR: float; function GetHRTime: float; var hrTime: Variant; begin // I need a more up-to-date node to use the bigint() function. // asm // @Result = process.hrtime.bigint(); // end; asm @hrTime = process.hrtime(); end; Result := (hrTime[0] * Seconds2Nano) + hrtime[1]; end; procedure DoGameLoop; var now, delta: float; remaining: integer; begin if GameLoopActive then begin now := GetHRTime; if now >= _loopTargetHR then begin delta := now - _loopPrevHR; _loopPrevHR := now; _loopTargetHR := now + _loopLengthHR; if delta > _loopLengthHR then begin _loopTargetHR -= (delta - _loopLengthHR); end; _loopProc(delta * Nano2Seconds); end; if GameLoopActive then begin remaining := Trunc((_loopTargetHR - GetHRTime) * Nano2MS); if remaining >= 4 {16} then SetTimeout(DoGameLoop, remaining) else SetImmediate(DoGameLoop); end; end; end; procedure StartGameLoop(update: TGameLoopCallback; msInterval: integer); begin if not GameLoopActive then begin GameLoopActive := True; _loopLengthHR := msInterval * MS2Nano; _loopProc := update; _loopPrevHR := GetHRTime; _loopTargetHR := _loopPrevHR; SetImmediate(DoGameLoop); end; end; procedure StopGameLoop; begin GameLoopActive := False; _loopProc := nil; end; end.  
  2. Like
    lynkfs got a reaction from jarto in css grid   
    2) using css grid to make a responsive 'form'
    The below component does some simple layouting of controls and also reacts to screen-sizing, both using the css grid :
    procedure TForm1.InitializeForm; begin   inherited;   // this is a good place to initialize components   var ResponsiveForm : TResponsiveForm := TResponsiveForm.Create(self);   ResponsiveForm.SetBounds(40,40,500,220);   ResponsiveForm.AutoHeight := true;   ResponsiveForm.Add('Name',TW3EditBox);   ResponsiveForm.Add('Email',TW3EditBox);   ResponsiveForm.Add('Township',TW3EditBox);   ResponsiveForm.Add('Comments',TW3Memo);   ResponsiveForm.Add('Submit',TW3Button,2); end; Demo here
    It is not really 100% responsive, as the labels should shift above the controls when screen size becomes small. It doesn't however look too bad and the tediousness of aligning labels and controls is taken care of by the css grid. (Adapted from this article). 
    It's probably as easy though to use anchors creating the same result
     
  3. Like
    lynkfs got a reaction from Czar 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)
     
  4. Like
    lynkfs got a reaction from jarto 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)
     
  5. Thanks
    lynkfs reacted to jarto in window component   
    Cool, you found the new events like OnAllMovement. That makes the code a lot easier. The jitteryness may come from MoveTo.
    Forgot one thing: You need to call Ctrl.SetCapture when MouseDown happens and Ctrl.ReleaseCapture during MouseUp.
  6. Like
    lynkfs got a reaction from Czar 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
     
     
     
  7. Like
    lynkfs got a reaction from IElite in window component   
    Just in case anyone has a need for a window component.
    (multiple windows, movable, resizable, bringtofront, minimise, close, maximise)
    project
     
     
     
  8. Like
    lynkfs 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. 
     
  9. Like
    lynkfs got a reaction from DavidRM in window component   
    Just in case anyone has a need for a window component.
    (multiple windows, movable, resizable, bringtofront, minimise, close, maximise)
    project
     
     
     
  10. Thanks
    lynkfs reacted to jarto in window component   
    @lynkfs SetCapture/ReleaseCapture takes care of those dragging problems that @Czar mentioned.
    Edit: However, to be able to use SetCapture and ReleaseCapture, you need to listen to MouseDown, MouseUp and MouseMove using the normal Delphi-like events instead of using the raw JS events.
    Edit2: When you use normal events, the EventManager takes care of a boatload of the complexity. For example, SetCapture locks on to the control meaning that all move events go that one. (See the Scrollbars code in the RTL as an example)
    The EventManager also notices situations where you click on control to drag it, move the mouse outside of the whole browser window and release the button there. If you try to listen to events through JS, these kinds of special situations are a pain to handle correctly.
  11. Like
    lynkfs got a reaction from Czar in window component   
    Just in case anyone has a need for a window component.
    (multiple windows, movable, resizable, bringtofront, minimise, close, maximise)
    project
     
     
     
  12. Like
    lynkfs got a reaction from jarto 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 :
    Demo
    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.
     
  13. Like
    lynkfs got a reaction from IElite in css grid   
    The CSS Grid is pretty fast.
    However the current major browsers have a hard-coded limit of 1000 rows (Chromium) or 10,000 rows (Firefox). See reference issue here
    Edited project here (better stylesheet handling)
     
     
  14. Thanks
    lynkfs got a reaction from IgorSavkic in css grid   
    The CSS Grid is pretty fast.
    However the current major browsers have a hard-coded limit of 1000 rows (Chromium) or 10,000 rows (Firefox). See reference issue here
    Edited project here (better stylesheet handling)
     
     
  15. Like
    lynkfs got a reaction from Czar 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
     
  16. Thanks
    lynkfs got a reaction from Czar 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
     
  17. Like
    lynkfs reacted to IgorSavkic in reCaptcha   
    What I did (for a reset pass form) was to include gogle recapcha js  to html, it auto displays/shows a small recaptcha logo on lower right and shows challenge only when my SMS ResetPass button is pressed:

     
    var   grecaptcha external 'grecaptcha': Variant;   grecaptcha.execute(GoogleRecaptchaKey, InitObject(['action', 'pwdreset'])).then(     lambda (token: Variant)       // We received result from Google recaptcha, pass it along with other entered values to the server       // Server will perform final validation of received token (is it valid value or not).       WriteLn(Token);       glbApp.ResetPass(Trim(edtUserName.value), Trim(edtCust.value),         lambda (AClient, AStatus)            ShowMessage('If entered details match registered user, password reset details will be sent to your eMail address.');         end       );     end   );
     
  18. Like
    lynkfs got a reaction from Czar 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
     
  19. Like
    lynkfs got a reaction from IElite in Responsive Design   
    css here, project here
    Nothing fancy, just used the css and html of the example as-is. Could be simplified 
    The CSS grid is implemented in these lines in the stylesheet :
      display: grid;   grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));   grid-gap: 1rem; "give me as many columns as fit on the available width where each column is at least 320px wide, or maximum 1 fraction"
    The CSS grid is pretty powerful and is available in all modern browsers, including mobile. Time permitting, I'll dig into it a bit deeper.
     
     
  20. Like
    lynkfs got a reaction from IgorSavkic 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 :
    Demo
    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.
     
  21. Like
    lynkfs got a reaction from IElite 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 :
    Demo
    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.
     
  22. Like
    lynkfs got a reaction from Czar 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 :
    Demo
    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.
     
  23. Like
    lynkfs got a reaction from IElite in Send requests to Node.js server from client?   
    As far as I understand Node, for a simple http server the action is in the handlerequest proc. 
    This procedure has a request and a response object, and the latter can be used to send data back to the client.
      Request.Handle.on('end', procedure(data: variant)     begin       Response.&End('Headers: '+request.Headers.ToString()+#13#10+                    'Content: '+Variant('this is the response from my server'));  //<=============       //These are not automatically freed after HandleRequest as that would       //prevent reading of content data using async functions.       Request.Free;       Response.Free;     end); This should be able to be picked up in the responseText of the calling httprequest  
    (There are some examples on the forum doing something similar using sockets, but your approach should work too)
  24. Like
    lynkfs 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.
  25. Like
    lynkfs reacted to Czar 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.
     
×
×
  • Create New...