Jump to content

lynkfs

Moderators
  • Content Count

    743
  • Joined

  • Last visited

  • Days Won

    146

Reputation Activity

  1. Like
    lynkfs got a reaction from jarto in video in embedded browser   
    The MP4 codecs are only license free in browsers (as long as users don't have to pay for the audio or video). In any other application the use of the most widely used MP4 codecs requires a commercial license.
    Looks like that is the reason for the exclusion of mp4 in CEF4
    It should be possible to write-your-own MP4 codec. There are a couple of interesting posts on the subject (post 1, post 2) and there is a rudimentary codec structure in the rtl (system.codec.)
    However not in the complexity of what mp4 requires
    Google has produced its own license free product : 'webm'
    This is used in their own products (youtube) and by other main producers (netflix)
    There are many online converters available to convert .mp4 files to .webm files
    Using the TW3MediaPlayer component (smartcl.controls.mediaplayer) to see how that works :
    procedure TForm1.InitializeForm; var   VPlayer : TW3MediaPlayer; begin   inherited;   // this is a good place to initialize components   VPlayer := TW3MediaPlayer.Create(self);   VPlayer.SetBounds(20,20,800,500);   if VPlayer.CanPlayType('video/webm','vp8, vp9') = msProbably then     writeln('probably');   if VPlayer.CanPlayType('video/webm','vp8, vp9') = msMaybe then     writeln('maybe');   if VPlayer.CanPlayType('video/webm','vp8, vp9') = msNo then     writeln('no');   VPlayer.Load('video1.webm');  //video1.mp4');   var Button1 := TW3Button.Create(self);   Button1.SetBounds(20,550,100,30);   Button1.Caption := 'Play';   Button1.OnClick := lambda VPlayer.Play; end; end;  
    And indeed this plays videos in both standalone browsers and the ide
     
     
     
  2. Like
    lynkfs got a reaction from jarto in https://peerjs.com/ - is this feasible?   
    just as a proof of concept :
    tutor initiates conversation with student : https://lynkfs.com/Experiments/peer/receive/www
    and on another machine : https://lynkfs.com/Experiments/peer/send/www (must be on another machine)
    student sends a text by copying tutor id into the edit box and pressing buttons 1, 2 and 3
    this text then arrives at the tutors project
    The user interface of these projects is really bad, sorry, just proof-of-concept. 
    This demo is basically a simple chap app, but since it is using webrtc (and webrtc handles not only text but also other media), I feel that extending this to a full-fledged channel between parties should be feasible and reasonably straightforward
     
  3. Like
    lynkfs got a reaction from jarto in https://peerjs.com/ - is this feasible?   
    Just going through the first bit of their docs, it looks fairly straightforward
    procedure TForm1.W3Button1Click(Sender: TObject); begin //   var Script := browserapi.document.createElement('script');   Script.src := 'https://cdn.jsdelivr.net/npm/peerjs@0.3.20/dist/peer.min.js';   browserapi.document.head.appendChild(Script);   Script.onload := procedure   begin     writeln('peer.js loaded');     asm @mypeer = new Peer({key: 'lwjd5qra8257b9'}); end; //demo key     mypeer.on('open', procedure(id:string) begin writeln('New peer ID : ' + id); end);   end; end; the remainder doesn't look too cumbersome, i'll have a look later
  4. Thanks
    lynkfs got a reaction from Czar in https://peerjs.com/ - is this feasible?   
    just as a proof of concept :
    tutor initiates conversation with student : https://lynkfs.com/Experiments/peer/receive/www
    and on another machine : https://lynkfs.com/Experiments/peer/send/www (must be on another machine)
    student sends a text by copying tutor id into the edit box and pressing buttons 1, 2 and 3
    this text then arrives at the tutors project
    The user interface of these projects is really bad, sorry, just proof-of-concept. 
    This demo is basically a simple chap app, but since it is using webrtc (and webrtc handles not only text but also other media), I feel that extending this to a full-fledged channel between parties should be feasible and reasonably straightforward
     
  5. Like
    lynkfs got a reaction from IgorSavkic in https://peerjs.com/ - is this feasible?   
    just as a proof of concept :
    tutor initiates conversation with student : https://lynkfs.com/Experiments/peer/receive/www
    and on another machine : https://lynkfs.com/Experiments/peer/send/www (must be on another machine)
    student sends a text by copying tutor id into the edit box and pressing buttons 1, 2 and 3
    this text then arrives at the tutors project
    The user interface of these projects is really bad, sorry, just proof-of-concept. 
    This demo is basically a simple chap app, but since it is using webrtc (and webrtc handles not only text but also other media), I feel that extending this to a full-fledged channel between parties should be feasible and reasonably straightforward
     
  6. Like
    lynkfs got a reaction from Czar in https://peerjs.com/ - is this feasible?   
    Just going through the first bit of their docs, it looks fairly straightforward
    procedure TForm1.W3Button1Click(Sender: TObject); begin //   var Script := browserapi.document.createElement('script');   Script.src := 'https://cdn.jsdelivr.net/npm/peerjs@0.3.20/dist/peer.min.js';   browserapi.document.head.appendChild(Script);   Script.onload := procedure   begin     writeln('peer.js loaded');     asm @mypeer = new Peer({key: 'lwjd5qra8257b9'}); end; //demo key     mypeer.on('open', procedure(id:string) begin writeln('New peer ID : ' + id); end);   end; end; the remainder doesn't look too cumbersome, i'll have a look later
  7. Like
    lynkfs got a reaction from Czar in https://peerjs.com/ - is this feasible?   
    webrtc I think has come of age, so it's worthwhile exploring
    I'll be happy to have a look
  8. Like
    lynkfs got a reaction from jarto in app   
    I usually don't publish commercial apps on the forum.
    Here is the exception : a retail shopping experience - made with Smart
  9. Like
    lynkfs got a reaction from jarto in proxy   
    I recently came across the javascript proxy object
    A proxy object basically monitors a chosen object, and has getter and setter functions which are invoked when the value of any of its properties changes (set) or are being accessed (get).
    In that respect there are some similarities with the mutationobserver object.
    In the below code snippet a regular EditBox has its text saved in a proxied object, which triggers the setter function
    and a Button which reads that value and thus triggers the getter function
    procedure TForm1.InitializeForm; begin   inherited;   // this is a good place to initialize components   var Edit1 : TW3EditBox := TW3EditBox.Create(self);   Edit1.SetBounds(32,40,300,32);   var Button1 : TW3Button := TW3Button.Create(self);   Button1.SetBounds(340,40,200,32);   Button1.Caption := 'read';   var Memo1 : TW3Memo := TW3Memo.Create(self);   Memo1.SetBounds(32,90,300,100); //set proxies   var MyProxy  : variant := new JObject;   var ProxyObj : variant := new JObject;   ProxyObj.EditBox1 := 'initialvalue';    //will be overwritten   Edit1.OnInput   := lambda MyProxy.EditBox1 := Edit1.Text; end;      //triggers 'handler.set'   Button1.OnClick := lambda Button1.Caption := MyProxy.EditBox1; end; //triggers 'handler.get'   var handler : variant := new JObject;   handler.get := function(obj, prop: variant): variant   begin     Memo1.Add('someone read ' + prop + ' as ' + obj[prop] + #10);     result := obj[prop];   end;   handler.set := function(obj, prop, value: variant):variant   begin     Memo1.Add('someone set ' + prop + ' to ' + value + #10);     obj[prop] := value;     result := true;   end;   asm     @MyProxy = new Proxy(@ProxyObj,@handler);   end; end;  
    This mechanism could f.i. be used to bind form components with a data source, updating them automatically when data changes or is being accessed
    Demo
     
  10. Like
    lynkfs got a reaction from Czar in app   
    I usually don't publish commercial apps on the forum.
    Here is the exception : a retail shopping experience - made with Smart
  11. Like
    lynkfs got a reaction from thejavasea in SmartMS intro with ThreeJS and p5.js   
    Edited
    The other approach is to gain access to the internal j5 functions in a more readable way, as in 
    function createElement(a,b:string): Variant; external 'createElement'; function ellipse(a,b,c,d:integer): Variant; external 'ellipse'; implementation { TForm1 } procedure TForm1.W3Button1Click(Sender: TObject); begin   var txt := createElement('p', 'move your mouse over the canvas');   txt.position(50, 70); W3DivHtmlElement1.onMouseMove := procedure(Sender: TObject; Shift: TShiftState; X: Integer; Y: Integer) begin   ellipse(X,Y,80,80); end; which eliminates the asm blocks
    (code relates to Demo1 project)
     
    and to top it all off :
    here is a version which does away with all of the above and previous, does not need a separate sketch.js file, custom template etc. and does everything in code
    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.Button,   SmartCL.Controls.Elements; type   TForm1 = class(TW3Form)     procedure W3Button1Click(Sender: TObject);   private     {$I 'Form1:intf'}   protected     procedure InitializeForm; override;     procedure InitializeObject; override;     procedure Resize; override;   end; var myp5 : variant; implementation { TForm1 } procedure TForm1.W3Button1Click(Sender: TObject); begin //   var Script := browserapi.document.createElement('script');   Script.src := 'https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js';   browserapi.document.head.appendChild(Script);   Script.onload := procedure   begin     writeln('p5.js loaded');     var s      : variant := new(JObject);     var sketch : variant := new(JObject); //set up the sketch object and create its canvas     s := procedure(sketch:variant)     begin       sketch.setup := procedure()       begin         sketch.createCanvas(W3DivHtmlElement1.width, W3DivHtmlElement1.height);       end; sketch.draw := procedure() begin //any initial draw activities //sketch.rect(10,10,50,50); end;     end; // create the p5 instance and link it to the panel     var x := W3DivHtmlElement1.handle.id;     asm @myp5 = new p5(@s, @x); end; //use the p5 instance     W3DivHtmlElement1.onMouseMove := procedure(Sender: TObject; Shift: TShiftState; X: Integer; Y: Integer)     begin myp5.fill('pink');       myp5.ellipse(X,Y,80,80);     end;     myp5.rect(100,100,50,50);   end; end; procedure TForm1.InitializeForm; begin   inherited;   // this is a good place to initialize components W3DivHtmlElement1.handle.style.border := '1px solid red'; end; procedure TForm1.InitializeObject; begin   inherited;   {$I 'Form1:impl'} end;   procedure TForm1.Resize; begin   inherited; end;   initialization   Forms.RegisterForm({$I %FILE%}, TForm1); end. this way you could even have multiple canvasses on the same form
  12. Like
    lynkfs got a reaction from IgorSavkic in app   
    I usually don't publish commercial apps on the forum.
    Here is the exception : a retail shopping experience - made with Smart
  13. Like
    lynkfs got a reaction from thejavasea in SmartMS intro with ThreeJS and p5.js   
    Demo1 and Demo2
    P5.js : There are different ways of doing this
    - mapping all p5.js functions and variables to pascal so they can be accessed from Smart by name
    - take a bit of a shortcut
    The latter approach looks like this :
    - let P5 construct its canvas. This requires a minimum sketch.js file with its setup and draw functions. (The draw function can be empty. See project zipfile demo1)
    - copy the constructed canvas to a Smart component (W3Panel);
    - use p5 functions in code
    Demo1 uses this approach, Demo2 is a copy of one of the p5 examples
    Both projects in this zipfile
     
     
     
  14. Like
    lynkfs reacted to Tim Koscielski in Align Issue in latest Alpha Version - 3.9.1.173   
    Yes, if I make the change and comment out that line, the items do align correctly on the initial form create.
    And if I leave that line enabled, you are correct that when I resize the window, they do draw correctly.
    Now that you know where the issue is, I feel great that you'll come up with a solution to accommodate. The progress you have made recently with this stuff is great and I have been enjoying working with this .
    And to be honest, I am using the Alpha track for production development and I had just gotten used to not leaving a way to revert back to the prior version. This time it got me. <grin>
    Thanks for all you do.
  15. Like
    lynkfs got a reaction from IElite in pinch and zoom suggestion   
    Suggestion
    can the default viewport meta tag in the generated index.html file be changed from
        <meta name="viewport" content="width=device-width, maximum-scale=1.0, initial-scale=1.0, user-scalable=no"/> into
        <meta name="viewport" content="width=device-width, maximum-scale=2, initial-scale=1, user-scalable=yes"/>
     
    This allows to pinch & zoom images etc on mobile by default
     
  16. Like
    lynkfs reacted to jarto in video in embedded browser   
    If there are licensing issues, that affect this, I am a bit hesitant compiling it myself and including them in a commercial product.
  17. Like
    lynkfs got a reaction from Daniel Eiszele in Radiogroup add function   
    Composing a Radiogroup in the designer works fine
    For objects created in code however the add function doesn't work
    //creating in code var RadioGroup1 : TW3RadioGroup := TW3RadioGroup.Create(self);   RadioGroup1.setbounds (200,200,200,200);   RadioGroup1.Add('bbb'); <==== no results //created in the designer   W3RadioGroup1.Add('aaaa'); <==== correct results (probably to do with the difference between TStringlist and TStrArray)
     
  18. Like
    lynkfs got a reaction from jarto in Radiogroup add function   
    Composing a Radiogroup in the designer works fine
    For objects created in code however the add function doesn't work
    //creating in code var RadioGroup1 : TW3RadioGroup := TW3RadioGroup.Create(self);   RadioGroup1.setbounds (200,200,200,200);   RadioGroup1.Add('bbb'); <==== no results //created in the designer   W3RadioGroup1.Add('aaaa'); <==== correct results (probably to do with the difference between TStringlist and TStrArray)
     
  19. Like
    lynkfs got a reaction from IgorSavkic in responsive grid   
    This post is about using the css-grid for responsive content.
    It happens often that the contents of a container need to re-arrange itself depending on the size (width) of the container, as in

     
    Using a css-grid for that purpose, the code is pretty minimal at just 5 lines :
    //container (w3panel)   cards.handle.style.display := 'grid';   cards.handle.style['grid-template-columns'] := 'repeat(auto-fill, minmax(180px, 1fr))'; //set minmax to just a bit bigger than the card-width   cards.handle.style['grid-gap'] := '50px';   cards.handle.style['justify-items'] := 'center'; //container item (w3panel)   card.handle.style.position := 'relative';  
     
  20. Like
    lynkfs reacted to IgorSavkic in Downloading Memo Contents as a File   
    Here's example for csv file:

    var csv: string; begin   csv := 'Field1,Field2,Field3' + #13#10; // Add other lines to it   var link = w3_createHtmlElement('a');     link.href := 'data:text/csv;charset=utf-8,' + EncodeURI(csv);     link.target := '_blank';     link.download := 'CarlSearch.csv';     BrowserAPI.Body.appendChild(link);     link.click();     BrowserAPI.Body.removeChild(link); end;    
     
  21. Like
    lynkfs got a reaction from Czar in design templates   
    I'm sharing some links below to app-demo's, based on design templates.
    I'm a big fan of these types of templates as they provide essential design guidance on navigation, styling and the use of animation. And since I'm not a graphic designer, that all helps tremendously.
    The demo's below are recreated in Smart, using elements of the 'famous' design templates (https://famous.co)
    Retail shop demo couple of slides of a business presentation  demo's optimised for laptop only
    (also the background video's on the first forms may take a couple of seconds to load)
    On the animation side : the animation framework in these demo's is based on waapi (web animation api) and consists of an extension of the standard form handling. Basically every form and every component on a form can enable web-animation events. These events are triggered by the phase a form is in : coming into focus going forward, going out of focus going forward, coming into focus going backwards and going out of focus going backwards. These phases not only trigger screen events, but also all component animation events
    Procedure Traverse(phase: string; screen: string; direction: string); begin   var z : variant := new JObject;   z := browserapi.document.getElementById('Component2').getElementsByTagName("*");  //all children of TDisplayView   for var i := 0 to z.length-1 do begin     if z[i].dataset.screen then begin       if (phase = 'init') and (screen = z[i].dataset.screen) then begin         if (direction = 'forward') then begin           if z[i].dataset.initforwardanim then             z[i].animate(json.parse(z[i].dataset.initforwardanim),z[i].dataset.initforwardtime);         end;         if (direction = 'reverse') then begin           if z[i].dataset.initreverseanim then             z[i].animate(json.parse(z[i].dataset.initreverseanim),z[i].dataset.initreversetime);         end;       end;       if (phase = 'exit') and (screen = z[i].dataset.screen) then begin         if (direction = 'forward') then begin           if z[i].dataset.exitforwardanim then             z[i].animate(json.parse(z[i].dataset.exitforwardanim),z[i].dataset.exitforwardtime);         end;         if (direction = 'reverse') then begin           if z[i].dataset.exitreverseanim then             z[i].animate(json.parse(z[i].dataset.exitreverseanim),z[i].dataset.exitreversetime);         end;       end;     end;   end; end;
     
     
  22. Like
    lynkfs got a reaction from IgorSavkic in design templates   
    I'm sharing some links below to app-demo's, based on design templates.
    I'm a big fan of these types of templates as they provide essential design guidance on navigation, styling and the use of animation. And since I'm not a graphic designer, that all helps tremendously.
    The demo's below are recreated in Smart, using elements of the 'famous' design templates (https://famous.co)
    Retail shop demo couple of slides of a business presentation  demo's optimised for laptop only
    (also the background video's on the first forms may take a couple of seconds to load)
    On the animation side : the animation framework in these demo's is based on waapi (web animation api) and consists of an extension of the standard form handling. Basically every form and every component on a form can enable web-animation events. These events are triggered by the phase a form is in : coming into focus going forward, going out of focus going forward, coming into focus going backwards and going out of focus going backwards. These phases not only trigger screen events, but also all component animation events
    Procedure Traverse(phase: string; screen: string; direction: string); begin   var z : variant := new JObject;   z := browserapi.document.getElementById('Component2').getElementsByTagName("*");  //all children of TDisplayView   for var i := 0 to z.length-1 do begin     if z[i].dataset.screen then begin       if (phase = 'init') and (screen = z[i].dataset.screen) then begin         if (direction = 'forward') then begin           if z[i].dataset.initforwardanim then             z[i].animate(json.parse(z[i].dataset.initforwardanim),z[i].dataset.initforwardtime);         end;         if (direction = 'reverse') then begin           if z[i].dataset.initreverseanim then             z[i].animate(json.parse(z[i].dataset.initreverseanim),z[i].dataset.initreversetime);         end;       end;       if (phase = 'exit') and (screen = z[i].dataset.screen) then begin         if (direction = 'forward') then begin           if z[i].dataset.exitforwardanim then             z[i].animate(json.parse(z[i].dataset.exitforwardanim),z[i].dataset.exitforwardtime);         end;         if (direction = 'reverse') then begin           if z[i].dataset.exitreverseanim then             z[i].animate(json.parse(z[i].dataset.exitreverseanim),z[i].dataset.exitreversetime);         end;       end;     end;   end; end;
     
     
  23. Like
    lynkfs reacted to jarto in Managing Tab Order in a Form   
    Thank you for the feedback. I've been thinking about this a while and I'd rather not do the automatic TabOrder numbering. It'd have to be done during runtime also and I feel that in most cases it'd just be an unnecessary extra performance hit. However, you'll be able to set the properties in the designer.
  24. Like
    lynkfs got a reaction from jarto in Managing Tab Order in a Form   
    I mostly agree.
    I suppose that on rare occasions one might want to do something when tw3display or displayview gets the focus, like in
      Display.OnGotFocus := procedure(sender:tobject) begin writeln('focus'); display.handle.style['background-color'] := 'white' end;
    see the zen-sky demo where display is a visible element
    Very rare I think, and even then the tabindex shouldn't be 1 but rather 0

     
  25. Thanks
    lynkfs reacted to IgorSavkic in Nodejs.Path Unit   
    That needs fix from dev team, but as a workaround try to write class helper (untested) and hopefully it will take precedence over default declaration.
    JPathExportHelper = class helper for JPath_Exports
       function Join(Paths: string): string;
    end;
    and implementation as:
    asm @Result = join(@Paths); end
    or
    Result := Variant(Self).join(Paths);
×
×
  • Create New...