Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation since 08/18/2018 in all areas

  1. 3 points
    DavidRM

    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
  2. 3 points
    lynkfs

    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";
  3. 2 points
    Czar

    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);
  4. 2 points
    Czar

    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;
  5. 2 points
    vaza

    Code formatting

    Hi Just would like to share a code formatting tip. I have been struggling for a while with code formatting in SMS. I often do refactoring in Delphi but Delphi code formatter was always messing SMS code, especially Html. Then I pressed control + D (shortcut set using GExperts menu) by accident when a procedure was selected and Delphi formatted just the selection. I didn't know that was possible. Now my SMS code is beautifully formatted and easy to read. Hopefully it would be useful for someone. Thanks VZ
  6. 2 points
    lynkfs

    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.
  7. 2 points
    jarto

    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.
  8. 1 point
    jarto

    Size of Components at Runtime

    This could be made a bit simpler by also making ClientWidth and ClientHeight writable.
  9. 1 point
    jarto

    tw3slider mouseup

    Yeah, true, as that component internally uses OnMouseDown, OnMouseMove and OnMouseUp. Edit: Fix will be in the next update.
  10. 1 point
    lynkfs

    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
  11. 1 point
    jarto

    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;
  12. 1 point
    lynkfs

    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
  13. 1 point
    Czar

    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
  14. 1 point
    lynkfs

    memo lines ?

    interesting. Basically you would need to keep Text(string) and Lines(array of string) in sync at all times, and only sync when data changes in either one of them I suppose you could define a Lines array, and override the js push method (for this array only) Lines = [] Lines.push = function(data) { ... update Memo.text with data .... return Array.prototype.push.call(this, data); } and in this override update Memo.Text (or re-create Text from Lines). That would cover the use case of Memo1.Lines.Add(data) and I suppose similarly for deletes. The other way around (changing Text instead of Lines) you would need to extend the SetText setter to update Lines (and not get into an infinite loop) Looking forward to see your solution
  15. 1 point
    jarto

    memo lines ?

    He must have just written it without testing. 😀
  16. 1 point
    lynkfs

    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...
  17. 1 point
    jarto

    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.
×