Category: Firemonkey

How to use many styles of TTF font in firemonkey android apps

Here is a description, how to use TTF fonts in the Firemonkey Android application: http://firemonkeyblog.blogspot.com/2014/12/using-custom-fonts-in-android-delphi.html. Everything is nice, but how to do it if the TTF font has several styles in several files, such as the Roboto font ? UPDATE: The problem is partially solved. If in the object's properties ( TextSettings - FontFamily) we will enter the name of the font file, eg Roboto-Bold, everything is OK. However, when trying to dynamically / programmatically assign the font file name to the FontFamily property - then it does not work. I don't know why.
Read More

One Codebase – Multiple Targets

FNC

This week we focused on FNC, with a series of media content, brought to you via Facebook, Twitter, blog posts and other media channels. We wanted to focus on what FNC is by highlighting each framework and its corresponding operating systems individually. Here is a sample of what this looks like for the WEB.

We plan on using this for communication, promotion, technical articles, and we believe this will allow you, as a customer, have a better understanding on what FNC is. Below is an overview of what FNC offers, and what it can potentially mean for your application.

TMS FNC Controls can be simultaneously used on these frameworks:

  • VCL
  • WEB
  • FMX
  • LCL

TMS FNC Controls can be simultaneously used on these operating systems/browsers:

TMS FNC Controls can be simultaneously used on these IDE’s:

One Codebase

With FNC, we aim for one code base, that can be re-used on all the supported frameworks and eventually target multiple operating systems. We started with FMX and VCL, and thanks to the high level of abstraction we added LCL support which gave us access to Unix operating systems. Recently, we have added WEB support as well via TMS WEB Core. As an example, we have created an FNC overview demo to demonstrate the “one-codebase – multiple targets” principle.

We are currently also working very hard on a BETA of FNC, which brings a lot of small improvements and fixes, but also brings 2 new components: TTMSFNCPDFLib and TTMSFNCGraphicsPDFIO. In case you missed the blog post demonstrating these 2 components, check out the blog post at the following URL: https://www.tmssoftware.com/site/blog.asp?post=560. The blog post focusses on creating a report in PDF completely generated client-side in the webbrowser. It shows how to mix custom PDF content and existing FNC components and of course also works on the “one codebase – multiple targets” principle explained in this blog post.

We want your feedback!

Please feel free to leave a comment, send us an email with suggestions on this approach and what we can improve in our communication. We want you to get a smile out of your application, because a smiling application, is a smiling customer!

Read More

Read More

what are the definition of the placeholders found in Entitlement.TemplateiOS.xml?

what are the definition of the placeholders found in Entitlement.TemplateiOS.xml under delphi Rio ? <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <%getTaskAllowKey%> <%applicationIdentifier%> <%pushNotificationKey%> <%keychainAccessGroups%> </dict> </plist>
Read More

TWebBrowser throwing thread exception when loading html from string

I'm developing an app that loads a HTML string into a WebBrowser, but when I call the LoadFromString methods from WebBrowser, it throws a RuntimeException with the message: java.lang.RuntimeException: java.lang.Throwable: A WebView method was called on thread 'Thread-2'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 2) {c7ba400} called on null, FYI main Looper is Looper (main, tid 2) {c7ba400}) The HTML is stored in a file and loaded into a string just for test reasons, the final app will get the string from a DataSnap and show it using WebBrowser. This is the code: procedure LoadString; var htmlContent: String; filePath: String; dbpath: String; begin filePath := TPath.Combine(TPath.GetDocumentsPath, 'index.html'); htmlContent := TFile.ReadAllText(filePath); WebBrowser1.LoadFromStrings(htmlContent, 'about:blank'); btnSearch.Visible := False; TabControl1.GotoVisibleTab(tbResult.Index); end; I'm not using thread in this app. If relevant, I'm using Delphi 10.1 Berlin and testing in a Moto G5 with Android 9.
Read More

how to setup the value for com.apple.developer.associated-domains in MyApp.entitlements?

When I try to upload my app (made with delphi Rio) to the appStore I have this error message: ERROR ITMS-90046: "Invalid Code Signing Entitlements. Your application bundle's signature contains code signing entitlements that are not supported on iOS. Specifically, value '*' for key 'com.apple.developer.associated-domains' in 'Payload/myapp.app/myapp' is not supported." then I look in the myApp.entitlements that Delphi generate and I have: <key>com.apple.developer.associated-domains</key> <string>*</string> But the problem I don't see where I can change this value? it's seam it's the "*" who make a problem, but don't see where I can change it
Read More

Ate too much candy? Calculate and export your BMI to PDF with FNC for the WEB!

Ate too much candy?

We all have those moments in life where we are proud of what we have achieved, be it in sports, school, at work… . Whenever we have reached a goal, were hard work lies at the base of it, we tend to reward ourselves with something that makes us even more excited of what we have achieved. For me, that something is candy. I know, I should be eating less of it, but hey!, I have earned it! As I’m obviously eating too much of it, I created a BMI calculation app to track if I should stop eating, or if there is still room for one tiny sweet piece of candy.

FNC for the web!

The application, which calculates the BMI, is written with the help of TMS FNC UI Pack, TMS FNC Dashboard Pack and TMS WEB Core and is running in the webbrowser. It allows entering your name, height (cm) and your weight (kg). The calculate button will indicate your BMI in the grid, allowing you to know if you should loose or gain some weight, or if you are absolutely perfect.

PDF for the web!

The BMI application is allowing you to export your data to PDF. Typically, when generating a report, invoice, or any other PDF data file in the browser, this is done on a back end server. The costs to handle the load, scalability can quickly rise and the maintenance gives a lot of headaches. With the TTMSFNCPDFLib and TTMSFNCGraphicsPDFIO components that are both used in the BMI application you no longer need a backend to generate a PDF in your web application. The components completely generate the PDF at the client-side (front end).

The TTMSFNCPDFLib component is used to generate the PDF, and the TTMSFNCGraphicsPDFIO component is a bridge to export FNC UI controls such as the TTMSFNCPlanner, TTMSFNCGrid, TTMSFNCChart and many more. In the BMI web application, both are used to combine the custom PDF exporting capabilities with the TTMSFNCGrid and TTMSFNCWidgetGauge components.

The code behind this is actually very simple.

procedure TPDFLibBMILogic.GeneratePDF;
var
  fn: string;
  o: TTMSFNCPDFIOExportObjectArray;
  r: TTMSFNCPDFIOExportRectArray;
  ms: TMemoryStream;
begin
  {$IFDEF ANDROID}
  fn := TPath.GetSharedDocumentsPath + PathDelim + 'BMI.pdf';
  {$ENDIF}
  {$IFDEF MACOS}
  fn := TPath.GetDocumentsPath + PathDelim + 'BMI.pdf';
  {$ENDIF}
  {$IFNDEF ANDROID}
  {$IFNDEF MACOS}
  fn := 'BMI.pdf';
  {$ENDIF}
  {$ENDIF}
  p.Options.Header := 'BMI Report for ' + FName;
  SetLength(o, 2);
  o[0] := FGauge;
  o[1] := FGrid;
  SetLength(r, 2);
  r[0] := RectF(50, 180, 50 + FGauge.Width, 180 + FGauge.Height);
  r[1] := RectF(50 + FGauge.Width + 50, 180, 50 + FGauge.Width + 50 + FGrid.Width, 180 + FGrid.Height);
  ms := TMemoryStream.Create;
  try
    p.Save(ms, o, r);
    ms.SaveToFile(fn);
    {$IFNDEF WEBLIB}
    TTMSFNCUtils.OpenFile(fn);
    {$ENDIF}
  finally
    ms.Free;
  end;
end;

The result, when clicking on the “Export To PDF” button, is shown below

Play with the demo yourself!

Curious on how the demo works, or if you want to know if you can eat more candy? Below is a link that shows the demo live! Note that the components, demo is currently not yet released, but we are working hard on a beta of FNC that is coming real soon, so stay tuned!

https://download.tmssoftware.com/tmsweb/demos/TMSWeb_FNCPDFLib_BMI/

Read More

Read More

TMS WEB Core v1.2 tips & tricks part 8: 3D Charts made easy

One of the big new features in TMS WEB Core v1.2 Padua is the built-in support for 3D graphics. This is accomplished by providing Object Pascal components and classes that wrap the powerful ThreeJS / WebGL libraries for rendering 3D graphics in the browser. This technology is meanwhile supported on every mainstream browser, including on mobile devices.

As always, the goal of TMS WEB Core is to offer OO RAD Component based we development, so, integrating 3D graphics in your TMS WEB Core web client applications becomes a piece of cake. So, let’s immediately jump to writing the code as an inspiration to get you started exploring the wonderful 3D web world.

When interfacing with an existing JavaScript libraries is done from a TMS WEB Core application, we have made it equally easy to setup the link references to these libraries. In case of 3D we will need the ThreeJS library. So, from the project context menu in the Delphi IDE select “Manage JavaScript Libraries” and from there check to use ThreeJS.

Next, put a TWebThreeJSChart on the form and you can start defining series for your chart. Since climate change is a bit a “hot” topic (pun intended) in the last years everywhere, for our sample we got the idea to render the average month temperatures in Belgium (where our main TMS office is located) for the past 3 years. We got the data from a website that lists the temperature measurements since 1833. You can find the data here.

The series we want to display are a series with all months of the year and a series for years. A series is of the type TThreeJsChartSeries and is created with the X and Y axis labels via:

var
  aSeries: TThreeJsChartSeries;

begin
  aSeries := TThreeJsChartSeries.Create(
   TJSArray.New('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'), 
   TJSArray.New('2017', '2018', '2019'));
end;

As you can see, we can create in Object Pascal a dynamic JavaScript array that ThreeJS needs via TJSArray.New(values).

Next, let’s add values for each month for the 3 years to the series. This is done for a month via:

  aSeries.addLegendRow('Jan', TJSArray.New(1.1, 6.0, 3.0));

Other than this, all we need is to setup things like title, X-axis label, Y-axis label, Z-axis label, Z-axis maximum and step value and the formatting of the values along the Z-Axis. When this is ready, to display the series, we simply clear any possible previous series that were setup and then assign the series created and call WebThreeJsChart.createChart.

One more property available in a series is the property TThreeJsChartSeries.ChartType. The 3D chart supports following types: ctBarChart, ctCylinderChart, ctConeChart, ctLineChart, ctAreaChart.

The total code becomes:

procedure TForm1.InitChart(AType: TThreeJSChartType);
var
  aSeries: TThreeJsChartSeries;
begin
  aSeries := TThreeJsChartSeries.Create(
    TJSArray.New('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'),
    TJSArray.New('2017', '2018', '2019')
  );

  aSeries.addLegendRow('Jan', TJSArray.New(1.1, 6.0, 3.0));
  aSeries.addLegendRow('Feb', TJSArray.New(6.1, 0.8, 7.0));
  aSeries.addLegendRow('Mar', TJSArray.New(9.6, 5.4, 8.5));
  aSeries.addLegendRow('Apr', TJSArray.New(8.8, 13.0, 11.0));
  aSeries.addLegendRow('May', TJSArray.New(15.5, 16.3, 12.0));
  aSeries.addLegendRow('Jun', TJSArray.New(19.2, 18.1, 0));
  aSeries.addLegendRow('Jul', TJSArray.New(18.3, 22.0, 0));
  aSeries.addLegendRow('Aug', TJSArray.New(18.1, 19.4, 0));
  aSeries.addLegendRow('Sep', TJSArray.New(14.1, 15.4, 0));
  aSeries.addLegendRow('Oct', TJSArray.New(13.3, 12.6, 0));
  aSeries.addLegendRow('Nov', TJSArray.New(6.6, 7.4, 0));
  aSeries.addLegendRow('Dec', TJSArray.New(4.4, 5.8, 0));

  aSeries.valueAxisMarkMaximum := 30;
  aSeries.valueAxisMarkStep := 5;
  aSeries.ChartType := AType;
  aSeries.valueFormatFloat := '#,##0°C';
  aSeries.Title := 'Average month'#13#10'temperatures Belgium';
  aSeries.ValueAxisTitle := 'Temp';
  aSeries.LegendAxisTitle := 'Months';
  aSeries.CategoryAxisTitle := 'Year';

  WebThreeJsChart1.Series := aSeries;
  WebThreeJsChart1.clearChart;
  WebThreeJsChart1.createChart;
end;

Finally, we want to add one more additional tip and that is a frequently asked question how we can easily center a control in the browser window using pure Object Pascal code instead of what is in web development more commonly done using HTML/CSS. Well, the good news is that in Object Pascal this is also very easy. Add an event hanlder for Form.OnResize and write the code:

procedure TForm1.WebFormResize(Sender: TObject);
begin
  if WebThreeJsChart1.Width 


This results in the chart with the numbers we have till now, May 2019:



or better discover it live here

There is much more than doing just 3D charts with ThreeJS and TMS WEB Core, there are also samples for creating surface charts, show 3D model files or setup your own 3D scenes. Discover these and more exciting features in TMS WEB Core that let you create web client applications with unprecedented capabilities.

You can download the trial version, go ahead with the standalone version you purchased or with TMS WEB Core and additional tools that are all included in TMS ALL-ACCESS. Our team looks forward to all your comments, feedback, feature-requests to help steering the development of TMS WEB Core to the next stages!

Read More

Read More

Delphi Now Has Linux UI Support

Just announced, FMXLinux has been licensed from KSDev for inclusion in the Enterprise and Architect editions of RAD Studio and related products (Delphi & C++ Builder).  The product is available via GetIt for all current subscribers. Since I have been following FMXLinux’s development for some time, I immediately installed the licensed version.  Unfortunately, the IDE experience is the same as the trial I previously installed directly from KSDev. I created a new Multi-device application with tabbed navigation from the wizard.  Looking at the list of target platforms (Android, Mac OS, iOS, Windows) I didn’t see Linux.  Fair enough, the templates on which the application is based do not contain the new UI platform.  Perhaps in a subsequent release since as per Marco’s introduction the product has not been fully integrated into the IDE. I went to add the new platform to the solution, by Rt. clicking The Target Platforms node in the project manager and it is greyed out.  If I delete a target it is re-enabled, but the list of targets I can add only contains the one I just deleted.  Rt. Clicking on the Application node in Projects window, there is an option “Add Linux Platform”.  Now I get a Linux 64 bit target platform node. This is covered in Marco’s introduction, but he doesn’t mention that attempting to add a component to my UI doesn’t work.  I can’t add a button to my form until I switch to another target platform, and then switch back so I can actually deploy and test on Linux.  This has been a known issue with the trial, and I was hopeful that such a poor user experience would be fixed now that EMBT has licensed the product.  For now, it’s an issue you will have to work around, and I’m sure it will be corrected in a future release. While only major Linux distros are currently supported (Ubuntu, RedHat and possibly a couple others) the team at KSDEV are working to support others including the more obscure ones like Elementary OS.  I for one am very pleased that Delphi finally can target Linux with GUI applications making it a complete XPlatform desktop solution for all 3 major targets.
Read More

iOS: how to add a title to a date picker dialog

I would like to add a title to a Date Picker Dialog. This is how I create the date picker dialog : // We should Create instance of UIDatePicker before creating main container. // Because We use UIViewPicker for determinate finally size of picker container // (Toolbar + Picker) FUIDatePicker := TUIDatePicker.Create; FUIDatePicker.setTimeZone(TNSTimeZone.Wrap(TNSTimeZone.OCClass.timeZoneForSecondsFromGMT(0))); FUIDatePicker.setDatePickerMode(UIDatePickerModeDate); { Subscribing to change orientation events } DefaultNotificationCenter.addObserver(GetObjectID, sel_getUid('DeviceOrientationChanged'), StringToID(FMXViewControllerFrameChanged), nil); { Creating Root view container for picker } FUIOverlayView := TUIView.Create; aUIColor := AlphaColorToUIColor($32000000); FUIOverlayView.setBackgroundColor(aUIColor); FUIOverlayView.setAutoresizingMask(UIViewAutoresizingFlexibleWidth or UIViewAutoresizingFlexibleHeight or UIViewAutoresizingFlexibleLeftMargin or UIViewAutoresizingFlexibleRightMargin or UIViewAutoresizingFlexibleTopMargin or UIViewAutoresizingFlexibleBottomMargin); FUIOverlayView.setFrame(CGRect.Create(0, 0, screen.Size.Width, screen.Size.Height)); aSingleTapGestureRecognizer := TUITapGestureRecognizer.Wrap(TUITapGestureRecognizer.Alloc.initWithTarget(GetObjectID, sel_getUid('HandleTap'))); aSingleTapGestureRecognizer.setDelegate(GetObjectID); aSingleTapGestureRecognizer.setNumberOfTapsRequired(1); try FUIOverlayView.addGestureRecognizer(aSingleTapGestureRecognizer); finally aSingleTapGestureRecognizer.release; end; { Creating Root view container for picker } FUIContainerView := TUIView.Create; FUIContainerView.setBackgroundColor(TUIColor.Wrap(TUIColor.OCClass.whiteColor)); FUIContainerView.setAutoresizingMask(UIViewAutoresizingFlexibleWidth or UIViewAutoresizingFlexibleLeftMargin or UIViewAutoresizingFlexibleRightMargin); FUIContainerView.setFrame(GetPopupFrame); FUIContainerView.layer.setMasksToBounds(true); FUIContainerView.layer.setCornerRadius(12); { Creating Toolbar } FUIToolBar := TUIToolbar.Create; FUIToolBar.setAlpha(0.8); FUIContainerView.addSubview(FUIToolBar); CreateToolbarConstraint; { Creating Toolbar buttons } aButtons := TNSMutableArray.Create; try { Adding Flexible Separator } FUIFlexibleSepararator1 := TUIBarButtonItem.Create; FUIFlexibleSepararator1.initWithBarButtonSystemItem(UIBarButtonSystemItemFixedSpace, nil, nil); FUIFlexibleSepararator1.setWidth(5); aButtons.addObject(NSObjectToID(FUIFlexibleSepararator1)); { Adding clear Button } if aBtnClearCaption <> '' then begin FUIClearButton := TUIBarButtonItem.Create; FUIClearButton.setTitle(StrToNSStr(aBtnClearCaption)); FUIClearButton.setStyle(UIBarButtonItemStyleBordered); FUIClearButton.setTarget(Self.GetObjectID); FUIClearButton.setAction(sel_getUid('Clear')); aButtons.addObject(NSObjectToID(FUIClearButton)); end else FUIClearButton := nil; { Adding Flexible Separator } FUIFlexibleSepararator2 := TUIBarButtonItem.Create; FUIFlexibleSepararator2.initWithBarButtonSystemItem(UIBarButtonSystemItemFlexibleSpace, nil, nil); aButtons.addObject(NSObjectToID(FUIFlexibleSepararator2)); { Adding Close Button } if aBtnCancelCaption <> '' then begin FUICancelButton := TUIBarButtonItem.Create; FUICancelButton.setTitle(StrToNSStr(aBtnCancelCaption)); FUICancelButton.setStyle(UIBarButtonItemStyleBordered); FUICancelButton.setTarget(Self.GetObjectID); FUICancelButton.setAction(sel_getUid('Cancel')); aButtons.addObject(NSObjectToID(FUICancelButton)); end else FUICancelButton := nil; { Adding Flexible Separator } FUIFlexibleSepararator3 := TUIBarButtonItem.Create; FUIFlexibleSepararator3.initWithBarButtonSystemItem(UIBarButtonSystemItemFixedSpace, nil, nil); FUIFlexibleSepararator3.setWidth(28); aButtons.addObject(NSObjectToID(FUIFlexibleSepararator3)); { Adding Done Button } FUIDoneButton := TUIBarButtonItem.Create; FUIDoneButton.setTitle(StrToNSStr(aBtnOKCaption)); FUIDoneButton.setStyle(UIBarButtonItemStyleDone); FUIDoneButton.setTarget(Self.GetObjectID); FUIDoneButton.setAction(sel_getUid('Done')); aButtons.addObject(NSObjectToID(FUIDoneButton)); { Adding Flexible Separator } FUIFlexibleSepararator4 := TUIBarButtonItem.Create; FUIFlexibleSepararator4.initWithBarButtonSystemItem(UIBarButtonSystemItemFixedSpace, nil, nil); if aBtnClearCaption <> '' then FUIFlexibleSepararator4.setWidth(5) else FUIFlexibleSepararator4.setWidth(15); aButtons.addObject(NSObjectToID(FUIFlexibleSepararator4)); { Adding button to Toolbar } FUIToolBar.setItems(aButtons); finally aButtons.release; end; { Adding DatePicker } FUIContainerView.addSubview(FUIDatePicker); CreateCalendarConstraint; FUIOverlayView.addSubview(FUIContainerView); and {~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~} procedure CreateToolbarConstraint; var Constraint: NSLayoutConstraint; begin FUIToolBar.setTranslatesAutoresizingMaskIntoConstraints(False); Constraint := TNSLayoutConstraint.Wrap(TNSLayoutConstraint.OCClass.constraintWithItem(NSObjectToID(FUIToolBar), NSLayoutAttributeLeft, NSLayoutRelationEqual, NSObjectToID(FUIContainerView), NSLayoutAttributeLeft, 1, 0)); Constraint.setActive(True); Constraint := TNSLayoutConstraint.Wrap(TNSLayoutConstraint.OCClass.constraintWithItem(NSObjectToID(FUIToolBar), NSLayoutAttributeRight, NSLayoutRelationEqual, NSObjectToID(FUIContainerView), NSLayoutAttributeRight, 1, 0)); Constraint.setActive(True); Constraint := TNSLayoutConstraint.Wrap(TNSLayoutConstraint.OCClass.constraintWithItem(NSObjectToID(FUIToolBar), NSLayoutAttributeBottom, NSLayoutRelationEqual, NSObjectToID(FUIContainerView), NSLayoutAttributeBottom, 1, 0)); Constraint.setActive(True); Constraint := TNSLayoutConstraint.Wrap(TNSLayoutConstraint.OCClass.constraintWithItem(NSObjectToID(FUIToolBar), NSLayoutAttributeHeight, NSLayoutRelationEqual, nil, NSLayoutAttributeNotAnAttribute, 1, _ToolBarHeight)); Constraint.setActive(True); end; {~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~} procedure CreateCalendarConstraint; var Constraint: NSLayoutConstraint; begin FUIDatePicker.setTranslatesAutoresizingMaskIntoConstraints(False); Constraint := TNSLayoutConstraint.Wrap(TNSLayoutConstraint.OCClass.constraintWithItem(NSObjectToID(FUIDatePicker), NSLayoutAttributeLeft, NSLayoutRelationEqual, NSObjectToID(FUIContainerView), NSLayoutAttributeLeft, 1, 0)); Constraint.setActive(True); Constraint := TNSLayoutConstraint.Wrap(TNSLayoutConstraint.OCClass.constraintWithItem(NSObjectToID(FUIDatePicker), NSLayoutAttributeRight, NSLayoutRelationEqual, NSObjectToID(FUIContainerView), NSLayoutAttributeRight, 1, 0)); Constraint.setActive(True); Constraint := TNSLayoutConstraint.Wrap(TNSLayoutConstraint.OCClass.constraintWithItem(NSObjectToID(FUIDatePicker), NSLayoutAttributebottom, NSLayoutRelationEqual, NSObjectToID(FUIToolBar), NSLayoutAttributetop, 1, 0)); Constraint.setActive(True); Constraint := TNSLayoutConstraint.Wrap(TNSLayoutConstraint.OCClass.constraintWithItem(NSObjectToID(FUIDatePicker), NSLayoutAttributeHeight, NSLayoutRelationEqual, nil, NSLayoutAttributeNotAnAttribute, 1, _DefaultPickerHeight)); Constraint.setActive(True); end; Any idea what i need to change in this code in order to add a title ?
Read More