Jump to content

All Activity

This stream auto-updates     

  1. Yesterday
  2. Last week
  3. Czar

    UI layout

    Being able to make more complex UI that works on all devices will make life much much easier Looking forward to finished product.
  4. DavidRM

    UI layout

    Now add some TW3Labels to your layout demo and experience Real Pain. 😉
  5. jarto

    UI layout

    ' Working on this now. Align in the RTL is at pretty good shape already.
  6. lynkfs

    css styling

    Thanks There are however a couple of minor / major (?) caveats doing it like this : I made up some more metro components, and it becomes apparent that it is unavoidable to use more modifier classes: TagStyle.Add('primary image-button outline icon-left rounded etc). this type of styling is not supported by the visual designer in the ide, so styling can be done in code only. Even though only one-liners (TagStayle.Add( ) (most rtl components (but not all) have a component, a border and a background theme class baked in. Not all of these can be reused, so sometimes the border and/or background classes may end up being empty) probably the second bullet (visual designer) is the most important one for future enhancements
  7. Czar

    Development updates

    I like the lighter default theme for buttons. Thanks for the update.
  8. DavidRM

    Node.JS WebSocket Client Socket

    This is me sharing again. The NodeJS WebSocket server socket is implemented in SMS. But I didn't find an implementation of the WebSocket client socket. Sometimes an SMS NodeJS server needs to connect to another server. So I kinda hacked this together using the server socket as a guide. unit UPBNCommonNJWebSocket; interface uses System.Types, System.Types.Convert, System.Time, System.Streams, System.Reader, System.Writer, System.Device.Storage, System.Objects, SmartNJ.System, SmartNJ.Streams, SmartNJ.Device.Storage, SmartNJ.Application, NodeJS.Core, NodeJS.WebSocket, SmartNJ.Server.WebSocket; type // Forward declarations TNJWebSocket = class; TNJWebSocketOpenEvent = procedure (Sender: TNJWebSocket); TNJWebSocketCloseEvent = procedure (Sender: TNJWebSocket; Code: integer; const Reason: string); TNJWebSocketErrorEvent = procedure (Sender: TNJWebSocket; Error: TJSErrorObject); TNJWebSocketMessageEvent = procedure (Sender: TNJWebSocket; Message: TNJWebsocketMessage); TNJWebSocket = class(TW3ErrorObject) private FSocket: JWsSocket; public property WSSocket: JWsSocket read FSocket; function SocketState: JWsReadyState; function Connected: boolean; function URL: string; function Protocol: string; procedure Connect(URL: string; Protocols: array of string); overload; procedure Connect(URL: string); overload; procedure Disconnect; overload; procedure Send(const Data: variant); overload; procedure Send(const Text: string); overload; procedure Send(const Data: TStream); overload; property TagData: variant; constructor Create; override; destructor Destroy; override; procedure Ping; published property OnOpen: TNJWebSocketOpenEvent; property OnClosed: TNJWebSocketCloseEvent; property OnMessage: TNJWebSocketMessageEvent; property OnError: TNJWebSocketErrorEvent; end; implementation constructor TNJWebSocket.Create; begin inherited Create; // We dont want to throw exceptions whenever SetLastError() is called ErrorOptions.ThrowExceptions := false; end; destructor TNJWebSocket.Destroy; begin FSocket := nil; inherited; end; procedure TNJWebSocket.Ping; begin if FSocket <> nil then asm (@FSocket).ping(function() {}); end; end; function TNJWebSocket.Protocol: string; begin if FSocket <> nil then Result := FSocket.protocol; end; function TNJWebSocket.URL:String; begin if FSocket <> nil then Result:=FSocket.url; end; function TNJWebSocket.SocketState: JWsReadyState; begin if FSocket <> nil then Result := JWsReadyState( integer( FSocket.readyState) ) else Result := rsClosed; end; function TNJWebSocket.Connected: boolean; begin Result := SocketState = rsOpen; end; procedure TNJWebSocket.Connect(URL: string); begin Connect(Url, []); end; procedure TNJWebSocket.Connect(URL: string; Protocols: Array of string); begin ClearLastError(); (* disconnect socket if already connected *) if connected then disconnect(); (* Allocate new socket *) var WebSocket = WebSocketAPI; asm (@self.FSocket) = new (@WebSocket)(@URL, @Protocols); end; // initialize standard socket events FSocket.on("open", procedure begin if assigned(OnOpen) then OnOpen(self); end); FSocket.on("error", procedure (error: variant) begin SetLastError("internal websocket error"); if assigned(OnError) then OnError(self, TJSErrorObject(error)); end); FSocket.on("message", procedure (message: variant) var ResData: TNJWebsocketMessage; begin if message.IsUint8Array then begin ResData.wiType := mtBinary; ResData.wiBuffer := JBuffer(message); end else begin ResData.wiType := mtText; ResData.wiText := message; end; if assigned(OnMessage) then OnMessage(self, ResData); end); Variant(FSocket).on("close", procedure (code: integer; reason: string) begin if assigned(OnClosed) then OnClosed(self, code, reason); end); end; procedure TNJWebSocket.Disconnect; begin ClearLastError(); if Connected then begin try FSocket.close(); finally FSocket := nil; end; end; end; procedure TNJWebSocket.Send(const Data: variant); begin FSocket.send(data); end; procedure TNJWebSocket.Send(const Text: string); begin FSocket.send(Text); end; procedure TNJWebSocket.Send(const Data: TStream); begin if Data <> nil then begin if Data.position < Data.Size then begin // Get bytes from stream var Bytes := Data.Read(Data.Size - Data.Position); // Convert to typed-array var TypedArray := TDataType.BytesToTypedArray(bytes); // Send as binary FSocket.Send(TypedArray); end; end; end; end. It might be a bit simplified, and it doesn't really follow the SMS component name convention, but it does what I need. And I figured I would share. -David
  9. jarto

    css styling

    @lynkfs I like it a lot!
  10. IElite

    RoadMap 2019

    @jarto Myself, I am more interested in examples of client/server related projects (e.g. writing SMS clients for mobile devices which talk to node.js server).
  11. jarto

    Sorting arrays and lists

    This is a tutorial for sorting arrays and lists in Smart Mobile Studio. String arrays and TStringList are pretty easy to sort. You only need to call Sort: var strarr: array of String; ... strarr.Sort; var strlist: TStringList; strlist:=TStringList.Create; ... strlist.Sort; But how do you sort arrays of records or arrays of classes? For example: TSortData = record Id: Integer; Data: String; end; You can't simply call Sort as your application does not know how you want to sort the records. You solve this by using a comparison function: function CompareSortData(Item1, Item2: TSortData): Integer; begin result:=CompareStr(Item1.Data, Item2.Data); end; . . . var objarr: array of TSortData; ... objarr.Sort(@CompareSortData); The comparison function should return a negative number if Item1 is smaller, positive number if Item1 is bigger and 0 if they are equal. In Smart Mobile Studio you can also use anonymous methods: var objarr: array of TSortData; ... objarr.Sort( function(Item1, Item2: TSortData): Integer begin result:=CompareStr(Item1.Data,Item2.Data); end); Comparison functions can also be used for TList and even for TStringList. For example, you may want to have greater control over how names are sorted (eliminating prefixes like von): function EliminatePrefix(Name: String): String; const Prefixes: array[0..1] of String = ['von ','af ']; begin result:=Name; for var a:=0 to High(Prefixes) do begin if pos(Prefixes[a],result)=1 then begin Delete(result,1,Length(Prefixes[a])); exit; end; end; end; . . . var StrList:=TStringList.Create; StrList.Add('Perry'); StrList.Add('Miller'); StrList.Add('von Essen'); StrList.Add('Stockton'); StrList.Add('af Trolle'); StrList.Sort( function(Name1,Name2: String): Integer begin result:=CompareStr(EliminatePrefix(Name1),EliminatePrefix(Name2)); end); for var a:=0 to StrList.Count-1 do WriteLn(StrList[a]);
  12. Earlier
  13. lynkfs

    css styling

    Easy to use... Suppose we want to develop a Metro theme To take buttons as an example, the official metro style has a number of predefined buttons : To replicate the above, and do it in such a way that : the component code (TW3Button) does not need any change the standard theming classes still apply (TW3Button TW3ButtonBorder TW3ButtonBackground), but with different content of course while allowing for these different predefined component versions is to do something like this procedure TForm1.InitializeForm; begin inherited; // this is a good place to initialize components var Button1 : TW3Button := TW3Button.Create(self); Button1.SetBounds(20,20,83,40); Button1.Caption := 'Default'; var Button2 : TW3Button := TW3Button.Create(self); Button2.SetBounds(110,20,83,40); Button2.Caption := 'Primary'; Button2.TagStyle.Add('primary'); var Button3 : TW3Button := TW3Button.Create(self); Button3.SetBounds(200,20,83,40); Button3.Caption := 'Secondary'; Button3.TagStyle.Add('secondary'); var Button4 : TW3Button := TW3Button.Create(self); Button4.SetBounds(290,20,83,40); Button4.Caption := 'Success'; Button4.TagStyle.Add('success'); end; result : with the metro css file for the above looking like this /* ////////////////////////////////////////// // TW3Button (default) ////////////////////////////////////////// */ .TW3Button { font-weight: 400; text-align: center; white-space: nowrap; vertical-align: middle; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; border: 1px solid transparent; padding: 0 0.75rem; -webkit-transition: all 0.15s ease-in-out; transition: all 0.15s ease-in-out; background-color: #ebebeb; color: #1d1d1d; cursor: pointer; outline: none; -ms-touch-action: manipulation; touch-action: manipulation; -webkit-appearance: button; /* font-size: 0.875rem; line-height: 34px; height: 36px; */ } .TW3Button:focus, .TW3Button:active { text-decoration: none; -webkit-box-shadow: 0 0 0 3px rgba(228, 228, 228, 0.45); box-shadow: 0 0 0 3px rgba(228, 228, 228, 0.45); } .TW3Button:hover { background-color: rgba(29, 29, 29, 0.1); } .TW3ButtonBackground { } .TW3ButtonBorder { } /* ////////////////////////////////////////// // TW3Button Primary ////////////////////////////////////////// */ .TW3Button.primary { outline-color: #75b5fd; background-color: #0366d6; color: #ffffff; } .TW3Button.primary:hover { color: #ffffff; background-color: #024ea4; border-color: #023671; } .TW3Button.primary:focus, .TW3Button.primary:active { -webkit-box-shadow: 0 0 0 3px rgba(3, 102, 214, 0.45); box-shadow: 0 0 0 3px rgba(3, 102, 214, 0.45); } /* ////////////////////////////////////////// // TW3Button Secondary ////////////////////////////////////////// */ .TW3Button.secondary { outline-color: #b7c6cd; background-color: #607d8b; color: #ffffff; } .TW3Button.secondary:hover { color: #ffffff; background-color: #4b626d; border-color: #36474f; } .TW3Button.secondary:focus, .TW3Button.secondary:active { -webkit-box-shadow: 0 0 0 3px rgba(96, 125, 139, 0.45); box-shadow: 0 0 0 3px rgba(96, 125, 139, 0.45); } /* ////////////////////////////////////////// // TW3Button Success ////////////////////////////////////////// */ .TW3Button.success { outline-color: #adeb6e; background-color: #60a917; color: #ffffff; } .TW3Button.success:hover { color: #ffffff; background-color: #477c11; border-color: #2d4f0b; } .TW3Button.success:focus, .TW3Button.success:active { -webkit-box-shadow: 0 0 0 3px rgba(96, 169, 23, 0.45); box-shadow: 0 0 0 3px rgba(96, 169, 23, 0.45); } see demo (check click and hover states) What do you think ? By the way, this css file is made up by screenscraping, which is actually not too bad / timeconsuming. Alternatively it could also be composed out of relevant Tailwind functions, results would be very similar.
  14. jarto

    css styling

    @lynkfs This is very interesting. The challenge would be to make it easy to use.
  15. jarto

    TW3StringGrid is available

    I just updated the first post here with new events, column classes and sort documentation.
  16. jarto

    Development updates

    A new update is available. RTL: Improvements to TW3StringGrid: New column types: TW3StringGridNumericColumn TW3StringGridButtonColumn Added sorting New event: OnCellChanged TStringList and TObjectList: Add Sort() with CompareFunction. Fix CSS browser prefix for Firefox Themes: Use normal size and style text in buttons.
  17. jarto

    layout, wordwrap and label nightmare

    Update: I've been running some tests. It's a bit dangerous to dynamically increase the label height when AutoSize is false. In the meantime, maybe you should try simply using a TW3DivHtmlElement where you do not specify height at all? You need to create the control in code and then set InnerText (or InnerHtml if you want to use html tags). When no height is set, the browser automatically resizes the height according to the content.
  18. IElite

    RTL Search

    I use a free version of FileSeek
  19. Czar

    RTL Search

    I use this external program. Just add .pas to search options. It is very quick and it is only way that I can search through rtl and projects. http://www.harddisksearch.com/
  20. DavidRM

    RTL Search

    I would find a built-in search of the RTL quite handy. Sorta like the "Find in Files...", where it brings up a list of hits, but searching the current SMS RTL folders and files instead. Could even just be a checkbox option in "Find in Files..." This would be a step in the direction of "better documentation". 😃 Or, at least, easier to review what's already available. Currently, I do this using Notepad++, but that doesn't let me open the results in the SMS IDE. Being in the IDE would provide access to "Find Declaration" and similar features. -David
  21. jarto

    RoadMap 2019

    Well, I believe that open sourcing is not a silver bullet that will magically bring new resources to the project. If there are people who are interested in participating, I'll be more than happy to actually offer them contract work. Before I joined this project, SMS was in an eternal "coming soon" -stage. A new update was just around the corner but days turned into weeks and weeks to months and years. I didn't like that as a customer. So when I've been running this development, I've not wanted to make promises that I can't keep. Before this my family owned and ran a very succesfull software company that developed the best and most used School Administration software in Finland. We did constant development making new features. We used constant evolution. I've been doing that same thing with Smart Mobile Studio and we really have seen a lot of development and improvements. And we will see constant and good development in the future too. When it comes to a roadmap, I've noticed that I'm really bad at making one. A software project is a moving target. A lot of features are being worked on. In the end, it's not clear when a feature will be finished and delivered. That's because priorities do change and sometimes (for example the new Grid) technology throws us a hard challenge that takes a very long time to solve. At the moment our top priorities are: Improve documentation, tutorials, demos. Update internal browser to a newer version of Chromium. Upgrade compiler to use a newer version of DWScript. Improve IDE (Designer, Wizards) On top of that we keep a keen eye on the needs and requests of our users and add new features/components to the RTL based on that. @Czar Thanks for the tip about the events related bug in the IDE. I was able to reproduce it. There are restrictions on what the IDE can do at the moment. And some restrictions actually depend on what's the best way of developing for the browser. For example, it's a lot better to have fonts and font sizes in CSS instead of setting them in the Object Inspector. @IElite Let me know what you want to see regarding mobile devices.
  22. IElite

    css styling

    Thanks, that did explain it better. Thanks for taking the time. I am interested in examining it further for sure.
  23. Czar

    css styling

    Aha. Ok I now understand. I will take a closer look on monday as this approach does sound promising
  24. lynkfs

    css styling

    Wow, you guys are funny. The question I had was : what is the easiest way to style Smart components. Smart ships with a couple of standard stylesheets, or themes, so styling is a matter of selecting one of these. To change the styling of a specific component in a theme, just change the css specifications in the stylesheet, either manually or through code. A different topic altogether is to develop new themes. It is not a simple task to f.i. develop a Metro theme stylesheet which covers all of the current Smart visual components. That's why I had a look at externally available css frameworks, to see if any of those would help with developing themes, or even work within the Smart development environment and if they are useful to begin with. I focused on one particular framework : Tailwindcss One of the problems with themes is when it becomes necessary to deviate from it. Say a project has chosen the default theme (default.css), but for some legitimate reason somewhere in the project a standard component has to be styled differently. Example : colour a button green to amplify a positive choice and colour it red to amplify dangerous choices ("do you really want to download these files from an unknown source ?" and then display a green "No" button and a red "Yes" button). It's not that simple to make this actually happen. Lets say we change the styling of the green button (based on the standard button), and opt to do that in code : var Button2 : TW3Button := TW3Button.Create(self); Button2.SetBounds(20,120,150,40); Button2.Caption := 'No'; // Button2.handle.style.background := '#48bb78'; //Button2.Color := clTeal; Button2.handle.style.border := '1px solid #48bb78'; //Button2.Border.Color := clTeal; Button2.handle.style.borderRadius := '0px'; //Button2.borderradius := 0; Button2.handle.style.color := 'white'; // //simulate hover Button2.handle.onmouseover := procedure(event: variant) begin event.target.style.background := 'orange'; end; Button2.handle.onmouseout := procedure(event: variant) begin event.target.style.background := '#48bb78'; end; works sort of ok, but requires a bit of effort Alternatively we can change the stylesheet, so if we opt to do that for the red button then this requires var Button3 : TW3Button := TW3Button.Create(self); Button3.SetBounds(200,120,150,40); Button3.Caption := 'Yes'; // Button3.TagStyle.Clear; Button3.TagStyle.Add('TW3Button TW3ButtonRed'); var cssProperties := 'background-color: red;'; browserapi.document.styleSheets[0].insertRule(".TW3ButtonRed { " + cssProperties + " }", 0); /* .TW3ButtonRed { background-color: red; } */ cssProperties := 'background-color: orange;'; browserapi.document.styleSheets[0].insertRule(".TW3ButtonRed:hover { " + cssProperties + " }", 0); either in code or adding the .TW3ButtonRed and the .TW3ButtonRed:hover manually to the stylesheet Again, works but requires some effort Using the Tailwind css framework, the above would be simplified to //green var Button4 : TW3Button := TW3Button.Create(self); Button4.SetBounds(20,220,150,40); Button4.Caption := 'No'; Button4.handle.className := "bg-green-500 hover:bg-blue-700 px-6 text-white rounded shadow-xl"; //red var Button5 : TW3Button := TW3Button.Create(self); Button5.SetBounds(200,220,150,40); Button5.Caption := 'Yes'; Button5.TagStyle.Clear; Button5.TagStyle.Add("bg-red-500 hover:bg-blue-700 px-6 text-white rounded shadow-xl"); Button1 : standard styling Button2 : changing standard styling in code Button3 : changing standard styling using css Button4/5 : using Tailwind I've probably confused everyone even more now Anyway, these are my thoughts : Tailwind has the advantage that it can style any of the standard Smart components. As such it could be used to make up a f.i. Metro theme. Still a significant task, but doable. Apart from that, I actually quite like Tailwind to style components on a need-to-do basis, their styling functions make the standard SMS buttons, panels, editboxes, memos etc look really good and modern. (A card btw is just a panel with a certain layout, where usually multiple of these panels appear on a form or page.)
  25. IElite

    css styling

    Im confused as well...I see nothing related to a 'card'
  26. lynkfs

    css styling

    I think sometimes I'm very bad at explaining things. I'll respond over the weekend
  1. Load more activity
×