Jump to content

Kattes

uniGUI Subscriber
  • Posts

    143
  • Joined

  • Last visited

  • Days Won

    11

Everything posted by Kattes

  1. Overview I would like to request an enhancement to the TUniMap component that introduces advanced layer management capabilities, allowing for more flexible and dynamic map presentations in UniGUI applications. The proposed extension would facilitate the handling of various map layers, including bitmap and vector layers, with features such as custom Z-indexing and transparency control. Proposed Features Layer Type Enumeration: Introduce TMapLayerType to distinguish between different types of map layers (e.g., bitmap, vector). Base Map Layer Class: Implement a TMapLayer base class with properties like ID, LayerType, and ZIndex, and methods for adding to the map, removing from the map, and updating the Z-index. Bitmap and Vector Layer Classes: Create TBitmapLayer and TVectorLayer subclasses to manage specific layer types, including functionalities for setting transparency (for bitmap layers) and handling vector data. Extended UniMap Component: Develop TExtendedUniMap, an enhanced version of TUniMap, with capabilities to add, remove, update, and reorder layers dynamically. This component should manage a collection of TMapLayer objects, offering a unified interface for layer manipulation. Justification In many mapping applications, the need to dynamically adjust the visibility and order of layers is crucial for providing users with a clear and informative view of the data. The ability to change the transparency of layers, apply blending modes, and manipulate the stacking order (Z-index) of both bitmap and vector layers would greatly enhance the flexibility and utility of the TUniMap component. Example Use Cases Environmental Monitoring: Displaying real-time data overlays (e.g., weather, pollution) on top of a base map, with user-controlled transparency for comparative analysis. Geospatial Analysis: Layering thematic maps in a specific order, adjusting visibility and order to highlight spatial relationships or patterns. Urban Planning: Overlaying architectural plans or development proposals on existing city maps, allowing for interactive exploration of future changes.
  2. This is exactly how it works, but don't forget that you need SSL connection for testing, i.e. HTTPS, otherwise you have no access to the reader and only get error messages. Kind regards, Kattes
  3. I will try my best to strengthen the UniGUI community
  4. Oh no - I was blind ! 🙄 Now everything works fine! Finally I used your code but put it to the MainForm OnCreate event, because I am not a friend of hidden JS scripts somewhere in the forms. I also suppressed the scroller from being visible in the standard browsers like Chrome, Firefox and Edge because I also wanted to keep the look and feel clean. But normally everyone uses the scroll-wheel anyway. Perhaps this is also useful for somebody else ... procedure TMainForm.UniFormCreate(Sender: TObject); var JSCode: string; begin // Write JavaScript code to add scroll to the TreeMenu JSCode := 'function treeMenu.afterCreate(sender) {' + ' sender.el.setStyle(''overflow-y'', ''auto'');' + ' sender.el.setStyle(''scrollbar-width'', ''none'');' + ' sender.el.setStyle(''-ms-overflow-style'', ''none'');' + ' var style = document.createElement(''style'');' + ' style.innerHTML = ' + ' `#${sender.el.id}::-webkit-scrollbar { display: none; }`;' + ' document.head.appendChild(style);' + '}'; // Execute JavaScript code UniTreeMenu1.ClientEvents.UniEvents.Add('treeMenu.afterCreate='+JSCode); end; Thank you again Sherzod !
  5. Ok my friend Sherzod - then please enlighten me 🙂
  6. When doing so my example crashes
  7. Hello @Sherzod, can you please give me some more details? is this based on my version of Unigui or a later one? is it still using this solution: treeMenu.afterCreate(sender) { sender.el.setStyle('overflow-y', 'auto'); } Kind regards, Kattes
  8. Sorry for the late response - but I was totally overloaded the last weeks.... Here the promised source code - its free for everybody, but please do not ask questions about it. In case you want enhance the code please do so but also post the enhancements here for everybody. 🙂 unit UniOpenDialog; { uniGUI Web Application Framework for Delphi Developed by: Kattes Free Usage for all registered UniGui Users :) } interface uses System.Classes, SysUtils, uniGUIBaseClasses, uniGUITypes, uniGUIClasses, uniFileUpload, System.IOUtils; type TUniCustomOpenDialog = class(TUniComponent) private FButton: TUniFileUploadButton; FOnFilesReady: TNotifyEvent; FAjaxEvent: TUniAjaxEvent; FOnCompleted: TUploadNotifyEvent; FOnMultiCompleted: TUploadMultiNotifyEvent; FFiles : TStringList; FFilter : string; FTargetFolder : string; FRebuild : boolean; function GetEraseCacheAfterCompleted: Boolean; procedure SetEraseCacheAfterCompleted(const Value: Boolean); function GetMessages: TUniCustomUploadMessages; procedure SetMessages(const Value: TUniCustomUploadMessages); function GetMaxAllowedSize: Cardinal; procedure SetMaxAllowedSize(const Value: Cardinal); function GetMaxFiles: Cardinal; procedure SetMaxFiles(const Value: Cardinal); function GetMultipleFiles: Boolean; procedure SetMultipleFiles(const Value: Boolean); function GetFilter: string; procedure SetFilter(const Value: string); function GetAjaxEvent: TUniAjaxEvent; procedure SetAjaxEvent(const Value: TUniAjaxEvent); procedure SetOverwrite(const Value: Boolean); function GetOverwrite: Boolean; function GetTimeoutMS: Integer; procedure SetTimeoutMS(const Value: Integer); function GetTimeoutSecs: Integer; procedure SetTimeoutSecs(const Value: Integer); procedure SetOnMultiCompleted(const Value: TUploadMultiNotifyEvent); procedure SetOnCompleted(const Value: TUploadNotifyEvent); procedure ButtonSingleCompleted(Sender: TObject; AStream: TFileStream); procedure ButtonMultiCompleted(Sender: TObject; Files: TUniFileInfoArray); public constructor Create(AOwner: TComponent); destructor Destroy; override; procedure Execute; property EraseCacheAfterCompleted: Boolean read GetEraseCacheAfterCompleted write SetEraseCacheAfterCompleted; property Files: TStringList read FFiles write FFiles; property Filter: string read GetFilter write SetFilter; property TargetFolder: string read FTargetFolder write FTargetFolder; property MaxAllowedSize: Cardinal read GetMaxAllowedSize write SetMaxAllowedSize; property MaxFiles: Cardinal read GetMaxFiles write SetMaxFiles; property Overwrite: Boolean read GetOverwrite write SetOverwrite default True; property OnFilesReady: TNotifyEvent read FOnFilesReady write FOnFilesReady; property OnAjaxEvent: TUniAjaxEvent read FAjaxEvent write FAjaxEvent; property OnCompleted: TUploadNotifyEvent read FOnCompleted write SetOnCompleted; property OnMultiCompleted: TUploadMultiNotifyEvent read FOnMultiCompleted write SetOnMultiCompleted; property MultipleFiles: Boolean read GetMultipleFiles write SetMultipleFiles; property Messages:TUniCustomUploadMessages read GetMessages write SetMessages; property TimeoutSecs: Integer read GetTimeoutSecs write SetTimeoutSecs; property TimeoutMS: Integer read GetTimeoutMS write SetTimeoutMS; end; TUniOpenDialog = class(TUniCustomOpenDialog) published property Filter; property Files; property TimeoutSecs; property TimeoutMS; property MaxAllowedSize; property Messages; property MultipleFiles; property MaxFiles; property TargetFolder; property Overwrite; property EraseCacheAfterCompleted; property OnCompleted; property OnMultiCompleted; property OnAjaxEvent; property OnFilesReady; end; procedure Register; implementation procedure Register; begin RegisterComponents('uniGUI Additional', [TUniOpenDialog]); end; constructor TUniCustomOpenDialog.Create(AOwner: TComponent); begin inherited Create(AOwner); // Name := AOwner.Name + 'OpenDialog'; FButton := TUniFileUploadButton.Create(AOwner); FRebuild := false; with FButton do begin Name := AOwner.Name + 'OpenDialog_UL'; SetParentComponent(AOwner); TargetFolder := ''; Filter := '.pat'; Visible := False; Messages.Uploading := 'Uploading...'; Messages.PleaseWait := 'Please Wait'; Messages.UploadError := 'Upload Error'; Messages.UploadTimeout := 'Timeout occurred...'; Messages.MaxSizeError := 'File is bigger than maximum allowed size'; Messages.MaxFilesError := 'You can upload maximum %d files.'; onCompleted := ButtonSingleCompleted; onMultiCompleted := ButtonMultiCompleted; end; FFiles := TStringList.Create; end; destructor TUniCustomOpenDialog.Destroy; begin inherited; FFiles.Free; end; procedure TUniCustomOpenDialog.Execute; var FDummy: TUniFileUploadButton; begin if FRebuild then begin FDummy := TUniFileUploadButton.Create(FButton.Owner); // Copy the properties of the original component to the new component FDummy.Parent := FButton.Parent; FDummy.EraseCacheAfterCompleted := FButton.EraseCacheAfterCompleted; FDummy.MultipleFiles := FButton.MultipleFiles; FDummy.MaxAllowedSize := FButton.MaxAllowedSize; FDummy.MaxFiles := FButton.MaxFiles; FDummy.Filter := FButton.Filter; FDummy.Messages.MaxSizeError := FButton.Messages.MaxSizeError; FDummy.Messages.MaxFilesError := FButton.Messages.MaxFilesError; FDummy.Messages.PleaseWait := FButton.Messages.PleaseWait; FDummy.Messages.UploadError := FButton.Messages.UploadError; FDummy.Messages.Uploading := FButton.Messages.Uploading; FDummy.Messages.UploadTimeout := FButton.Messages.UploadTimeout; FDummy.TargetFolder := FButton.TargetFolder; FDummy.ButtonVisible := FButton.ButtonVisible; FDummy.OnCompleted := FButton.OnCompleted; FDummy.OnMultiCompleted := FButton.OnMultiCompleted; FDummy.OnAjaxEvent := FButton.OnAjaxEvent; FDummy.Overwrite := FButton.Overwrite; FDummy.Visible := FButton.Visible; // Switch instance FButton.Free; FButton := FDummy; FRebuild := false; end; FButton.JSInterface.JSCall('fileInputEl.dom.click', []); end; function TUniCustomOpenDialog.GetAjaxEvent: TUniAjaxEvent; begin result := FButton.OnAjaxEvent; end; function TUniCustomOpenDialog.GetEraseCacheAfterCompleted: Boolean; begin result := FButton.EraseCacheAfterCompleted; end; function TUniCustomOpenDialog.GetFilter: string; begin result := FButton.Filter; end; function TUniCustomOpenDialog.GetMaxAllowedSize: Cardinal; begin result := FButton.MaxAllowedSize; end; function TUniCustomOpenDialog.GetMaxFiles: Cardinal; begin result := FButton.MaxFiles; end; function TUniCustomOpenDialog.GetMessages: TUniCustomUploadMessages; begin result := FButton.Messages; end; function TUniCustomOpenDialog.GetMultipleFiles: Boolean; begin result := FButton.MultipleFiles; end; function TUniCustomOpenDialog.GetOverwrite: Boolean; begin result := FButton.Overwrite; end; function TUniCustomOpenDialog.GetTimeoutMS: Integer; begin result := FButton.TimeoutMS; end; function TUniCustomOpenDialog.GetTimeoutSecs: Integer; begin result := FButton.TimeoutSecs; end; procedure TUniCustomOpenDialog.SetAjaxEvent(const Value: TUniAjaxEvent); begin FButton.OnAjaxEvent := Value; FRebuild := true; end; procedure TUniCustomOpenDialog.SetEraseCacheAfterCompleted(const Value: Boolean); begin FButton.EraseCacheAfterCompleted := Value; FRebuild := true; end; procedure TUniCustomOpenDialog.SetFilter(const Value: string); begin FButton.Filter := Value; FRebuild := true; end; procedure TUniCustomOpenDialog.SetMaxAllowedSize(const Value: Cardinal); begin FButton.MaxAllowedSize := Value; FRebuild := true; end; procedure TUniCustomOpenDialog.SetMaxFiles(const Value: Cardinal); begin FButton.MaxFiles := Value; FRebuild := true; end; procedure TUniCustomOpenDialog.SetMessages(const Value: TUniCustomUploadMessages); begin FButton.Messages := Value; FRebuild := true; end; procedure TUniCustomOpenDialog.SetMultipleFiles(const Value: Boolean); begin FButton.MultipleFiles := Value; FRebuild := true; end; procedure TUniCustomOpenDialog.SetOnCompleted(const Value: TUploadNotifyEvent); begin FOnCompleted := Value; end; procedure TUniCustomOpenDialog.SetOnMultiCompleted( const Value: TUploadMultiNotifyEvent); begin FOnMultiCompleted := Value; end; procedure TUniCustomOpenDialog.SetOverwrite(const Value: Boolean); begin FButton.Overwrite := Value; FRebuild := true; end; procedure TUniCustomOpenDialog.SetTimeoutMS(const Value: Integer); begin FButton.TimeoutMS := Value; FRebuild := true; end; procedure TUniCustomOpenDialog.SetTimeoutSecs(const Value: Integer); begin FButton.TimeoutSecs := Value; FRebuild := true; end; procedure TUniCustomOpenDialog.ButtonSingleCompleted(Sender: TObject; AStream: TFileStream); var FileStream: TFileStream; s : string; begin if not FButton.MultipleFiles then begin if TDirectory.Exists(FTargetFolder) then begin s := IncludeTrailingPathDelimiter(FTargetFolder) + FButton.FileName; if FileExists(s) and not fButton.Overwrite then raise Exception.Create('UniOpenDialog: File "'+s+'" already exists. An overwrite is not allowed'); FFiles.Clear; FileStream := TFileStream.Create(s, fmCreate); try FileStream.CopyFrom(AStream, AStream.Size); if FButton.EraseCacheAfterCompleted then DeleteFile(AStream.FileName); finally FileStream.Free; end; end else s := AStream.FileName; FFiles.Add(s); if Assigned(FOnCompleted) then FOnCompleted(Self, AStream); if FileExists(s) and Assigned(FOnFilesReady) then FOnFilesReady(Self); end; end; procedure TUniCustomOpenDialog.ButtonMultiCompleted(Sender: TObject; Files: TUniFileInfoArray); var I: Integer; s : string; FileStream: TFileStream; begin if FButton.MultipleFiles then begin FFiles.Clear; for I := Low(Files) to High(Files) do begin if Files[I].Success and Assigned(Files[I].Stream) then begin if TDirectory.Exists(FTargetFolder) then begin s := IncludeTrailingPathDelimiter(FTargetFolder) + Files[I].OriginalFileName; if FileExists(s) and not fButton.Overwrite then raise Exception.Create('UniOpenDialog: File "'+s+'" already exists. An overwrite is not allowed'); FileStream := TFileStream.Create(s, fmCreate); try FileStream.CopyFrom(Files[I].Stream, Files[I].Stream.Size); if FButton.EraseCacheAfterCompleted then DeleteFile(Files[I].Stream.FileName); finally FileStream.Free; end; end else s := Files[I].CacheFile; FFiles.Add(s); end; end; if Assigned(FOnMultiCompleted) then FOnMultiCompleted(Self, Files); // inform the owner that files are ready to process if (FFiles.Count >0) and Assigned(FOnFilesReady) then FOnFilesReady(Self); end; end; end.
  9. Hi, I am reopening an older support request from 2019, which is shown below. I am running 1.90.0.1565 and the previous solution no longer works. Does anyone have a proper solution for scrolling the uniTreeMenue vertically? I also tested to put the UniTreeMenu within a Scrollbox, but unfortuantely the size of UniTreeMenu keeps constant independing if you inflate sub-menus. Unfortunately I have a customer, who complains on this - so I urgently need to find a solution here. Kind regards, Kattes
  10. Hello, I am running 1.90.0.1565 and the previous solution no longer works. Does anyone have a proper solution for scrolling the uniTreeMenue vertically? For the solution, please look here;
  11. @Sherzod: I have created a new class UniOpenDialog based on UniFileUploadButton, which can be used as a non-visual component in UniGUI. Basically it works like a wrapper of UniFileUploadButton. My first idea to manipulate the settings of UniFileUploadButton from the JS side seems to be too complicated and would also have a high risk of incompatibility with future versions of UniGui. So I decided to rebuild UniFileUploadButton at runtime if parameters have been changed. Do you think this could be worthwhile for others? If so, I could share my sources with you for free so you can include it in one of the next official releases. Here is the class definition I created: type TUniCustomOpenDialog = class(TUniComponent) private FButton: TUniFileUploadButton; FOnFilesReady: TNotifyEvent; FAjaxEvent: TUniAjaxEvent; FOnCompleted: TUploadNotifyEvent; FOnMultiCompleted: TUploadMultiNotifyEvent; FFiles : TStringList; FFilter : string; FTargetFolder : string; FRebuild : boolean; function GetEraseCacheAfterCompleted: Boolean; procedure SetEraseCacheAfterCompleted(const Value: Boolean); function GetMessages: TUniCustomUploadMessages; procedure SetMessages(const Value: TUniCustomUploadMessages); function GetMaxAllowedSize: Cardinal; procedure SetMaxAllowedSize(const Value: Cardinal); function GetMaxFiles: Cardinal; procedure SetMaxFiles(const Value: Cardinal); function GetMultipleFiles: Boolean; procedure SetMultipleFiles(const Value: Boolean); function GetFilter: string; procedure SetFilter(const Value: string); function GetAjaxEvent: TUniAjaxEvent; procedure SetAjaxEvent(const Value: TUniAjaxEvent); procedure SetOverwrite(const Value: Boolean); function GetOverwrite: Boolean; function GetTimeoutMS: Integer; procedure SetTimeoutMS(const Value: Integer); function GetTimeoutSecs: Integer; procedure SetTimeoutSecs(const Value: Integer); procedure SetOnMultiCompleted(const Value: TUploadMultiNotifyEvent); procedure SetOnCompleted(const Value: TUploadNotifyEvent); procedure ButtonSingleCompleted(Sender: TObject; AStream: TFileStream); procedure ButtonMultiCompleted(Sender: TObject; Files: TUniFileInfoArray); public constructor Create(AOwner: TComponent); destructor Destroy; override; procedure Execute; property EraseCacheAfterCompleted: Boolean read GetEraseCacheAfterCompleted write SetEraseCacheAfterCompleted; property Files: TStringList read FFiles write FFiles; property Filter: string read GetFilter write SetFilter; property TargetFolder: string read FTargetFolder write FTargetFolder; property MaxAllowedSize: Cardinal read GetMaxAllowedSize write SetMaxAllowedSize; property MaxFiles: Cardinal read GetMaxFiles write SetMaxFiles; property Overwrite: Boolean read GetOverwrite write SetOverwrite default True; property OnFilesReady: TNotifyEvent read FOnFilesReady write FOnFilesReady; property OnAjaxEvent: TUniAjaxEvent read FAjaxEvent write FAjaxEvent; property OnCompleted: TUploadNotifyEvent read FOnCompleted write SetOnCompleted; property OnMultiCompleted: TUploadMultiNotifyEvent read FOnMultiCompleted write SetOnMultiCompleted; property MultipleFiles: Boolean read GetMultipleFiles write SetMultipleFiles; property Messages:TUniCustomUploadMessages read GetMessages write SetMessages; property TimeoutSecs: Integer read GetTimeoutSecs write SetTimeoutSecs; property TimeoutMS: Integer read GetTimeoutMS write SetTimeoutMS; end;
  12. I created this test environment. Unfortunately I cannot see any influences when changing the settings from the server side. procedure TMainForm.UniButtonApplyClick(Sender: TObject); begin UniFileUploadButton1.MultipleFiles := UniCheckBoxMultiple.Checked; UniFileUploadButton1.MaxAllowedSize := trunc(UniNumberEditMaxAllowedSize.Value); UniFileUploadButton1.MaxFiles := trunc(UniNumberEditMaxFiles.Value); UniFileUploadButton1.Filter := UniEditFilter.Text; end; FileUpload-DragDrop-Test.zip
  13. Hi, I need to change some properties of this component at runtime. In detail I want to change: property Filter: string read GetFilter write SetFilter; property MaxAllowedSize: Cardinal read GetMaxAllowedSize write SetMaxAllowedSize; property MultipleFiles: Boolean read GetMultipleFiles write SetMultipleFiles; property Messages:TUniCustomUploadMessages read GetMessages write SetMessages; Thank you and regards, Kattes
  14. Thank you Wilton for this inspiration!
  15. Very nice, Fred! I am also working on a sticky note solution for an office software. Inspired by all the sticky notes I found during my visits to customers' offices. All their monitors are full of these notes - so the dashboard user interface was a clear thing 😀
  16. So to be on the safe side, we only need to install the newer runtime on the same server and the application automatically will look for the right runtime environment? So nothing else to do or to consider - no side effects?
  17. Dear Sherzod, first of all, thank you very much for your quick reply. UniDBGrid1.ClientEvents.ExtEvents.SetText('reconfigure=function reconfigure(sender, store, columns, oldStore, oldColumns, eOpts)'+ ' { if (columns[3].isSortable()) { columns[3].sort('''+cSort+''') }}'); In principle your solution works, but has some side effect to the "Locate" command I am using to select a specific row in the UniDBGrid. procedure TuDashboardFrame.UniDBGrid1AfterLoad(Sender: TUniDBGrid); var FD : TFDQuery; iTID : integer; begin iTID := UniMainModule.TicketID; FD := TFDQuery(UniDBGrid1.Datasource.DataSet); if GetValueAsInteger(FD,'Ticket_Id') <> iTID then begin FD.Refresh; FD.Locate('Ticket_ID',iTID,[]); end; end; The "Locate" no longer works. Do you have another suggestion? Finally, I just want to get control over the sort indicator without having it also re-sort the contents of the assigned column.
  18. Hi, is there any solution for the newer UniGui versions? Best regards, Kattes
  19. For me the following code for mobile environment worked: UniSession.AddJS(UnimScrollBox1.JSName+'.getScrollable().scrollTo(0, 0);'); // Scroll to Top
  20. Hi again, Please forget my question above - I finally found out that not uniGUI is responsible for the issue with Safari mobile. The problem comes from an Iframe I used to wrap the uniGUI application into an external HTML page. To get my problem fixed I just added the following to the HTML-code of my wrapper: <script> window.addEventListener('touchstart', {}); </script> So if anyone comes across the same problem with iframes, this is the solution. Best regards, Kattes
  21. Hi there, Just a very simple question: Is it possible to use mouse events (OnMouseDown, OnMouseClick, OnMouseUp) in a standard uniGUI application if running it on an iPhone Safari browser? It seems so that none of these events are working if this browser is used. No problems with Chrome and Android, but Safari mobile seems to be somehow "special". Kind regards, Kattes
  22. Thank you Sherzod. As always I appreciate your help!
  23. Yes, this is exactly what I mean. The program assigns two different UnimImages the same content only with a different size - but you will get two different pattern. If you scan the sharper QR-Code it will show you something which was build in the past from a totally different session, which also could be closed already. So it really looks like a memory crosstalk problem.
  24. Can you try my exe, please?
  25. Have you tried my compiled exe or did you build a new one?
×
×
  • Create New...