Jump to content
uniGUI Discussion Forums


uniGUI Subscriber
  • Content Count

  • Joined

  • Last visited

Everything posted by wprins

  1. wprins

    Old man needs help

    If it's for a course then there's no point (nor would it be allowed) to just supply you with the solution. The point with asking about Delphi is that if you're more used to Delphi you should perhaps explore the concepts in the comfort of Delphi first as that might be slightly easier to start with, before working out how the same concepts are realised in Java. Ultimately you're learning 2 things at once: The abstract concepts of socket based networking as well as how this is implemented/realised concretely in a programming language, in this case Java. You've not mentioned what you've tried so far and where you've gotten stuck? It might be worth (also) posting your question on a more general programming forum like StackOverflow. But you'll need to more specific and explain exactly where you're getting stuck ideally with an MCVE if possible. You should probably also read this. Hope that helps.
  2. wprins

    Old man needs help

    Is this homework/done as part of some course? What have you tried so far and where have you become stuck exactly? Have you tried writing the same thing in Delphi and/or UniGui yet? If so how did you get on?
  3. wprins

    leaflet maps - unihtmlframe

    You've forgotten to post links to the "other forum".
  4. wprins

    Layout: advanced tutorial

    Note, I've now created a github repo with the code and the fixes I made. It is available here.
  5. Of course you can use plain procedures or functions, but they key thing you must understand is that UniGUI is of necessity a multi-threaded environment. That means that you need to keep in the back of your mind the question whether there could be concurrency problems when you access any "shared thing" out there. Again, while one can mostly program with a single threaded "typical" mindset (ignoring threading issues) providing you're using things belonging to the "current" session, anything else that is shared must be carefully considered regarding possible concurrency problems. What would happen for example in your procedure above if 2 sessions execute it at exactly the same time? Since all the parameters would be distinct and there's no shared variables anywhere, there's no problem in this case. But if there was (for example) a shared global variable referenced in that procedure, then you'd have to think how multiple threads simultaneously trying to update such a shared resource would behave. You'd likely need a lock or monitor or mutex or something to ensure the threads interoperate correctly on the shared resource.
  6. wprins

    UniGUI support, feedback in general and the future?

    Thanks for sharing. Am I right in assuming these are these Firemonkey applications? And what about the internals? Did you use datasnap or something else for the middle/back end? What about client architecture? Did you use FireDAC components or TClientDatasets or something else entirely? (Back in XE5 days I evaluated Delphi's Android support and suffice it to say it was IMHO dire at the time, basically broken and didn't work well enough for me to risk using in production. It looks though like things have come along very well and that I should revisit this.)
  7. wprins

    UniHTMLFrame and Server Path

    We had a similar requirement. First of all, understand: URLFrame.URL is basically a way for you to get the browser to ask for a specified URL (file) in a totally standard "http/s" way. So you must think in terms of "URL" not "shared folder" in the first instance. Next, UniGUI's "FilesFolderURL" gives you a way to get a URL to refer to files in a known UniGUI FilesFolder location, via an HTTP/S URL therefore recognized by the UniGUI server. So, thats one way to get UniGUI to do the "translation" from server based path/file location to something that UniGUI will recognize an serve to a client browser. Of course it doesn't help you because you're interested in some other shared location accessible by your server. It follows that since UniGUI doesn't know about this location, you must implement something similar to what UniGUI does for its file/folder location. In short, to solve this we implemented a servermodule event handler/method (sorry I don't have the code in front of me otherwise I'd perhaps be a bit more specific) that basically recognizes special URL's requests (by prefix) and which further along the URL contains a file-id (AES256 encrypted filename/path in fact). The server module then of course decrypts the request and manually/directly serves up the requested file providing the requestor is allowed to do so of course. That's the essence of it anyway. Walter
  8. wprins

    MVC pattern in UniGUI vs traditional coding to form

    A big reason to prefer more decoupled approaches such as MVC, MVP, MVVM, MV* is testability. If all your logic is inside event handlers then typically it's quite hard to properly test and not possible to test entirely in isolation. This may not be a show stopping problem but it is a consideration at least. (Also see for example the "Humble Dialog" pattern and "Humble View".)
  9. wprins


    For what it's worth, the above example didn't work as-is in the latest UniGUI version(s). I've updated it, added a few logging calls and instructions to make it clearer what's happening, as well as changing the flow somewhat (avoiding using a custom event in favour of just triggering the actual button click instead.) The code is available here: https://github.com/ByteJuggler/uni_keycap/tree/master
  10. wprins

    Layout: advanced tutorial

    Hi, Just to note that the "layout.rar" example from the message in this post does not run on the latest UniGUI and displays the message: "'field' config has been deprecated. Please use the 'angleField' config instead." It might be useful to update it and/or include it in the official demo if it's not already there (? I've not exhaustively looked at all the included demos, my apologies if it's actually already included!) Edit: The simple way to "fix" this is to edit ClientEvents.UniEvents and open Ext.chart.CartesianChart, then open chart.beforeInit and comment out the "config.axes" assignment in the code. (There's obviously a better way of fixing it but I didn't have the time or patience to work out what exactly has changed and how it should be updated. Changing "fields" to "angleField" or "angleFields" did not work and resulted in another error message.) Walter
  11. Hi, Today upgraded our project to (from 1.0.xxx before). Mostly everything seems to be working ok except for 2 minor things: 1) Login form icon not displaying correctly. It displays correctly ad design time. The icon is supplied via the Form's Icon property, and seems fine in the object inspector. Edit: To add, it looks like the icon is there, but is not being resized to 16x16 anymore automatically for the login form thumbnail icon. (I'll see if manually resizing it fixes the issue...) Edit2: Resizing the icon doesn't fix it, it's somehow still too large it seems, and now being "upscaled" as well. I get the impression there's some code somewhere that's set to scale the supplied icon to size, except it's apparently using the wrong size. Edit3: I've removed the icon entirely from the login form. It now displays with the default Delphi icon at designtime but is somehow now displaying the correct icon correctly at runtime?! (It may be picking it up from the Application icon, I'm guessing.) 2) I usually (but not necessarily every time) during login get the following message: Event:click, Object: O50 not found in session list. It could be timed out, refresh page and try again. It's always O50, and only seems to happen on logging in. Any suggestions on what might be causing this would be appreciated. Obviously it's possible that it's something in our project but then neither of these problems existed prior to the upgrade. Thanks Walter
  12. wprins

    Max Characters in Memo

    Thanks, apologies, I should've found that myself.
  13. wprins

    Max Characters in Memo

    Sherzod, thank you. Out of interest, can one do the same via beforeInit()? (I assume so?)
  14. wprins

    Call another web application

    I assume you meant to write it as the above (note I inserted [in]). What do you mean by "another web application" and what do you mean by "call" exactly? You can call other web services in the normal way you would from non uniGUI applications by whatever means suits your purpose. You can also "call" and frame another website inside a uniGUI frame, with some work and some co-operation from the site being called/framed. You could call a uniGUI application in various ways as well, though you'd need to arrange things to suit your purpose, which is to say you'll have to arrange for the required credentials/login to be somehow handled seamlessly/in the background. (We do something like this from an iSeries green screen system which publishes a clickable URL on the green screen and it directly "calls" our UniGUI application, taking the user to a specific page/form in the UniGUI application. If the user isn't already logged in then they're prompted to log in, after which of course the browser knows the user and further logins is seamlessly handled as required.)
  15. wprins

    Max Characters in Memo

    Today I needed this feature. It would be better if TUniMemo exposed MaxLength as a property to control this. But thanks for this solution. Edit: Also setting the maximum length doesn't actually prevent the entry of more than the maximum length. It does colour the memo frame red and display a hover warning about the maximum length however. Is it possible to actually stop entry once the memo reaches capacity?
  16. wprins

    UniGUI support, feedback in general and the future?

    For what it's worth, we generally employ the same policy -- avoid the use of closed source components whenever possible, UniGUI being essentially the only exception we've allowed in this policy for a very long time as it is such a good product. Still, I really continue to worry and dislike the level of risk we're carrying due to the size of FMSoft, e.g. if something happens to Farshad or FMSoft this will have quite serious consequences. It is entirely within the realm of possibilities to end up in a situation where FMSoft stops trading with no way to obtain the source code to UniGUI, and consequently that all the investment into a UniGUI based solution then ends up having to be abandoned and entirely rewritten due to lack of access to source and consequent inability to upgrade to newer versions of the Delphi and web ecosystems. (To add this is not just a purely hypothetical possibility either, I've actually worked with a company once where exactly this happened and a system had to be replaced at great cost and trauma to the business due to another business having gone under, so much so that they then negotiated special escrow agreements with a new provider to ensure they would have access to a product's source should that partner business cease trading etc... The whole issue is worrying enough that, as much as I like UniGUI, I do continue to consider the alternatives and will likely consider switching to eliminate this risk if something becomes available that is competitive with UniGUI.)
  17. Hi, I've today become aware of the new hyper-server functionality. Fantastic. It will solve some of the issues we've sort of just had to manage/deal with as mentioned in documentation. However, I have a question: It seems from the documentation however that Nodes (worker processes) that are managed by the hyper-server must reside on the same physical/virtual box? Is this corect? If so it's slightly unfortunate as it would seemingly be very useful if nodes could also be distributed over multiple servers rather than only being hosted on one single instance (for additional ability to scale and redundancy.) Or am I missing something or looking at this the wrong way? Thanks Walter
  18. What is the use of UniSession.SendStream()? In what context might one use it? Likewise UniSession.SendFile()?
  19. Hi, Problem: I'm trying to determine the client's apparent IP address (their public IP) so it is known inside the user's uniGUI session. Background: This is needed to enable us to generate an access token for integrating with an external party/site, where the originating browsers IP address is also used in the token signature/hash calculation/verification process. Obviously determining the user's IP is something that needs to happen inside the browser itself, in order to get the apparent public IP address of the browser running the application. Now it turns out that from a web browser/JS perspective this is quite easy. In fact there are multiple services that has API's that enable one to retrieve your apparent public IP. (See here, for example.) So the obvious idea is to somehow have the browser perform this IP capture itself just prior to, or as part of Login and then pass it and store it as part of the user's session (MainModule). Now I've had a look at the "HTTP POST callback" examples which would've provided, it would seem,a way to achieve this, if our login page was in fact a TUniURLFrame. I could then write some Javascript code to GET from the above URL (on document ready/loaded etc, say) and then update the browser document accordingly to finagle things so that on submit/POST the IP would effectively get passed together with the other form variables. However, we currently use a typical uniGUI login form with edit boxes and so on for login, not a uniURLFrame. So I'm a little at a loss as to where/how to sneak the required JS into the page to fetch the IP and ensure that it gets passed to the uniGUI server session either immediately or on login. Question: Given the above, what's the best way for me to effectively get the browser to get the user's IP address using e.g. https://api.ipify.org/?format=json, and pass this back with the other login details on login to the uniGUI server session? Alternatively do you have any better ideas or have I missed some obvious solution to this problem? (Maybe perhaps using UniSession.AddJS() which has just occurred to me while writing this...?) Thanks so much in advance for any pointers/suggestions, Walter
  20. For anyone finding this in future: The URL suggested by Gerhard (freegeoIP) is being retired as of July 2018. An alternative is www.ipify.org. Code as follows: procedure TLoginForm.UniLoginFormAjaxEvent(Sender: TComponent; EventName: string; Params: TUniStrings); begin if SameText(EventName, 'ClientIPAddr') then begin //Do what you want with the IP. As example we set the IP on a frame embedded in the login form (assumes there's a BrowserIP property.) LoginFrame.IPLabel.Caption := 'Your public IP is: '+Params.Values['ip']; LoginFrame.BrowserIP := Params.Values['ip']; end; end; procedure TLoginForm.UniLoginFormBeforeShow(Sender: TObject); begin //Reference: https://www.ipify.org/ UniSession.AddJS( '$(function() {'+ ' $.getJSON("https://api.ipify.org?format=jsonp&callback=?",'+ ' function(json) {'+ ' ajaxRequest(' + self.WebForm.JSName + ', "ClientIPAddr", ["ip="+json.ip]);'+ ' }'+ ' );'+ '});' ); end;
  21. Hi Apologies for what might be a beginner question, but is there an obvious/easy/trivial way to respond to the runtime resizing of the client side browser and consequently anchored (or aligned) DBGrid, so that the page size used by the DBGrid matches the visible size in the browser? Thanks.
  22. Gerhard, sparkz thanks. I've not been on the forums much for the last 2 or so months. I eventually actually came up with a solution by myself about 2 months ago. It's not entirely unlike what you've (Gerhard) done, yours is a bit more succinct. I was planning on posting my solution at some point but have been either away or too busy. I'll still post it sometime as I avoid using AddJS which seems somehow slightly smelly to me and so may be of interest to others...(?) Edit: Gerhard, thanks again for your example. I did just have a quick look at what I did previously and I think your solution is perhaps preferable, nice and neat and to the point. Will try it out in due course. Nevertheless, for interest and in case anyone finds it useful or educational: Basically I used UniSession.CallbackURL() and UniSession.CallbackTarget() to generate a callback URL and target from within Delphi code. These are placed inside static HTML+JS page code placed a designtime (e.g. TUniHTMLFrame or TUniURLFrame content). At the bottom of the page I wrote some Javascript to retrieve the IP, after which I trigger a normal JS Form submit which fires the retrieved IP address off into the UniGui Session via UniFormAjaxEvent(). UniHTMLFrame1.HTML content: <div style="background-color:#ccc"> <br/><br/><br/><br/><br/> <form name="input" action="{URL_CALLBACK}" method="POST" target="{CALLBACK_TARGET}"> Username: <input type="text" name="user" value="Enter Text..."><br/> IP:<input type="text" name="ip" id="ip" value=""><br/> <input type="submit" value="Submit"> </form> <br/><br/><br/><br/><br/> </div> <script> var request = new XMLHttpRequest(); request.open('GET', 'https://jsonip.com', false); //synchronous request.send(null); if(request.status === 200) { data = JSON.parse(request.response); //console.log(data); //JQuery way: $("#ip").val(data.ip); document.forms["input"]["ip"].value = data.ip; //JQuery way: $("form#input").submit(); document.forms["input"].submit(); } </script> On Form create: procedure TMainForm.ReplaceTags; var S, Sc : string; begin S := UniSyntaxEdit1.Text; Sc := UniSession.CallbackUrl('mycallback', Self, []); S := StringReplace(S, '{URL_CALLBACK}', Sc, []); Sc := UniSession.CallbackTarget; S := StringReplace(S, '{CALLBACK_TARGET}', Sc, []); UniHTMLFrame1.HTML.Text := S; end; procedure TMainForm.UniFormCreate(Sender: TObject); begin UniSyntaxEdit1.Text:=UniHTMLFrame1.HTML.Text; ReplaceTags; end; Form Ajax event handler: procedure TMainForm.UniFormAjaxEvent(Sender: TComponent; EventName: string; Params: TUniStrings); begin if EventName = 'mycallback' then begin UniEdit1.Text := Params.Values['user']; UniEdit2.Text := Params.Values['ip']; UniMemo1.Text := Params.Text; end; end; (Again, this was based on and is a modified version of "HTTP Post Callback - HTMLFrame" demo project. I also similarly modified "HTTP Post Callback - URLFrame - Auto Target" which uses TUniURLFrame component instead of TUniHTMLFrame and does not require the "CALLBACK_TARGET" substitution.) Best regards.
  23. Hello, I've been away on holiday. Unfortunately I see no one's got any suggestions for my problem? So hence I post this additional response to bump it up a bit. As a reminder, my problem/question in short: What is the best way to call/run some Javascript in the browser and have something from it posted back to the corresponding UniGUI user session, and then from the UniGUI session update or set a cookie in the browser as a result? Walter
  24. Hello! Thanks for your response, but this does not help unfortunately. The properties you gave gives the "local network" IP address of the client machine on which the browser is running, which isn't usually the same as the apparent public IP address of that same machine. For example, if I run the uniGui server on my own machine and visit the server page with a browser, the above properties predictably return If I visit my machine from another machine on the LAN, these properties give the the other machine's LAN IP address. So far so good. But of course, if my machine or the other machine, were to visit some other website out on the internet, then both my machine, and the other machine will appear to be originating from a third different IP address, e.g the public IP address of the router and/or proxy server through which the traffic is being routed from the machines out to the site being visited. Now if you think back to what I'm doing: The client browser is simultaneously showing a (local network) uniGUI server, *and* framing another site (out on the internet in this case). Therefore, to the UniGUI server the browser machine appears to have a local LAN IP, but to the site on the internet the browser looks like it has the public IP address where the traffic is coming from. Now for the framing to work, the uniGUI server has to know what the browser's apparent IP address is, and generate an access token using this information (amongst other things.) E.g. it doesn't use the the local LAN IP that is directly visible to the UniGUI server and is obviously not known by the remote site, but it has to use the IP address seen by the third party site. As I mentioned before, this can in fact be easily retrieved from the context of the client browser with a bit of Javascript, but I'm not sure how to get this back to the uniGUI server. That is, my key question is what the best way is to essentially get the browser to do a request to the internet (to establish its "public" IP) and then pass this to the user's UniGUI session, so it can generate the token to place in a TUniURLFrame. Thanks in advance! Walter
  25. wprins

    uniGUI: Verification failed

    Thanks for the feedback, it helps to at least know what the cause of the issue is. I'll avoid messing with the virtualisation settings and bear in mind that doing so may affect the uniGUI installation. (Actually the fact that it was off was as a result of a BIOS upgrade some time ago, which as is usual, reset the BIOS settings to defaults. It wasn't until today that I actually needed to use Hyper-V again and then noticed that virtualisation support was in fact off in the BIOS and turned it back on. Perhaps it's worth mentioning this somewhere in the documentation somewhere.) Thanks again and have a great day, Walter