Jump to content

Czar

Members
  • Content Count

    447
  • Joined

  • Last visited

  • Days Won

    13

Reputation Activity

  1. Like
    Czar reacted to IElite in When is the next contest?   
    Like any other company, the priority is on new features and upgrades then on technical documentation, demos, and how-tos.
     
    I'm still waiting for update to Smart Book 
     
    I think the community should spend more time sharing.  Maybe SMS administrators can create a Forum topic where we can share applications, tips and tricks, etc. that we have learned along the way. Maybe it can be broken down into topics such as Mobile Apps, Games, graphics, Browser Apps, etc
  2. Like
    Czar reacted to lynkfs in 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
     
     
  3. Like
    Czar reacted to jarto in find component within another component   
    You can use ForEach() to loop through the children:
    MyPanel.ForEach( function (const Child: TW3TagContainer): TEnumResult begin if Child is TW3Label then begin TW3Label(Child).Caption:='IT WORKED!'; //result:=erBreak; //If you want to exit end; end);  
  4. Like
    Czar reacted to jarto in Size of Components at Runtime   
    This could be made a bit simpler by also making ClientWidth and ClientHeight writable.
  5. Like
    Czar got a reaction from jarto in smartcl.effects   
    Suggestion - the fxmove etc are very good - easy to use. However, there doesn't appear to be a simple rotation effect. You can go the whole rotation system using TW3RotateCSSAnimation however, if you simply want to adjust the angle a bit, like a rocking boat of swaying palm trees then you appear to have to make your own. 
     
    procedure TForm1.RockBoat;
    begin
      visual.boatangle := visual.boatangle +0.2;
      visual.boatimg.Angle := sin(visual.boatangle);
      TW3Dispatch.Execute( procedure begin RockBoat end, 75);
    end;

  6. Thanks
    Czar reacted to DavidRM in ShowModal and Measuring Text   
    In the ShowModal, the "init" callback is called before FormActivated is called. Thus, my calling UpdateUI in the init callback is... premature.
    By adding an OnActivated event handler to the ShowMessageForm, which calls UpdateUI (removing the call from the init callback), my original code works as expected.
    -David
  7. Thanks
    Czar reacted to jarto in tw3slider mouseup   
    Yeah, true, as that component internally uses OnMouseDown, OnMouseMove and OnMouseUp.
    Edit: Fix will be in the next update.
  8. Like
    Czar got a reaction from jarto in inheritance   
    I managed to a solution which is probably better
     
      var Context := JCanvasRenderingContext2D(LBitmap.canvas.context.handle.getContext('2d'));

        Context.font:="75px verdana";
    Context.shadowColor:="black";
    Context.shadowBlur:=7;
    Context.lineWidth:=5;
    Context.strokeText("TEstMe",25,100);
    Context.shadowBlur:=0;
    Context.fillStyle:="white";
    Context.fillText("TEstMe",25,100);
  9. Thanks
    Czar got a reaction from lynkfs in inheritance   
    I managed to a solution which is probably better
     
      var Context := JCanvasRenderingContext2D(LBitmap.canvas.context.handle.getContext('2d'));

        Context.font:="75px verdana";
    Context.shadowColor:="black";
    Context.shadowBlur:=7;
    Context.lineWidth:=5;
    Context.strokeText("TEstMe",25,100);
    Context.shadowBlur:=0;
    Context.fillStyle:="white";
    Context.fillText("TEstMe",25,100);
  10. Like
    Czar got a reaction from IgorSavkic in smartcl.effects   
    Suggestion - the fxmove etc are very good - easy to use. However, there doesn't appear to be a simple rotation effect. You can go the whole rotation system using TW3RotateCSSAnimation however, if you simply want to adjust the angle a bit, like a rocking boat of swaying palm trees then you appear to have to make your own. 
     
    procedure TForm1.RockBoat;
    begin
      visual.boatangle := visual.boatangle +0.2;
      visual.boatimg.Angle := sin(visual.boatangle);
      TW3Dispatch.Execute( procedure begin RockBoat end, 75);
    end;

  11. Like
    Czar reacted to lynkfs in Background uploading files   
    amazing app ? - looks absolutely wonderful
    As to Edge, I don't know why these guys (MS) bother at all
    In my experience Edge is completely buggy (latest : doesn't even allow localStorage on win10) and is far behind implementing even the simplest of html5 / w3c specs (detail/summary tags, doh) 
    Edge is the new IE
    (I'll have a look later if there is a workaround)
    Cheers
     
  12. Like
    Czar reacted to jarto in Scroll form   
    There are a few ways you can do this:
    Easiest is to just set NativeScrolling := True on the form. After that it just scrolls the whole form automatically, if the full contents are not visible.
    If you don't want the whole form to scroll, you can build all the scrollable contents inside a ScrollBox. Here you have two possibilities: TW3NativeScrollBox or TW3ScrollBox. If you use TW3ScrollBox, make sure to create the contents inside it's content (MyCtrl := TWhatever.Create(ScrollBox.Content) and to call ScrollBox.UpdateControl when content is built and resized.
    The difference between the "native" solutions and TW3ScrollBox is, that TW3ScrollBox does all the scrolling with code, which lets you control everything better.
  13. Like
    Czar reacted to lynkfs in OpenStreetMap component?   
    you can use a simple IFrameHtmlElement on a form and set src to something like this
      W3IFrameHtmlElement1.Src := "//www.openstreetmap.org/export/embed.html?bbox=10.970685482025146%2C49.5968664515866%2C10.98160743713379%2C49.603138573344914&layer=mapnik&marker=49.60000261331038%2C10.976146459579468";
     
  14. Like
    Czar reacted to lynkfs in a basic JSON question   
    if you include ECMA.Json then you don't need to asm block your parse statements
    don't know what your TR1 variable is, but define it as a variant. Do a
        console.log(@TR1); //  {"business":"lynkfs","departments":[{"deptname":"marketing","staff":[{"first and after parsing you can access your fields as in TR1.business and TR1.departments[0].deptname etc
    .
    Below is what I call my dogs breakfast. Just a set of steps to convert from one data structure to another. Multiple stringify's and parse's in there
    step 1 : create a record structure  step2 : change some values programmatically step3 : change record structure to json step4: create a TDataSet from json step5 : save json to local storage step 6: retrieve localstorage step 7: create a SQLite db from json step 8: save complete SQLite db to local storage and retrieve it again step 9: save json to a MYSql db on server step 10: and retrieve it again unit Form1; interface uses   System.Types,   System.Types.Convert,   System.Objects,   System.Time,   SmartCL.System,   SmartCL.Time,   SmartCL.Graphics,   SmartCL.Components,   SmartCL.FileUtils,   SmartCL.Forms,   SmartCL.Fonts,   SmartCL.Theme,   SmartCL.Borders,   SmartCL.Application, SmartCL.Controls.Button, ECMA.JSON, System.DataSet,   SmartCL.Storage.Local, System.Sqlite, W3C.XMLHttpRequest, W3C.HTML5, W3C.DOM,   System.Streams, W3C.Console, system.structure, system.structure.json, system.json; type   TForm1 = class(TW3Form)     procedure W3Button1Click(Sender: TObject);   private     {$I 'Form1:intf'}   protected     procedure InitializeForm; override;     procedure InitializeObject; override;     procedure Resize; override;     Procedure DoStuff;   end; // record types type   JStrC = class(TJSonStructure)   //record     firstname    : string;              //external 'firstname';     surname      : string;              //external 'surname';   end;   JStrB = class(TJSonStructure)   //record     deptname     : string;              //external 'deptname';     staff        : Array of JStrC;      //external 'staff';   end;   JStrA = class(TJSonStructure)   //record     business     : string;              //external 'business'     departments  : Array of JStrB;      //external 'departments';   end; var document external 'document': variant; var window   external 'window':   variant; var console  external 'console':  variant; implementation { TForm1 } Procedure TForm1.DoStuff; begin // // step1 : set up a leveled structure, (either records or classes) //         i.e. business unit with departments with employees per department     writeln('Step1'); // /*   //business unit   var StrA01 : JStrA;   StrA01.business    := 'lynkfs';     //department marketing     var StrB01 : JStrB;     StrB01.deptname    := 'marketing';       //staff Keith Ansell       var StrC01 : JStrC;       StrC01.firstname   := 'Claire';       StrC01.surname     := 'Adams';     StrB01.staff.Add(StrC01);       //staff Charles Bailey       var StrC02 : JStrC;       StrC02.firstname   := 'Vicky';       StrC02.surname     := 'Anderson';     StrB01.staff.Add(StrC02);   StrA01.departments.Add(StrB01);     //department frontdesk     var StrB02 : JStrB;     StrB02.deptname    := 'front desk';       //staff Keith Ansell       var StrC03 : JStrC;       StrC03.firstname   := 'Keith';       StrC03.surname     := 'Ansell';     StrB02.staff.Add(StrC03);       //staff Charles Bailey       var StrC04 : JStrC;       StrC04.firstname   := 'Charles';       StrC04.surname     := 'Bailey';     StrB02.staff.Add(StrC04);   StrA01.departments.Add(StrB02); */   //business unit   var StrA01 := JStrA.Create;   StrA01.business    := 'lynkfs';     //department marketing     var StrB01 := JStrB.Create;     StrB01.deptname    := 'marketing';       //staff Claire Adams       var StrC01 := JStrC.Create;       StrC01.firstname   := 'Claire';       StrC01.surname     := 'Adams';     StrB01.staff.Add(StrC01);       //staff Vicky Anderson       var StrC02 := JStrC.Create;       StrC02.firstname   := 'Vicky';       StrC02.surname     := 'Anderson';     StrB01.staff.Add(StrC02);   StrA01.departments.Add(StrB01);     //department frontdesk     var StrB02 := JStrB.Create;     StrB02.deptname    := 'front desk';       //staff Keith Ansell       var StrC03 := JStrC.Create;       StrC03.firstname   := 'Keith';       StrC03.surname     := 'Ansell';     StrB02.staff.Add(StrC03);       //staff Charles Bailey       var StrC04 := JStrC.Create;       StrC04.firstname   := 'Charles';       StrC04.surname     := 'Bailey';     StrB02.staff.Add(StrC04);   StrA01.departments.Add(StrB02);   // check   writeln(inttostr(StrA01.departments.length) + ' departments');   for var i := 0 to StrA01.departments.length -1 do begin     writeln(StrA01.departments[i].deptname + ' ' + inttostr(StrA01.departments[i].staff.length) + ' staff');     for var j := 0 to StrA01.departments[i].staff.length -1 do begin       writeln(StrA01.departments[i].staff[j].firstname + ' ' +               StrA01.departments[i].staff[j].surname);     end;   end;   var jsontext: string := '';   asm     @jsontext = JSON.stringify(@StrA01);     console.log(@jsontext); //  {"business":"lynkfs","departments":[{"deptname":"marketing","staff":[{"firstname":"Vicky","surname":"Anderson"}]},{"deptname":"front desk","staff":[{"firstname":"Keith","surname":"Ansell"},{"firstname":"Charles","surname":"Bailey"}]},{"deptname":"new department","staff":[]}]}   end;   StrA01.Write('business','lynkfs');   window.alert(StrA01.ToJson); // // step2 : depending on business logic, add/delete/change data in these arrays at will     writeln('Step2'); //   // employee Claire Adams leaves   StrA01.departments[0].staff.Delete(0);    //or coding to that effect   // a new empty department is created   var StrB := JStrB.Create;   StrB.deptname := 'new department';   StrA01.departments.add(StrB);   // check   writeln(inttostr(StrA01.departments.length) + ' departments');   for var i := 0 to StrA01.departments.length -1 do begin     writeln(StrA01.departments[i].deptname + ' ' + inttostr(StrA01.departments[i].staff.length) + ' staff');     for var j := 0 to StrA01.departments[i].staff.length -1 do begin       writeln(StrA01.departments[i].staff[j].firstname + ' ' +               StrA01.departments[i].staff[j].surname);     end;   end; // // step3 : Turn object to json     writeln('Step3'); //   var textdata: string := '';   asm     @textdata = JSON.stringify(@StrA01);     console.log(@textdata); //  {"business":"lynkfs","departments":[{"deptname":"marketing","staff":[{"firstname":"Vicky","surname":"Anderson"}]},{"deptname":"front desk","staff":[{"firstname":"Keith","surname":"Ansell"},{"firstname":"Charles","surname":"Bailey"}]},{"deptname":"new department","staff":[]}]}   end; // // step4 : Define and populate TW3DataSet from json     writeln('Step4'); //   var DataSet := TW3DataSet.Create;      // note TW3Dataset is not leveled   Dataset.FieldDefs.Add('business',ftString);   Dataset.FieldDefs.Add('deptname',ftString);   Dataset.FieldDefs.Add('firstname',ftString);   Dataset.FieldDefs.Add('surname',ftString);   DataSet.CreateDataset;   var v := json.parse(textdata);   For var i := 0 to v.departments.length -1 do begin     For var j := 0 to v.departments[i].staff.length -1 do begin       DataSet.Append;       Dataset.Fields.FieldByName('business').AsString := v.business;       Dataset.Fields.FieldByName('deptname').AsString := v.departments[i].deptname;       Dataset.Fields.FieldByName('firstname').AsString := v.departments[i].staff[j].firstname;       Dataset.Fields.FieldByName('surname').AsString   := v.departments[i].staff[j].surname;       DataSet.Post;     end;     If v.departments[i].staff.length = 0 then begin     //empty department       DataSet.Append;       Dataset.Fields.FieldByName('business').AsString := v.business;       Dataset.Fields.FieldByName('deptname').AsString := v.departments[i].deptname;       DataSet.Post;     end;   end;   // check   DataSet.First;   while not DataSet.Eof do   begin     writeln(inttostr(DataSet.recno+1) + ' ' +             Dataset.Fields.FieldByName('business').AsString + ' ' +             Dataset.Fields.FieldByName('deptname').AsString + ' ' +             Dataset.Fields.FieldByName('firstname').AsString + ' ' +             Dataset.Fields.FieldByName('surname').AsString);     DataSet.Next;   end; // // step5 : save json to local storage (persistent on specific device)     writeln('Step5');     // step 5 only needs to be run once //   var LocalStorage := TW3LocalStorage.Create;   LocalStorage.Open('mytreasure');   LocalStorage.SetKeyStr('json',textdata);   LocalStorage.Close; //bypassing SmartCL.Storage.Local :   window.localStorage.setItem('pete',textdata); // // step6 : retrieve json from local storage (persistent on specific device)     writeln('Step6'); //   textdata := '';   LocalStorage.Open('mytreasure');   textdata := LocalStorage.GetKeyStr('json','unknown');   LocalStorage.Close;   var v1 := json.parse(textdata);   // check   writeln(inttostr(v1.departments.length) + ' departments');   for var i := 0 to v1.departments.length -1 do begin     writeln(v1.departments[i].deptname + ' ' + inttostr(v1.departments[i].staff.length) + ' staff');     for var j := 0 to v1.departments[i].staff.length -1 do begin       writeln(v1.departments[i].staff[j].firstname + ' ' +               v1.departments[i].staff[j].surname);     end;   end; //Bypassing SmartCL.Storage.Local   v1 := json.parse(window.localStorage.getItem('pete'));   // check   writeln('/////////////////////pete/////////////////////////////');   writeln(inttostr(v1.departments.length) + ' departments');   for var i := 0 to v1.departments.length -1 do begin     writeln(v1.departments[i].deptname + ' ' + inttostr(v1.departments[i].staff.length) + ' staff');     for var j := 0 to v1.departments[i].staff.length -1 do begin       writeln(v1.departments[i].staff[j].firstname + ' ' +               v1.departments[i].staff[j].surname);     end;   end; // // step7 : save json to SQLite     writeln('Step7'); //   var db   : TSQLiteDatabase;   var res  : TSQLiteResult;   db := TSQLiteDatabase.Create;   db.Run('CREATE TABLE `business`    (id INTEGER, business TEXT)');   db.Run('CREATE TABLE `departments` (id INTEGER, busid INTEGER, deptname TEXT)');   db.Run('CREATE TABLE `staff`       (id INTEGER, deptid INTEGER, busid INTEGER, firstname TEXT, surname TEXT)');   var v2 := json.parse(textdata);   db.Run("INSERT INTO `business`(`id`,`business`) VALUES (0,'" + v2.business + "')");   for var i := 0 to v2.departments.length -1 do begin     db.Run("INSERT INTO `departments`(`id`,`busid`,`deptname`) VALUES (" +          inttostr(i) + ",0,'" + v2.departments[i].deptname + "')");     for var j := 0 to v2.departments[i].staff.length -1 do begin       db.Run("INSERT INTO `staff`(`id`,`deptid`,`busid`,`firstname`,`surname`) VALUES (" +            inttostr(j) + "," + inttostr(i) + ",0,'" + v2.departments[i].staff[j].firstname +            "','" + v2.departments[i].staff[j].surname + "')");     end;   end; //  check //  res := db.Exec("SELECT a.business, b.deptname, c.firstname, c.surname " + //                 "from business a, departments b, staff c " + //                 "where c.busid = a.id and c.deptid = b.id and b.busid = a.id"); // or something a bit simpler   res := db.Exec("SELECT surname FROM staff");   //writeln(res.columns[0]);   //title of first field : 'business'   var rows := res.values;   for var i := 0 to rows.length -1 do begin     var columns := rows[i].values;     for var j := 0 to columns.length-1 do begin       writeln(columns[j]);     end;   end; // or alternatively, same result // //  for var i := 0 to res.values.length -1 do begin                   //rows //    for var j := 0 to res.values[i].values.length-1 do begin        //columns //      writeln(res.values[i].values[j]);                             //cell //    end; //  end; // // step8 : save sqlite db to localstorage     writeln('Step8'); //   var MyStream : TStringStream;   MyStream := TStringStream.Create;   db.SaveToStream(MyStream,true);   var textdata3 := MyStream.DataString;   console.log(textdata3);   //save textdata3 to local storage   var LocalStorage2 := TW3LocalStorage.Create;   LocalStorage2.Open('sqlite');   LocalStorage2.SetKeyStr('stream',textdata3);   LocalStorage2.Close;   //read textdata3 from local storage   LocalStorage2.Open('sqlite');   textdata3 := LocalStorage2.GetKeyStr('stream','unknown');   LocalStorage2.Close;   //populate stream with localstorage data and revive sqlite db from stream   MyStream.DataString := textdata3;   MyStream.Position := 0;   console.log(mystream.datastring);   var db2 := TSQLiteDatabase.Create;   db2.LoadFromStream(MyStream);   writeln(db2.active);   res := db2.Exec("SELECT surname FROM staff");   //test   for var i := 0 to res.values.length -1 do begin                   //rows     for var j := 0 to res.values[i].values.length-1 do begin        //columns       writeln(res.values[i].values[j]);                             //cell     end;   end; /* // // step9 : save json to server (persistent over all devices)     writeln('Step8'); //   var s := "UPDATE `test` SET `webjson`='" + textdata + "'";   var FHttp := JXMLHttpRequest.Create;   FHttp.open("POST",'...../smsdmlmysql.php');   FHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");   var encodedstr1 := browserapi.window.encodeURIComponent(S);   var sql_statement := 'sql_statement=' + encodedstr1;   FHttp.send(sql_statement); // // step10 : retrieve json from server     writeln('Step9'); //   s := "select * from test";   var FHttp2 := JXMLHttpRequest.Create;   FHttp2.open("POST",'...../smsdbmysql.php');   FHttp2.setRequestHeader("Content-type","application/x-www-form-urlencoded");   var encodedstr2 := browserapi.window.encodeURIComponent(S);   var sql_statement2 := 'sql_statement=' + encodedstr2;   FHttp2.send(sql_statement2);   JGlobalEventHandlers(FHttp2).onLoad := lambda(e:JEvent)     var smscursor := JSON.parse(FHttp2.responseText);     for var i := 0 to smscursor.rows.length -1 do begin       textdata := smscursor.rows[i].webjson;     end;     writeln(textdata);     result :=true;   end; */ end; procedure TForm1.W3Button1Click(Sender: TObject); begin   DoStuff; end; procedure TForm1.InitializeForm; begin   inherited;   // this is a good place to initialize components end; procedure TForm1.InitializeObject; begin   inherited;   {$I 'Form1:impl'} end; procedure TForm1.Resize; begin   inherited; end; initialization   Forms.RegisterForm({$I %FILE%}, TForm1); end.  
     
  15. Like
    Czar reacted to jarto in a basic JSON question   
    Yes. There are many ways you can do that. Here's a quick function that splits the string into a StrArray:
    function SplitJson(JsonStr: String): TStrArray; var i,Start,QCount: Integer; InQ: Boolean; begin Start:=1; for i:=1 to Length(JsonStr) do begin var ch:=JsonStr[i]; case ch of '"': begin if not InQ then InQ:=True else if JsonStr[i-1]<>'\' then InQ:=False; end; '{': begin if not InQ then inc(QCount); end; '}': begin if not InQ then dec(QCount); if QCount=0 then begin result.Add(copy(JsonStr,Start,i-Start+1)); Start:=i+1; end; end; end; end; if i>0 then result.Add(copy(JsonStr,Start,i-Start+1)); end;  
  16. Like
    Czar reacted to lynkfs in Measuretext not doing a great job :(   
    I've noticed the inconsistent measuretext function too.
    However in your case you can use textAlign in the canvas
        LBitmap.Canvas.Context.DC.textAlign := 'right';     LBitmap.Canvas.TextOut(400, 70, s, clwhite);        //400-wdth  
  17. Like
    Czar got a reaction from lynkfs in Mouse Click on w3image   
    I am posting this little sample as it solves a problem we had and maybe it will be useful for someone sometime. We are making simple (sic.) app to allow our franchisees to add their own details to base images.
     
    The images can be quite big and don't fit nicely on the screen so I needed a way to translate mouse clicks from the image. I ran into problems when the images didn't fit the aspect ratio of the image container and the fscontain was screwing with my coordinates. The solution was simple, as it often is. Simply change the dimensions of the image container to fit the aspect ratio of the image data.
     
     
    ImageMouseDown.rar

  18. Like
    Czar reacted to jarto in memo lines ?   
    Ok, lets elaborate. This is pretty universal regardless of programming languages.
    Suppose I just add:
    property Lines: TStrArray read GetLines; ...and GetLines does take the current text and splits it into an array.
    Then you have code like this:
    for var i:=0 to Memo.Lines.Count-1 do WriteLn(Memo.Lines[i]); When the code is run, every time Memo.Lines is accessed, it results in a call to GetLines. So, if you have 1000 lines, the code above would result in 1001 calls to GetLines and 1001 splits of the whole text to an array. This is what my message meant.
    What @lynkfswrote is about a more advanced solution where the memo would store the contents as both text (as it does now) and a separate Lines-array. That would eliminate the performance problem, but it'd introduce other problems like:
    More memory usage as data is stored internally twice. All the challenges to make sure that both the text and the array match, no matter how the memo contents are changed. I haven't tested if @lynkfs solution works and what it requires.
  19. Haha
    Czar reacted to jarto in memo lines ?   
    He must have just written it without testing. ?
  20. Like
    Czar reacted to lynkfs in no-code   
    Setting up a blog in WordPress is a no-brainer of course.
    Setting one up in Smart is pretty easy too. This one repurposes a treeview as a vertical collapsible menu and a series of Google docs in an iFrame. Using Google docs is a bit of a short-cut but it does provide the basics in a single package : perfect formatting capabilities, editing online and authorisation for editing source, or able to comment, or viewing for anyone.
    As for the subject (a no-code/lo-code framework) this obviously is unfinished ('intro' and the beginning of 'framework' entries only). I may do some more work on it when time permits. If you have thoughts on the subject and make it a collaborative effort then let me know.
    By the way, the form under 'Design' is a proof of concept for using the jsPlumb library (included in Smart in the libraries directory). A very useful library, check it out. Panels are draggable, links are connectable by mouse and touch etc...
  21. Like
    Czar reacted to lynkfs in calling external javascript   
    ok, they changed the entry point from a function call to a var, and renamed it to 'math'
    //function mathjs: Variant; external 'mathjs'; var mathjs external 'math': variant; point script.src to 'https://cdnjs.cloudflare.com/ajax/libs/mathjs/5.1.0/math.min.js' and use as before
    (instead of referencing the cdn or a local url you can of course store whatever version of the library you like on one of your own servers and point the script.src to that)
  22. Like
    Czar reacted to lynkfs in calling external javascript   
    this code works
    var document external 'document': variant; var console  external 'console':  variant; function mathjs: Variant; external 'mathjs'; implementation { TForm1 } procedure TForm1.W3Button1Click(Sender: TObject); begin   var Script : THandle := document.createElement('script');   Script.src := 'lib/math.js';   //'https://cdnjs.cloudflare.com/ajax/libs/mathjs/5.1.0/math.min.js';   document.head.appendChild(Script);   Script.onload := procedure   begin     console.log('loaded');     //... do your thing     console.log('1.2 / (2.3 + 0.7) [Execute] = ' + mathjs.eval('1.2 / (2.3 + 0.7)'));   end; end; Obviously there is a difference between the local library and the cdn library. The latter doesn't recognise the function 'mathjs', or its called differently. I'll have a look later on
  23. Like
    Czar reacted to lynkfs in calling external javascript   
    featured demos / console / math expression parser
  24. Like
    Czar got a reaction from jorn in Pixelbuffer   
    Visually it looks interesting. I am getting about 20 fps - it is not clear who I am or what I am doing

  25. Thanks
    Czar reacted to Christian in Pixelbuffer   
    The gameplay is simple. Just click on a part of the map and your player moves to this position. By pressing the space bar you place a bomb (max. 10 bombs can be placed at a time). If you are in Range of the bomb you activate the timer by right mouse click. Aim is to bomb the builders and the building.
    I skip 2 frames in order to have at least 22fps. The performance can be increased by minimizing the for loops in the render procedure and the access to the arrays. It was just a proof of concept how to paint and i'm happy to figured it out.
     
    Christian
×
×
  • Create New...