Jump to content


  • Content count

  • Joined

  • Last visited

  • Days Won


lennart last won the day on November 15

lennart had the most liked content!

1 Follower

About lennart

  • Rank

  • Birthday 09/21/1973

Contact Methods

  • Website URL

Profile Information

  • Gender
  • Location
    Vestfold, Norway


  • Company name
    The Smart Company AS
  • Sector
    Information technology
  • Position
    Lead developer

Smart Mobile Studio

  • Edition
  1. Working with css, how to

    I just explained how it should be handled. And css is cascading, meaning that you define both for webkit, ffox etc. in the same file - you dont need the browserprefix in a static file. Just put it in a css file, add it as a resource and then load it in using TW3Storage functions.
  2. Working with css, how to

    Someone posted a technique for injecting CSS, and while I normally dont go around correcting - the code posted was so bad that it could easily break the application. Smart has classes for css that are easy to use. Always check the RTL folder, and search in the class-browser. So if you are looking for CSS stuff, then search "CSS" in the class browser. Quick intro A stylesheet is just an object, like everything else in the DOM (document object model). The browser will take your css-files (if listed in the html) and load them in, then they turn up as objects you can access. But, you can also create these objects yourself and feed in the CSS as a string. You can even create single rules (or styles) as objects and manually populate them. Few does this since its easier to use a string. Loading CSS The easiest way to load an extra CSS file is to use the LoadCSS() method in TW3Storage. This is a class function in a static class, so you dont create an instance of TW3Storage first. You will find this class in SmartCL.FileUtils. An example for loading css looks like this: TW3Storage.LoadCss('thisurl', procedure (const FromUrl: string; const ObjectHandle: THandle; const Success: boolean) begin if success then begin writeln("css loaded"); end; end); Notice the parameter "objecthandle" in the anonymous callback. This is a handle to the created stylesheet object. You dont need to care about that, but if you should want to manually access the stylesheet DOM object after loading - then this is the easiest way to do it. The second method is to create a stylesheet class: var sheet := TW3StyleSheet.Create; sheet.append(#" .mystyle { background-color: #FFFFFF; }"); This class has several add methods, but it also has a very clear "Append" method, allowing you to add chunks of css style code. So as you can see, getting external css into its own stylesheet is very simple, and class based - rather than hacking into a stylesheet you simply presume will be there. The global stylesheet When your application starts a global stylesheet is created. This is not the theme stylesheet, but a secondary stylesheet that controls and units can use to stuff their dependencies into. All our effect css is stored in this secondary stylesheet. If you just need to store a couple of new styles or define some animation, then its overkill to create a third stylesheet object. Just append your code to the global stylesheet instead var globalstyles := TW3StyleSheet.GlobalStyleSheet(); globalstyles.append(#" .TMyCoolStuff { some-value: 12px; }"); The whole point of Smart is to create standard ways of accessing otherwise cumbersome things. Adding & removing styles from your controls TW3Stylesheet contains more class members that should be interesting: AddClassToElement RemoveClassFromElement FindClassInElement So whenever you want to add a style to a class, these are the best to use. You can also remove and check if a style is applied to an element with these. They take the control-handle as a parameter and should be fairly straight forward to understand. Well, hope it clears up a few things!
  3. Sleep?

    TW3Dispatch.Execute( procedure () begin // your code here end, 1000);
  4. OK, I have issued a fix which should go out with the build later today or tomorrow (not my table so the manager has to deal with that). I noticed several minor mistakes. For instance, the callback "prepare" in the overloaded ShowDialog method never fired. Delayed callback failed because the method was a class method, marked as static, which means the variables are killed on exit (hence the bug above). Everything is now moved into a normal class, TW3DialogManager, which is available from TW3CustomApplication (or just, application). The Showdialog methods are still exposed as usual, so you dont need to change anything. About adjusting a dialog You asked earlier how to change the glyph and glyph color on a dialog. I must apologize because I did not know the callback didnt fire. But the way you would do this is as such: W3Button1.OnClick := procedure (Sender: TObject) begin application.ShowDialog(aoYesNoCancel, procedure (const Dialog: TW3Dialog) begin Dialog.Header.Caption := 'The header'; Dialog.Text.Caption := 'The text!'; Dialog.Glyph.GlyphType := lgtFontAwesome; Dialog.Glyph.GlyphColor := clWhite; Dialog.Glyph.GlyphId := 'fa-5x fa-exclamation-triangle'; end, procedure (const Dialog: TW3Dialog; const DialogResult: TW3DialogResult) begin writeln("You picked:" + DialogResult.ToString()); end); end; The dialog contains a "glyph" child control, this is of type TW3GlyphContainer (so you must include the unit SmartCL.GlyphContainer if you want to play with this). As you see you have properties for everything here, like GlyphColor. And you need to use the normal Font-Awesome CSS codes to pick the image you want. Simply visit: http://fontawesome.io/icons/ for a list of available glyphs, and set the code(s) as you like. The size is determined by "fa-5x" (5 times the ordinary size). Note: You can also use this in labels. If you set the caption of a label or a button caption to: W3Label1.Caption := ' <i class="fa fa-free-code-camp" aria-hidden="true"></i> Hello world!'; You get a nice fire glyph before the text The fix should be in circulation shortly -- cheers!
  5. I think i can fix this. From what i see above, i have used TW3Dispatch to kill the dialog after the main procedure has been closed. As I look at it now, i realize that the garbage collector can actually eat the Dialog & BlockBox objects since our "free" code executes after the procedure has exited. It would have been different had the dialog + blockbox been fields in a class, then the values would have been safely stored there -- but since they are local variables, the JS runtime gobbles them up on exit and they are in effect "NIL" when i try to access them 100ms later
  6. Allegro for Smart Mobile Studio (Yay!)

    This should be fixed now. Having said that, and had a look at the latest allegro sources, our code is actually faster! In the previous update I added lookup tables to make RGB -> Color .. Color -> RGB close to instantaneous. Allegro uses expensive and slow text-to-value conversion (or worse, variant which is the default value type in JavaScript). Seondly, allegro is just a thin wrapper over Canvas2d, which is exactly what we have as well - but we have added a lot more features. The tile/block copying code we have is from a demo library that is much faster than allegro ever was. We also give you direct pixel access via TW3ImageData, something allegro doesnt event support. It does a slow and simple setpixel() style call. You could probably inherit from TW3ImageData and implement line, circle, fillrect etc. like you would do with a DIB in delphi -- and it would beat the crap out of HTML5's canvas even. I was going to do that earlier but my time is limited with so much to do. If you look around the RTL you will find all the pieces you need that match and surpass allegro. But, the more the merrier, so I do see the idea of having support for it. Quite a few C games that could be ported I guess, as long as the logic is vanilla C and pointers is kept at a minimum. We have support for pointers btw -- check out the memory buffer classes and "blue-pointer" scheme. I dont think any JS system does what we do there at all. Just my two cents
  7. New Themes ?

    If you want to handle everything yourself, then you can shortcircuit the system with: type TMyButton = class(TW3Button) protected procedure StyleTagObject; override; end; And then just reset the whole theme: procedure TMyButton.StyleTagObject; begin inherited; ThemeReset(); end; This will kill theming on that control. But it will still try to match with a CSS style with the same name (TMybutton). Here you can just load in a stylesheet you control instead: // This code goes well in your TApplication.ApplicationStarting() // In new projects there is a "unit1.pas" file that contains your unique application object uses SmartCL.FileUtils; TW3Storage.LoadCSS('res/mycssfile.css', procedure (const FromUrl: string; const ObjectHandle: THandle; const Success: boolean) begin if Success then writeln("My css is now loaded!"); end); Once loaded the control's name will match up with the .TMyButton {} style you have defined there, and voila - you have the best of both worlds.
  8. Styling Tw3Dialog

    Ill add a callback with the dialog so things like this is easier to change
  9. Styling Tw3Dialog

    It should already be included. It fails because you now have it in two places. PS: You can add webfonts in the project dialog, but font-awesome is a permanent part of the system. Its standard for JS based products like Indy is to delphi. When we go out of alpha we will drop the cloudflair link and include the actual file instead. The easiest way to set the color for the font, is to change the font color either in the themefile or in the font-awesome tag. If you look in the SmartCl.GlyphContainer unit you will see how i have done it there.
  10. New Themes ?

    RecursiveElk: Im working on the documentation, but in general: no, there is no way to set a border for everything. You will have to write your own skin for that - or do a recursive function that clears the theming from a control, and then apply your style instead. You can call the thethod "ThemeReset()" to completely remove any theming from a control. If you also set StyleClass := "" then you essentially have a clean, non styled element. Perhaps that will be easier to style if you want something unique. What I would do is the following: Start with the Default skin (ubuntu) file and check the "Use custom css" to get a copy into your project Change the theme element to use whatever palette you want Add your border somewhere (you can also just load in a second stylesheet if you like) With this done I would simply inherit out the controls for my project and use those instead. Override StyleTagObject() in each and set the theme-border to "none" then add your custom borderstyle via TagStyle.AddStyleToControl(Handle, nameofstyle). This may sound like much, but we are talking one procedure per control. You may use a 100 buttons in your program, but you only have to define it once. Writing a new themefile and adapting to the regime sounds easier to be honest. IElite: A theme is made up of smaller parts. When you think of it, a theme engine is just a clever system that keeps track of these parts and makes them available to you. So in our theme scheme we have the following parts: 14 different borders 10 different background types 4 different font sizes Each of these parts is made to be used by one of our 3 control-types. When making the theme I found that we essentially have 3 types of controls, and this seem to be how others organize their systems as well. Both Apple, Android and Linux visually operate with 3 types of controls: Normal controls (button, editbox, checkbox etc) Toolbar controls (toolbutton, seperator and whatever we add in the future) Dialog controls (dialog button and controls styled to catch the users attention). Why should I use this stuff? The idea behind the theming are many, but the jist of it always bakes down to: Make your application look good Concurrency in style Ease of use, making it possible to create new controls that adapt to whatever theme is set The concurrency part is probably the most important to get here. All the theme elements (border, background and font) is made to match its counterpart. For example, DecorativeBorder and DecorativeBackground will always compliment eachother regardless of what skin you use. Same with ButtonBorder and ButtonBackground. The important part here is that each theme-file (css file) defines the same names, but they naturally look different from theme to theme. But if you stick to the regime and try to use the pre-defined borders etc. as much as possible in your own stuff - then your customcontrols will survive between skins. So you can change between Apple, Android and Linux without problems (and more in the future). While iOS seem to be utterly flat and soul-less these days, most UI styles need different borders and small changes to create a living, vibrant look and feel. The reason I prefer the older android theme is because it has a more solid feel than the latest, which is a poor mans copy of iOS. When we made the Apple skin we essentially had to delete most of the stuff in there, because iOS is just flat as a pancake. Button-borders and list-borders are not visible etc. etc. Clearly Apple dont care about older users who might not see too good (1/3 of their userbase) or people with color-blindness (which is 1 out of 10 in the world), When making an app its important to take that into account. Most users would rather use an application that has clear distinction between UI elements, than a UI that demands you to concentrate to navigate visually. But we had to ship themefiles that follows what is modern and good, so we did that. When I have more time I will make more themes. Both the Amiga OS 4.x theme (which is really good), Windows 10 and a couple of Debian based skins is what I personally would like. Cheers Jon
  11. Styling Tw3Dialog

    Hi! The dialog has a second control, which is why the text is pushed to the right. This control contains the "alert glyph" from font-awesome. Make sure that this is visible and it should look more normal. Or just inherit from the dialog, set with width of the glyph panel to 0 and that should do the trick.
  12. Vendor Prefix within a javascript object

    You are mixing the purpose of these things up. Prefix and PrefixDef are used in two very different scenarios. The first does a prefix to create the qualified JS name. The second is used when altering css directly. I should know, I wrote the RTL
  13. Vendor Prefix within a javascript object

    You are looking for: BrowserAPI.Prefix() and BrowserAPI.PrefixDef(). These will give you the right prefixes for the browser currently running. I would strongly urge you to look at the SmartCl.Effects unit and see how css transitions are handled there. We have standard classes for this, so you dont have to manually do this. And even if you have your own CSS you just override and deliver it inside an effect class. You might also be interested in the SmartCL.Tween.** units if you want finer control. CSS is set in the style property of the handle: Handle.style[myproperty] := somevalue; Please note that "style[" is case sensitive, so "Handle.Style" wont work. JavaScript is picky that way. There is also W3_SetStyle() which is more pascal-ish if you like that
  14. TW3JSONP

    JSONP is a very obscure technology. Essentially you need to generate Javascript that is then downloaded and injected into the DOM, and then a callback fires ... its a long otello like they say in starwars. You should really use a WebSocket server, which just happens to be a normal http server with websocket on-top of it. Then you can use the much more powerful and stable TW3WebSocket client class instead. Best of luck!
  15. Onclick failure when switching TW3Editbox on iOS.

    Good catch, will investigate this and have reported it to our project manager. There are a number of things this can be. It can be a clean bug, but somehow I doubt that since Android and vanilla desktop browsers doesnt show this behavior. As you probably know, Apple is not a friendly company towards HTML5 based applications. They imposed a number or restrictions in Safari to ensure that web apps couldnt compete with Appstore. That has sort of backfired on them, but there are a few things we cant get around without Cordova. So I have to ask: 1. Is this running in normal Safari on iOS? 2. What model of iPhone / iPad is it? 3. What version of the OS / Safari version do you have? This could be as simple as a tag declaration, to more complex solutions like how we deal with focus events and delegate event objects.