Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by lennart

  1. No that is a TW3Dataset implementation. Im talking about a grid
  2. If you want pixel perfect scrolling, use iScroll. It has been 5 years in the making and is the best. The SMS adaptation can be found on my github repo: https://github.com/quartexNOR/smartpascal/blob/master/Casebook/qtxScrollController.pas and iScroll.js (copy to $install\libraries folder: https://github.com/quartexNOR/smartpascal/tree/master/Casebook >> Do you mean to create rows and cells but not add it to table (delay appendChild till row comes into view)? That could be a good idea, it should save second or two on large table. This is what we do in the DB grid that will be in the next update
  3. There seems to be a missunderstanding about the VJL (its not called SCL, but VJL). First of all, libraries like jQuery has little to offer the standard object pascal model. Like the name implies jQuery is a "query" system, designed primarily for looking up named identifiers in the DOM, sorting them, extracting groups of elements and so on. JQuery has naturally grown these past couple of years, but its still based on a model where the code "does not know" the handle of element it should act on. Secondly, when it comes to UI widgets: most frameworks out there are literally "skin deep". They make a button look good, use fancy colors and so on -- but the controls themselves have no depth. in 90% of the cases its just a <div> tag or something else "dressed up" to look like a real control. This would be the exact opposite of how classical object pascal works. The entire VCL and LCL (and before that, turbo vision and its clones) were based on the notion of classes -- where the class "knows" the handle it represents, from cradle to grave (so to speak). The entire point of the VJL was to setup a somewhat familiar environment -- so people can port over Delphi and LCL components to HTML5. Focus has not been on integrating with JS libraries so much. That came later. Having said that, wrapping JS libraries is very easy. Especially using the typescript importer. But the VJL is about writing new components and getting whatever functionality you desire in object-pascal form. Take something simple, like a listbox. It's super simple to make this in SMS, and styling it to look exactly like jQUI or whatever takes minutes. But the value of such controls is not in the "bling", but rather in the depth of the components and amount of methods you can use on the lists. The initial control base was actually just meant as an example. We figured that most people come from Delphi and will port over various component from Delphi or Lazarus. The look of things is just CSS, which is something you learn in 1-2 days if you get a good book. Naturally VMT based code is going to be bigger than hand-written non-oop based code. Delphi was also called "bloated" when it came, because back then everyone was doing turbo pascal with 50% assembler. You can always find ways to "cut down" the size of something, but the question is price. If all you want is the JQuery UI, that is not an RTL issue, but a styling issue. Re-implementing JQUI for SMS would be very easy, including whatever effects or visual feedback it has to offer. TW3CustomControl in combination with smartcl.effects.pas gives you a lot of power to create complex and dynamic visual controls. And since we have classes and instances, we get to attack the problems from a better vantage point. I would suggest that we take a closer look at the jQUI css scheme. Most of it seems portable and can be used to skin SMS applications out of the box. In fact, the form-scrolling animation we use was written to be nearly identical to the JQUI version. And naturally, last but not least, SMS was created to build mobile applications using Phonegap. It has grown a lot these past 4-5 years, and now it can target both NodeJS and NodeWebkit, but the basic principles of object pascal will always be there. Classes, instances knowing the handle of their managed controls. More than anything, we need object pascal versions of popular widgets, not wrappers.
  4. There is a small podcast on Smart Mobile Studio at Soundcloud: https://soundcloud.com/jon-aasenden/smart-mobile-studio-cast-1
  5. A switch between http and https is essentially not a SMS problem, but a server setting. Its like switching between tape and cd, it wont affect logic or protools, but rather how the artist chose to publish the music. In your hosting account or server admin console, define https instead of http. Should not be more difficult than that.
  6. lennart


    Guys, i have it on a disk somewhere .. easier to just PM me on facebook or send me an email Was it anything in particular you wanted? There are a few controls there like the header that slides in the back/next buttons (rubber band effect)? Well, just email me if you want the code, ill have a look around my drives for it
  7. I think we may be mixing eggs and apples here, but outside RTTI you might want to fall back on the system units. If you have a look at system.types.pas You will see that the datatypes from SMS point of view, is to a large degree defined just to be "compatible" with some legacy code, but not binary compatible. Javascript doesnt really have all the datatypes we are used to, and like christian says, integer will map to int64. Which also is the case for byte (!) The types javascript exposes (except Microsoft who exposes more, but they live in their own galaxy) are: TW3VariantDataType = ( vdUnknown = 1, vdBoolean = 2, vdInteger = 3, vdFloat = 4, vdString = 5, vdSymbol = 6, vdFunction = 7, vdObject = 8, vdArray = 9); This is why the system.types and system.types.convert units are so important. Without them SMS would suffer the same problems that haunts quite a few javascript libraries (even google gears got that part wrong), resorting to hacks like storing bytes as charcodes just to force data to behave as it should under native languages. I solved it by pre-allocating a small untyped buffer when your application starts, this we use whenever we convert between javascript reality and native reality. You can create a data-view into untyped buffers of an intrinsic type, which is very very fast (!) This allows us to support faster datatype conversion than common JS libraries. And with that we also got support for blue-pointers (fake pointers based on offsets into a view), allocmem, move(), Readmemory. All of these form the basis of streams as we know them under Delphi or Freepascal. So you might want to check out these units while you are on the subject (and there is often comments of importance in the source): System.Memory System.Memory.Allocation System.Memory.Buffer But back to your problem Like christian says the javascript virtual machine should default to a fixed value-type (int64). But there have been cases where Firefox and Safari mobile builds have deviated from this. Why I have no idea, but i presume to save memory perhaps under embedded platforms. Could be they just forgot to disable a conditional switch, who knows. The behavior firefox (early 2015) and Safari Mobile (mid 2015) demonstrated, was that they seemed to pick datatypes not exposed to the JSVM, based on the first value you assigned to a variable. Ex: var bytevalue = 12; //should be int64 but was a single byte (!) var bytebreaker = 256; // Here it would clip bits beyond 0..15 var wordbreaker = 65539; // Here it would clip bit-shifts beyond 0..31 var longbreaker = 2147483648; // here is finally picks a signed int64 (!) I only noticed this when implementing a codec class for RC4 and Blowfish encryption where bitshift is used. You can imagine the havoc this caused when we started writing code that relied 100% on concurrent behavior regardless of browser. And not a single note to be found in the mozilla repository or webkit. When I upgraded my development machines around december, having coded around the problem, the behavior was finally gone. Although Safari suddenly dropped support (read: will not allow you) to create Uint8ClampedArray, so we had to fall back on Uint8Array and make sure bits from one byte doesnt bleed into the next. Stick to the VJL if you can Unless your work involves RTTI (which i presume it does hence your post here), you could alternatively use Variant.Datatype() to get the JSVM type. Please note that the code below is directly from my dev-machine, it's not yet in the repository or update channels. It has to pass QA testing before it's commited to our servers. But if it helps you out in some way, then feel free to use it at your own risk. I always test code on Firefox, chrome, Safari, IE, Spartan and opera (and the same on mobile devices when available). Also, if you have a faster version or improvements in any way, feel free to post it here. We absolutely welcome your input! Hopefully some of what i have written here helps you out, or at least gives you a better overview of related functionality. VarType() however requires a deeper fix, since that is a "magic" function managed by the compiler. But you are indeed correct that it should be in-sync with the rest, so I will forward it to Eric, our compiler wizard. Using it is quite simple: 1. Include System.Types in your uses clause 2. Do a simple cast to get access to the helper (if its not a variant to begin with): procedure TForm1.DataTypeTest; var LTestValue: Integer; begin writeln("------- Datatype test -------"); writeln("Type = " + Variant(LTestValue).Datatype.ToString() ); end; Here is the code, as you can see it does not take delphi or c# into account, but is only interested in SMS's point of view. type (* These are essentially the types common between browsers. Sadly the typeOf() method can have char-case differences. External references: ==================== https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof *) TW3VariantDataType = ( vdUnknown = 1, vdBoolean = 2, vdInteger = 3, vdFloat = 4, vdString = 5, vdSymbol = 6, vdFunction = 7, vdObject = 8, vdArray = 9 ); TW3VariantHelper = helper for variant function Valid: boolean; function Defined: boolean; function UnDefined: boolean; function Equals(const Reference: variant):Boolean; function IsObject: boolean; function IsArray: boolean; function IsInteger: boolean; function IsFloat: boolean; function IsBoolean: boolean; function IsString: boolean; function IsSymbol: boolean; function IsFunction: boolean; function DataType: TW3VariantDataType; end; //############################################################################# // TW3VariantHelper //############################################################################# function TW3VariantHelper.Valid: boolean; begin asm @Result = !( (@self == undefined) || (@self == null) ); end; end; function TW3VariantHelper.Equals(const Reference: variant):Boolean; begin asm @result = (@self == @Reference); end; end; Function TW3VariantHelper.Defined: boolean; begin asm @result = !(self == undefined); end; end; function TW3VariantHelper.UnDefined: boolean; begin asm @result = (self == undefined); end; end; function TW3VariantHelper.DataType: TW3VariantDataType; var LType: String; begin if Valid then begin asm @LType = typeof @self; end; // Sooo want to use a lookup table here, but it wont work // due to the similarities between type-text. There is also a char-case // difference between IE and firefox that could make a 1:1 dictionary // lookup un-realiable. Hence the brute-force lowercase + case swich case LType.ToLower of 'object': begin // If it has length, it's an array // JQuery actually screwed this up (LOL!) if not (self.length) then result := vdObject else result := vdArray; end; 'function': result := vdFunction; 'symbol': result := vdSymbol; 'boolean': result := vdBoolean; 'string': result := vdString; 'number': begin (* $NEXT-UPDATE: we should add single, double, int32 and so on to the checking. First of all to get rid of our near identical type-list in system.types.convert, but also to simplify documentation. *) case ( round(self) <> self) of true: result := vdFloat; false: result := vdInteger; end; end; 'array': begin (* $NEXT-UPDATE: I would suggest we expand datatype information into a record. Array doesnt really mean much, and each element in an array can have a different type. But we can at least detect if it's a native array (like Uint8Array) or a plain javascript array. Something like: TW3ArrayType defines if it's an array connected to a native, untyped buffer -- or just a normal javascript array type TW3ArrayType = (atNative, atJavaScript); TW3DatatypeInfo = record tiType: TW3VariantDataType; tiArray: boolean; tiArrayOf: TW3ArrayType; end; *) result := vdArray; end else result := vdUnknown; end; end else result := vdUnknown; end; function TW3VariantHelper.IsObject:Boolean; begin asm @result = ((@self) !== undefined) && (@self !== null) && (typeof @self === "object") && ((@self).length === undefined); end; end; function TW3VariantHelper.IsSymbol:Boolean; begin asm @result = ((@self) !== undefined) && (@self !== null) && (typeof @self === "symbol"); end; end; function TW3VariantHelper.IsFunction:Boolean; begin asm @result = ((@self) !== undefined) && (@self !== null) && (typeof @self === "function"); end; end; function TW3VariantHelper.IsBoolean:Boolean; begin asm @result = ((@self) !== undefined) && (@self !== null) && (typeof @self === "boolean"); end; end; function TW3VariantHelper.IsString:Boolean; Begin asm @result = (@self !== undefined) && (@self !== null) && (typeof @self === "string"); end; end; function TW3VariantHelper.IsFloat:Boolean; begin asm @result = ((@self) !== undefined) && (@self !== null) && (typeof @self === "number") && (Math.round(@self) != @self); end; end; function TW3VariantHelper.IsInteger:Boolean; begin asm @result = ((@self) !== undefined) && (@self !== null) && (typeof @self === "number") && (Math.round(@self) === @self); end; end; function TW3VariantHelper.IsArray:boolean; begin asm @result = ((@self) !== undefined) && (@self !== null) && (typeof @self === "object") && ((@self).length !== undefined); end; end;
  8. Hi. This bug will be fixed. I am not sure what went wrong there, but we are investigating it. As for copy & paste, that is not the case here. Javascript is async, nothing is ever created "at once". No control or form is ever ready until after the constructor has finished, the prototype constructed and finally injected into the DOM. This is why the callback and setTimeOut calls are there. The second procedure checks if the form already exists or is being created to avoid possible duplication, just in case someone calls this method by mistake. After changing project options, did you remember to save the project before compiling & running it again?
  9. Cool! Nice work! WIll you make a package with these controls? Also, just a tip: If you inherit from TW3CustomControl instead you can cut the code in half. TW3CustomControl creates a DIV by default, so you dont need to override makeElementTagObj() Also, the code in the resize event only applies to TW3GraphicControl, if its a pure DIV you dont need it. It actually has no impact since you are basically doing width:=width and height:=height. To make the control display itself correctly when its ready in the DOM, use the class helper for TControlHandle procedure TMyControl.InitializeObject; begin inherited; Handle.ReadyExecute( procedure () begin show; end); end; Keep up the cool work!!
  10. lennart

    Resize event

    This happens because all forms are hosted on a display, which in turn is hosted inside a root-container. The organization is as such: Display Container (TW3Display) Display View (TW3DisplayView) Form This organization has to do with animations and moving forms in and out of view. You can also create components directly on these host containers (they are TW3CustomControl based after all). So if you want a static header, like iOS apps typically have -- one that is not affected by scrolling or moving between forms, just create it in TW3Display(!). Then the toolbar will be completely unaffected by whatever happens in the form container (which is subject to CSS3 GPU scrolling). So this architecture is there for a reason, although they do cause a couple of extra resizes on startup. But that will change very soon. More technical, why does resize fire at all before things are fully visible? Well, browsers differ, but there is always a short delay between when an object is created by your constructor - and when the visual element is injected into the DOM and fully ready to be used. This can cause some confusion when coming from Delphi, because WinAPI does not issue events before everything is ready (which sadly JS does!). Naturally, when TW3Display resizes it forces TW3DisplayView to resize as well -- which in turn causes the forms to resize. The resize that you get after a couple of ms is the one issued when the DOM is actually 100% ready. So the 3 first should actually never fire at all. But what you should do in all your code, is to check the csReady component state. Always. Procedure TForm1.Resize; begin if Handle.Valid and (csReady in ComponentState) then begin // Ok, form is now setup -- but it can take 1-2 ms before the browser has realized the controls! end; end; This is something we have worked on a lot! In fact, i re-wrote the whole form/display system at least 4 times trying to get rid of it. It used to issue 10-20 calls, so getting it down to 4 took a lot of work, considering we target a myriad of browsers, builds and platforms. But in such a complex system, fixing one thing can often cause problems with legacy code. So we decided to opt for some manual labour like you will find in C#/Mono and iOS development. There you have to check everything. So i think we found a good balance. Tips: 1. Just because an object has been created, does not mean its fully realized in the DOM (mozilla is better than chrome here) 2. Remember that all handles have helper classes which gives you functions to test them (!) 3. Always check references before using them in resize handlers (always!) procedure TForm1.Resize; begin if Handle.Valid and (csReady in ComponentState) then begin end; end; All TW3Components have the ComponentState SET, so it will work on all visual elements. To Check if the document is ready, Also, when updating content, use beginupdate/endupdate: beginUpdate; try PopulateNewObjects; finally AddToComponentState([csSized]); //tell the system to issue a resize EndUpdate; end; Low-level work: All handle types has helper classes. And TW3ControlHandle has the best: (* Helpter class for control handles *) TControlHandleHelper = strict helper for TControlHandle function Defined:Boolean; function UnDefined:Boolean; function Valid:Boolean; function Equals(const Source:TControlHandle):Boolean; function Ready: Boolean; function HandleParent:TControlHandle; function HandleRoot:TControlHandle; procedure ReadyExecute(OnReady:TProcedureRef); procedure ReadyExecuteAnimFrame(OnReady:TProcedureRef); end; So all the code normal JS coders use to avoid this -- we have also. But it requires you to get into the RTL a bit (just like we all did with VCL) to get to grips with it. Future work ========== The above topics are JS/browser problems, not RTL problems. This is just how JavaScript and the DOM works. Any Handle/control will never be ready until after the constructor finishes, which is why the 3 initial resize calls are very hard to get rid of (!) But we keep on updating and making fixes, so it will be taken care of at a later stage. Hope this explains it
  11. This is very, very odd. What browser are you using? The normal scroll "rule" if we can call it that, is that there must content within that exceeds the container width/height before scrolling becomes enabled. So.. FBox := TW3CustomControl.Create(self); FBox.SetBounds(10,10,400,400); FContent := TW3CustomControl.Create(FBox); FContent.SetBounds(10,10,800,800); //This causes overflow In the above pseudo code, scrolling would only work after FContent has been created. We have used px-numeric here since the beginning, sounds very odd that this suddenly should not work now. What CSS do you use? Sure you havent disabled scrolling in a sheet?
  12. lennart

    Form Entry Effects

    This is a silly naming convention i agree. It was actually taken from the C# API i was using with Mono (the first versions of SMS was heavily inspired by mono/monotouch). And it defines how the "new" form enters rather than how the current form leaves. So feFromRight means that the new form will come in from the right etc. etc. And yes, new and cool animations are abound, especially with the new Tweening library. You can check out the base-code at github: https://github.com/quartexNOR/smartpascal If you code some cool effects let me know, we can include it!
  13. That game is easy to check collision for, because each element is a square so thats just a TRect.Contains or overlap test. What you want is a routine that can take any shape or outine, based on the graphics you assign to each element. e.g: FMySprite.background.fromUrl('res/shaceship_01_01.png'); //sprite type 01, animation 01 FMySprite.Mask := CreatePolygonFor(spTypeSpaceShip);
  14. Well, it depends on the type of application. If its a purely canvas based game then classical techniques (to some extent) applies. You usually do masking/scanline to detect collisions but that may be to slow here (its the type of thing you would optimize with lookup tables and assembly in native scenarios). You can also have a polygon outline for each sprite and use our polygon testing code, which is fast but tiredsome to work with (perhaps create an editor for outline drawing). The fastest is naturally a purely mathematical approach if that is possible, like christian mentions. Ultimately an outline technique would be the best (most accurate) no matter what, but it does require you to define a shape that kinda fits each sprite-type. So it all boils down to how complex your graphics is. Like in those old shoot'em ups where collision was primarily done on the ship body, the wings could collide without people paying to much attention to it. For DIV (TW3CustomControl) based games with Sprite3D, Well -- it may be best to check some of the games written in Sprite3D to see how they do it? Essentially a DIV will always be rectangular despite background graphics or content. So some form of polygon mapping will probably be the fastest technique there as well. Here i would suggest you have a peek at how purely JS coders solve this -- but my gut feeling is that a well written polygon overlapping routine would be the fastest. Depending ofcourse how many objects you have on screen at any given point. The old game engines from the Amiga days try to keep it down to 32 moving sprites at any given time, parrallax scrolling with max 2 moving and 1 static layer -- i would most likely use mappy with 2 layers + 1 parrallax moving background layer. Well, hope it helps! And let us know what you code up with, i've been thinking about this myself earlier on.
  15. Resize for canvas under HTML5 is very different from ordinary DIV based components. First of all, altering the width/height of the container does not change the canvas-content size. The fact is that both the canvas.width and container.width must have the same value. Hence, some events are abstracted, because the application will resize whenever it is needed. What you can do is add an event manually with W3_AddEvent() from SmartCl.System.pas The syntax is: procedure w3_AddEvent(a_tagRef: THandle; a_eventName: String; a_callback: TProcedureRef; a_useCapture: boolean = true); So you can use it as such: w3_addevent(self.handle,'resize', procedure () begin self.invalidate end, true); if you are adding this to the constructor, you may want to wait until the DOM is ready: self.Handle.ReadyExecute( procedure () begin w3_addevent(self.handle,'resize', procedure () begin self.invalidate end, true); end; The ReadyExecute() adds a watcher to the handle, and when the handle is valid (the DOM is ready and the element created) it will execute a section of code. So now you can safely place this in the constructor without getting errors or strange behavior. Note: You may want to use Beginupdate + AddToComponentState([csSized]) + EndUpdate around the invalidate call, since that will force a recursive refresh if you are mixing with normal controls on the same container.
  16. The easiest way to learn how to make components is to look at the RTL files. Start with something simple, like TW3Panel, then have a look at TW3Label and so on. A simple component is just: type TMyComponent = class(TW3CustomControl) protected procedure InitializeObject;Override; procedure FinalizeObject;Override; procedure Resize;Override; end; Next, to style it, add a style with the same name as the component to the CSS files, like this: .TMyComponent { background: #FF00FF; } And thats essentiallty it. To make it do something you populate it with child objects (or set the events, override the event handlers etc), and make use of the beginUpdate() / endUpdate() mechanisms (together with AddComponentState) to avoid updating the view to much. If you have made components with Delphi before, some of these things should be familiar. Again, the best way to learn is by looking at the components in the RTL. What "basic concepts" of SMS are you struggling with?
  17. That is a good question! I arranged a "Raspberry PI 2" contest last summer on component writing, but sadly few people seem eager to write their own components, so we had to pospone it. BUT, it's a good idea to hold another compo! Let me think up something cool and we'll get on it soon!
  18. My blog has functioned as, well, my personal development blog. This is scheduled to be separated this month, so from now on all things SMS will occur on the main website (here). As for news, where to begin! First, we have established a company, a proper stock based company. Secondly we are seeking investors for the company, which takes up a lot of our time. And third we have two updates in the pipeline. The second update represents a huge change to the RTL, not code-breaking stuff, but a huge re-organisation for better separation between nodeJS and purely browser based code. We want to be able to use as much as possible under Nodejs without problems. And then there is the IOT project, which i havent written so much about yet. Essentially a customized Linux distro running on ARM which boots directly into WebKit and runs your applications in KIOSK mode. This is powered by a nodeJS service layer giving you full access to Linux from Smart Mobile Studio. But this is more interesting for IOT development and Raspbery PI "makerbots" so to speak. And last but not least, our cloud ware, which i will write more about shortly in a full article, as it represents the future of SMS and opens up a whole new world for all of us. But the details will have to wait until after the next update, which should be out this month.
  19. I have already answered the post that shane had here, which was based on a missunderstanding about how the childCount works (actually, the same code would break in delphi as well). I am unable to re-create the error you report here? I added this to my form's private section FForm: TW3Panel; Then i added two buttons on the form, and then hook up their events like this: W3Button3.onClick := procedure (Sender:Tobject) begin FPanel := TW3Panel.Create(self); FPanel.setBounds(32,200,200,200); end; W3Button4.OnClick := procedure (Sender:Tobject) begin if assigned(FPanel) then FPanel.free; end; And they work just fine. As for the listbox problem --- you must remember that when you free a component, its also removed for the internal objectlist. This means that Child-Count will change, and also that any reference to the panel will be invalid from then on. If you are doing a resize call directly after deleting the object, it may be that you need a small delay so the DOM have enough time to remove it. Have you tried calling with W3_SetTimeOut?? e.g: var item := GetSelectedItem; Item.free; w3_setTimeOut( procedure () begin Resize; end, 100); You should also use the beginupdate and endUpdate() mechanisms here BeginUpdate; try //delete item here AddToComponentState([csSized]); finally EndUpdate; // automatically calls resize for you end; If you can post your code here, i can have a look at it?
  20. The problem is obvious: When you call free on an item, its removed from the internal queue, hence the array for/next loop goes out of sync. When you delete item #3 and then jump to item #4, you actually miss an element. Because when item #3 is deleted, item #4 becomes the new item #3. You have to adjust the index and take height for this: var x:Integer =0; while (x<GetChildCount) do begin var obj := GetChildObject(x); if (obj is TW3Panel) then Begin obj.free; continue; end; inc(x); end;
  21. Well, on top of my head it would be easiest to do this in JS: procedure W3Form1.w3button1click(sender:TObject) begin asm document.src = "http://www.google.com"; end; end; Or something to that effect..
  22. The compiler has seen a massive overhaul in the latest beta, so yes, it could be a bug there. We shall ofcourse have a look at this. I presume you are using the latest beta right? Also: The new RTL is much, much more complex than any of our previous releases. The introduction of TStream and binary data access is not just "a few small classes". Streaming depends on memory allocation, being able to access and read data on byte level -- which in turn drags in dependencies like System.memory.pas, System.typeCon.pas and other units which contains a lot of code. Also, TStream support has been added to various components so there is an overall increse in code-size. As a general note: When developing, always generate with comments, RTTI and type/range checking ON. This makes debugging and locating errors easier. When everything is tested and working - you compile the final build with this OFF Remember to apply code-enfuscation and code-packing to make the final JS as compact as possible But the source of the larger size on executables is, like mentioned, the introduction of low-level sub systems like TStream, TAllocation and everything dealing with memory management. Javascript doesnt really have raw memory access, so it brings a huge benefit to Smart programs to have this. It puts us en-par with many native languages out there, even Delphi and FPC itself. Having said that, I am architecting a very different RTL right now. It wont be a part of Smart for a while, but it will have a huge impact on size and complexity when the transition is complete. We intend to phase in more and more of the new architecture over the next couple of years. Since more and more platforms support JavaScript, it's important for us to be compatible with as many of these as possible. This means that we are slowly moving from a purely VCL like RTL that only targets phones and tablets, into a service oriented RTL that can run even on non UI based platforms. The latter means that you regard the RTL as a collection of services which may or may-not be supported by the system. The services you dont use naturally wont be compiled into the final JS file at all, saving a lot of space! So where we now have loads of classes and functions stuffed in a single unit -- the new model will have these divided into more files, in classic dependency injection style. Example: Today system.memory, system.stream and system.typecon make up the gist of raw binary access to data. In a service oriented RTl these will be resolved to more files, like this: System.Streams System.MemoryStream System.StorageStream System.StringStream System.Memory System.Memory.IO System.Memory.Buffer System.Types System.Types.Convert System.Types.Serialization In the above scheme the first file (system.memory or system.streams) contains the actual service code. While the individual files starting with the same name contains isolated API's or objects exposed by the service. These are linked into the code only if you include them in your uses list. So you will have a much more fine grain control over what goes into your JS binaries. Writing SOA code is very similar to traditional Delphi for WinAPI: var StreamService: IStreamService; if PlatformServices.GetStreamService(StreamService) then begin var Stream: IStream; if StreamService.CreateMemoryStream(Stream) then begin SaveData(Stream); end else raise exception.Create(PlatformServices.GetLastError); end;
  23. We are working and a new release should be ready VERY shortly. In fact, only two cases left in the ticket box for the update These months have been hectic, with summer holidays taking a huge chunk of our time and also two members of the team has moved to new locations. Also we are preparing to push SMS to the next level - so if we have been quiet there are good reasons for it. But, we are not going anywhere and work is being done on a daily basis.
  24. lennart


    The problem in your example is that you attempt to resize (the setsize call) the DIV during the creation of the form. Javascript is ASYNC which means that there is no real way of ensuring that the resize is executed during creation (the handle might not be ready).ยจ If you have a look at my library code you will notice a lot of: Self.Handle.readyExecute() calls from the constructor. What this does is essentially to "wait until the handle is ready and the component setup, then execute this code". This is the only way to ensure that startup code is executed at the right time. But just to get things working, try this: 1. Place the setSize() call in the OnReSize event handler for the form 2. Place a button on the form, and execute the ASM section there JS objects always have to be setup and accessed in specific steps. Since all JS code is executed ASYNC, this means you have to use the methods in TW3CustomControl (initialize, resize etc.) more closely than under other languages. If I was you I would create a custom-control (just type it in above the form code) and initialize that. Then later when you have it working good you can start to test boundaries.
  • Create New...