Formatted emails (HTML email) from TAdvRichEditor

Bookmarks: 

Tuesday, September 12, 2017

Our TAdvRichEditor UI control has everything on-board to generate HTML from its rich document content, including exporting images that are possibly used in the document. Although generating this HTML can be easily done via the TAdvRichEditorHTMLIO non-visual component connected to the TAdvRichEditor, we frequently receive support emails from users struggling to use the generated HTML to send it as email with the Indy components (TIdMessage, TidSMPT).

Therefore, we decided not only to create a sample code snippet to show how this can be done, but also to create a non-visual component (available in the latest TMS Component Pack release) to reduce the code to generate such email message to the minimum possible, that is, to one line of code:
    emailio.GenerateEmail(idmessage);

But, back to full code first that shows how to use the Indy components to generate HTML emails with embedded images as this can be generally applied for cases also where no TAdvRichEditor is used.

Drop a TIdMessage component on the form. We create a multipart message, with a part for the plain text version of the email, a part for the HTML email header and a part for the HTML itself. Then we add attachments to the message where ContentDisposition is set to 'inline' and the ContentID is set to the ID used in the HTML image reference cid attribute. So, if we have in the HTML code an image reference like:

then the ContentID for the attachment containing the image will be :
ContentID := 'imageref1';

Now, let's put this together using a TAdvRichEditor, TAdvRichEditorHTMLIO, idMessage on the form. We set AdvRichEditorHTMLIO.RichEditor to the TAdvRichEditor instance we want to export. It is very important to set AdvRichEditor.HTMLImages to igID as this instructs the TAdvRichEditor to export images references as CID URI attributes. The export to HTML and image files from TAdvRichEditor becomes:
var
  i: integer;
begin
  AdvRichEditor1.HTMLImages := igID;
  // we save the output to a temporary HTML file
  AdvRichEditorHTMLIO1.Save('.
icheditor.html');

  for i := 0 to AdvRichEditor1.HTMLImageList.Count - 1 do
    begin
      // we prepare the images as temporary images files for use as attachments for the message
      AdvRichEditor1.HTMLImageList.Items[i].SaveToFile('.img'+i.ToString+'.png');
    end;
end;

As you can see, the images to be used in the export are available via the collection AdvRichEditor.HTMLImageList. From there, we can save the images to file to be used as attachments for the Indy idMessage. The code to construct the idMessage from here becomes:
  idMessage1.IsEncoded := True ;
  idMessage1.ContentType := 'multipart/alternative';
  idMessage1.ClearBody;

  with TIdText.Create(idMessage1.MessageParts, nil) do
  begin
    // here we include the text as plain text
    Body.Text := AdvRichEditor1.PlainText;
    ContentType := 'text/plain';
  end;

  with TIdText.Create(idMessage1.MessageParts, nil) do
  begin
    ContentType := 'multipart/related; type="text/html"';
  end;

  with TIdText.Create(idMessage1.MessageParts, nil) do
  begin
    // we load the content from the temporary HTML file
    Body.LoadFromFile('.
icheditor.html');
    ContentType := 'text/html';
    ParentPart := 1;
  end;

  // here we loop over images to add all as attachments 
  for i := 0 to FRichEditor.HTMLImageList.Count - 1 do
  begin
    with TIdAttachmentFile.Create(idMessage1.MessageParts,  + '.img' + i.ToString + '.png') do
    begin
      ContentID := 'image'+ i.ToString;
      ContentType := 'image/png';
      ContentDisposition := 'inline';
      ParentPart := 1;
    end;
  end;

When the idMessage message has been created, it is straightforward to send it via the idSMTP component, i.e., this is minimally:
  IdMessage1.From.Address := 'info@tmssoftware.com';
  IdMessage1.Recipients.Add.Address := 'bruno@tmssoftware.com';
  IdMessage1.Sender.Address := 'info@tmssoftware.com';

  idsmtp1.Host := 'smtp.mailserver.com';
  IdSMTP1.Connect;
  idsmtp1.Send(idMessage1);
  idsmtp1.Disconnect();

With this code now explained, let's introduce the class TAdvRichEditorEmailIO included in unit AdvRichEditorEMailIO.pas in the latest version 8.7.3.0 of TMS Component Pack. With this class, we can reduce the code to send a HTML email from TAdvRichEditor to:
  AdvRichEditorEMailIO.GenerateEmail(idmessage);
  idMessage.Subject := 'A HTML email from TAdvRichEditor';

  idSMTP1.Host := 'smtp.mailserver.com';
  IdSMTP1.Connect;
  idSMTP1.Send(idMessage);
  idSMTP1.Disconnect();

The resulting Delphi application looks like this:

and when opening the email sent in MS Outlook, it looks like:

You can easily get started to build your own HTML formatted text email client. You can download the source code of the application here and you can compile and use this with the latest TMS Component Pack release. In the next updates of TMS FMX UI Pack that also includes the FireMonkey version of our rich editor component, we'll also include a FireMonkey version of the HTML email creator class and the same applies for the cross-framework version of the rich editor in the TMS FNC UI Pack.

Bruno Fierens


Bookmarks: 

This blog post has received 7 comments. Add a comment.



Join us in The Netherlands and Germany at several upcoming Delphi conferences

Bookmarks: 

Tuesday, September 05, 2017

We look forward to connect with you at the upcoming conferences! TMS will be present at following Delphi events:

The LAB - European Delphi & C++Builder Conference 2017
19 September 2017 - Eindoven, The Netherlands

TMS software will be present with a booth where you can meet us and find out about our latest product offerings.
Bruno Fierens will give a session about VCL & FMX Delphi applications based on Google Maps and TMS WebGMaps. He will demonstrate how locations on the map can be indicated in different ways, how addresses can be associated with locations, how locations can be coupled to pictures and how to load POI files and visualize the POIs on the map. Furthermore, route directions can be calculated, displayed and imported & exported for exchange with navigation systems or smartphone apps. Finally the GeoJSON file format is explained and it is shown how these can be used together with Google Maps.Dutch spoken


Foren-Tage 2017
23 September 2017 - Hamburg, Germany

TMS software will be present with a booth where you can meet us and find out about our latest product offerings.
Bruno Fierens will give a session about VCL & FMX Delphi applications based on Google Maps and TMS WebGMaps. He will demonstrate how locations on the map can be indicated in different ways, how addresses can be associated with locations, how locations can be coupled to pictures and how to load POI files and visualize the POIs on the map. Furthermore, route directions can be calculated, displayed and imported & exported for exchange with navigation systems or smartphone apps. Finally the GeoJSON file format is explained and it is shown how these can be used together with Google Maps.


EKON 21
24 October - Cologne, Germany

Bruno Fierens will give a presentation about creating cross-framework UI controls. The similarities and differences between the two key UI frameworks VCL and FMX that come with Delphi are explained. With this knowledge, it is possible to create an abstraction layer that allows to create UI controls that will work both in VCL applications and in FMX applications (and also in the LCL framework). The abstraction layer FNC (Framework Neutral Components) is introduced and explained and with the help of this FNC layer, it is demonstrated to create a UI control from scratch for VCL, FMX and LCL.


TMS hands-on training day
23 November 2017 - Meerbusch-Büderich, Germany

After an introduction on the latest news from Embarcadero, the first half of the day will be devoted to an in-depth look at TMS VCL components, in particular TAdvStringGrid and TAdvTreeView. In the second part of the day, focus will be on cross-platform development and cross platform UI controls. We'll round up the day with a look at Google Maps integration and a "What's cooking in the labs" session. Sessions will be in German.




Nancy Lescouhier


Bookmarks: 

This blog post has not received any comments yet. Add a comment.



TMS FNC Ribbon : modern ribbon UI on every operating system and for every Pascal framework

Bookmarks: 

Monday, September 04, 2017

With the FNC product line (framework-neutral-components), it is our vision to enable developers with a single UI controls set, a single learning-curve and a single license to have the freedom of choice to develop Delphi VCL Windows applications, Delphi FMX cross-platform applications for Windows, macOS, Android, iOS or even LCL based Lazarus applications for Windows, macOS or Linux.

Since our study & research to realize this FNC layer, we have already created a powerful grid, a flexible planning/scheduling/calendar control, a feature-rich treeview, a rich editor, a toolbar and many more smaller UI controls. The next logical step was to create a ribbon UI control to enable building modern user interfaces for your VCL, FireMonkey Delphi applications of Windows, macOS or Linux applications created with Lazarus/FPC. Our ribbon UI control takes the hard work out of your hands to offer the subtle differences a Microsoft Office 2016 style colourful ribbon UI comprises on these different operating systems.

To get started, we have integrated ribbon application and ribbon form repository items in the Delphi "new item" wizard. You can select from there to create a new VCL or FMX ribbon project or to add a new VCL or FMX ribbon form to your existing project.



It is of course also possible to add a new ribbon UI to an existing form. To do so, drop the TTMSFNCRibbon control on the form and do not forget to descend your form from TTMSFNCRibbonForm instead of a TForm.

The ribbon architecture
Let's have a look at the TTMSFNCRibbon control itself. It consists of several parts, the main parts being:



TMSFNCRibbonWrapper : This is the container component for the ribbon form caption that contains the QAT, caption text, system menu
TMSFNCRibbonQAT : This is the quick access toolbar that can sit in the window caption or below the ribbon. The position can be set via the property TTMSFNCRibbon.QATMode.
TMSFNCRibbonCaption : This represents the caption text of the window itself
TMSFNCRibbonSystemMenu : This is the application system menu typically used to close, minimize or maximize the form
TTMSFNCRibbonFileButton : This is the application menu button
TMSFNCRibbonPageControl : This is the page control that is used to paginate between different ribbon pages
TTMSFNCRibbonPageControlContainer : This is a single ribbon page that is a container for toolbars on the ribbon

To add a toolbar and toolbar controls to the ribbon, right-click the TTMSFNCRibbonPageControlContainer and from the context menu select to add a toolbar.
Next, right-click the toolbar and from the context menu you can choose to add several toolbar controls.


The controls that can be added to the ribbon toolbar are not limited to this set of controls and as such other UI controls can be added as well to the toolbar. More later about the dynamic sizing configurability of the toolbar controls and the toolbar compact mode.

Matching the Microsoft Office 2016 theme, the TTMSFNCRibbon has a property Theme from where a number of predefined colors can be selected (like the MS Word, MS Excel, MS PowerPoint ribbon colors) but this property can also be set to rbtCustom and then a custom application color can be selected with TTMSFNCRibbon.CustomThemeColor. The TTMSFNCRibbon control will automatically calculate lighter & darker color variants to make up such custom color theme. The color & appearance of each individual element on the ribbon can be customized, but the easiest way to select a consistent looking color is clearly with the TTMSFNCRibbon.Theme and TTMSFNCRibbon.CustomThemeColor setting.

The ribbon toolbar
The place where buttons for interaction with your application are placed is the ribbon toolbar and typically, controls are grouped on toolbars that belong together. By default, the size of the toolbar will automatically adapt to the number & size of controls added to the toolbar. The default size is TMSFNCRibbonToolBar.AutoSize = true, TMSFNCRibbonToolBar.AutoWidth = true, TMSFNCRibbonToolBar.AutoAlign = true. This means that when adding controls to the toolbar, these will be added starting left aligned and the size of the toolbar will grow as controls are added. The toolbar can have a dynamic sizing behavior. That means that when the application window width will become smaller or larger, the toolbar can dynamically size to fit all toolbars in the width of the ribbon. The smallest mode for the toolbar is the compact state. In this state, the toolbar is only a button and the toolbar buttons will only become visible when the toolbar compact state button is clicked. In compact state, the toolbar can display a picture on the button and this is selected via TMSFNCRibbonToolBar.CompactBitmaps: TTMSFNCScaledBitmaps. This is a collection of bitmaps that can be used for different DPI sizes. The control will decide itself what bitmap to use from the collection depending on the DPI of the screen the application is running on. Further customization of the compact state is done via TTMSFNCRibbonToolBar.CompactAppearance, TTMSFNCRibbonToolBar.CompactWidth, TTMSFNCRibbonToolBar.CompactBitmapVisible. When the toolbar is not in compact state, its controls are visible but these can be visible in different sizes. The sizes a ribbon toolbar button can have is set with TMSFNCRibbonDefaultToolBarButton.MinimumLayout, TMSFNCRibbonDefaultToolBarButton.MaximumLayout. By default, the minimum size is bblBitmap, the maximum size is bblLarge and the size in between is bblLabel. When the application is maximized for example and thus the toolbar has sufficient space, all buttons on the toolbar can be shown in bblLarge state. When the application width shrinks, the controls on the toolbar can first reduce to bblLabel state where the controls become a label with attached glyph. When the form width further shrinks, the next step is when the toolbar controls are rendered in bblBitmap state, essentially, only showing the button glyph. Of course, if for a button the MinimumLayout and MaximumLayout are both set to bblLarge, the toolbar control size will never change during application for width changes. Only when the toolbar width cannot longer fit on the ribbon, the entire toolbar will go to compact state.

Visualizing this is probably the best way to make this more clear.
In this first step, notice the Insert toolbar that has sufficient space for hosting two large state buttons:


As the form width decreases, the Insert toolbar shrinks by putting its controls in label layout:


Making the form even smaller now makes the toolbar shrink its controls to bitmap layout:


The final and smallest state of the toolbar is the compact state, where all its controls are hidden and the toolbar controls only become visible by clicking the compact state toolbar button to show the full toolbar in a popup:


The ribbon page groups
Another often used ribbon UI feature is the ribbon page groups. Sometimes functionality in the application has so much controls to interact with the features of the functionality that it is too much to have one ribbon page for it and that it is better to divide it in two or more pages. To make the ribbon pages look consistently together, the concept of page groups is used. This is a group indicator above the ribbon page tabs. Adding a ribbon page group can be easily done via the collection TTMSFNCRibbon.Groups. Add a new TMSFNCRibbonGroup item to this collection and here it can be configured what the index is of the first ribbon page in the group (TMSFNCRibbonGroup.StartPageIndex) and the last page (TTMSFNCRibbonGroup.EndPageIndex). The group can be given a group name set via TTMSFNCRibbonGroup.Text and with the group the selected ribbon page tab can have its own color set via TTMSFNCRibbonGroup.Color & TTMSFNCRibbonGroup.TextColor. The page group itself is a darker variant from the ribbon theme color. In this example, a ribbon page group was created for the Insert and Export page. The page group name is Tools and was created by setting TMSFNCRibbonGroup.StartPageIndex to 1 and TTMSFNCRibbonGroup.EndPageIndex to 2.
g := rb.Groups.Add;
g.Text := 'Tools';
g.StartPageIndex := 1;
g.EndPageIndex := 2;



The ribbon QAT
Frequently used functions, like a save, undo, ... function can be added to the always visible QAT (quick access toolbar). This QAT sits normally on the form caption or right below the ribbon. By default, on a new TMSFNCRibbon, the QAT is available on the caption. To add controls to it, also right-click the control at design-time and from the context menu select the controls to add. The QAT has by default an automatically managed option menu (at the right-side of the QAT). From this options menu, controls on the QAT can be hidden or made visible and the position of the QAT can be selected. The option menu can be further customized by implementing any of its menu event handlers like OnOptionsMenuCustomize, OnOptionsMenuItemCanShow, OnOptionsMenuMoreCommands, ...



Learn more
Several resources are available for you to learn more about our FNC abstraction layer and controls:
Blog post about FNC UI pack
Blog post about developing FNC custom controls
FNC controls video series

Conclusion
Our TMS FNC ribbon control has everything on board to allow you to add a ribbon UI to your applications, be it Delphi VCL Windows applications, cross platform FireMonkey applications or applications created with Lazarus for Windows, macOS or Linux. It is easy & fast to configure but at the same time can be extensively and in detail customized. Together with our FNC grid control, you can build Excel like user interfaces in a matter of hours, or in combination with our FNC rich editor a word processor like application, etc... Once you learned to use the TMS FNC Ribbon control, you can apply this knowledge to your next project developed against another UI control framework or you could reuse code from one application in a given framework for another application using another framework. We look forward to see awesome applications you create and hear about further needs you might have to facilitate your development and make it even faster.

Bruno Fierens


Bookmarks: 

This blog post has received 4 comments. Add a comment.



TMS Subscription Manager v2 is here

Bookmarks:  One comprehensive tool to manage any of the many bundle subscriptions you can purchase from TMS software was our goal for TMS Subscription Manager v2.0 that is now finally released. TMS Subscription Manager v2.0 supports TMS ALL-ACCESS, TMS VCL Subscription, TMS Business Subscription, TMS Component Studio, TMS FMX Component Studio, TMS FNC Component Studio and TMS IntraWeb Component Studio.

With TMS Subscription Manager v2.0, you can use a single login in this application and you get instant access to all products in the purchased bundle. For TMS ALL-ACCESS, this is at this moment a whopping 63 products. The TMS Subscription Manager v2.0 now categorizes the products neatly per technology : VCL, FMX, BIZ, FNC, DEV, .NET, IntraWeb and LCL.



Per product, you get a description, link to the product webpage, info on latest available version and release date, info on your last download version and download date and info on your last product install version and date. With colors, the status of each product is indicated. In white are products ready for download, in yellow products ready for install, in orange products for which you can meanwhile download a newer version and in green the products for which the latest version was installed, so you are up-to-date for. If you have our premier TMS ALL-ACCESS subscription, you can much easier find your way in the many products by filtering. You can open & close per product technology, you can filter to see for example only all installed products for which there is a new version, you can perform a search in product name or product description. If you perform a search on 'grid', you'll see we have a grid for VCL in the TMS Component Pack, a grid for FireMonkey in the TMS FMX UI Pack, a grid for cross-framework development in TMS FNC UI Pack and a grid for web application development in TMS IntraWeb Component Pack.

But there is more. If you are working on a project that includes several specific TMS products, you can mark these products as your favourite products by clicking the heart icon and then perform a filtering to see the latest status of only your favourite products.



The new v2.0 version also allows to start multiple downloads. To get all new releases since your last login, you could filter on "New version", then check all products and click the "Download all" button in the column header cell for the download column and it will do all downloads for you and make the products ready for install.

And that is not all, behind the scenes, TMS Subscription Manager is now keeping a backup of any product versions you have downloaded. From the settings page, the folder where all downloads are stored can be directly opened. With keeping a full backup of every single version you have downloaded (and probably installed) it is now possible to perform rollback if it would be necessary for some reason. Right-click on the downloaded version number cell per product and from the context menu you can see all available versions (if there are any) and activate another version for install.



Finally, the TMS Subscription Manager v2.0 keeps you always informed about the validity of your subscription and will guide you to the renewal order upon expiry. Last but not least, from the TMS Subscription Manager there is a comprehensive list of links to interact with us, via email, social media, forums, RSS, Youtube videos ...



To round up, some technical tidbits: TMS Subscription Manager is built with Delphi 10.2 Tokyo as a single EXE portable executable. The products are displayed and managed in our TAdvStringGrid UI control. The application will self-update thanks to our TWebUpdate component and in case something goes wrong, exception logging is handled by Eurekalog.

If you have any TMS bundle subscription, you can download TMS Subscription Manager v2.0 now from the "My products" page and get started with the new tool. We hope you enjoy it and it will make you more productive than with the v1.0.

We have already several ideas for further developments on TMS Subscription Manager v2.0, like making it optionally a Delphi IDE plugin with automatic notifications, allowing to invoke the installers silently, integrating the downloads of our free tools, making it possible to also manage separate product purchases, ... but we also eagerly look forward to your ideas. We're sure that with your brilliant ideas, we can make the tool even more awesome than it is today!

Bruno Fierens


Bookmarks: 

This blog post has received 6 comments. Add a comment.



Exploring parametric ODE with TMS Analytics and Physics numerical tool

Bookmarks: 

Thursday, July 13, 2017

Ordinary differential equations (ODE) used in many applications for physical, economical and other problem solution. The equations commonly describe the time evolution of some system from known initial state – initial value problem (https://en.wikipedia.org/wiki/Initial_value_problem).

The TMS Analytics and Physics pack contains the ODE solution tool of solving initial value problems for systems of ODEs. This tool is totally integrated with the symbolic capabilities of the library. This allows solving parametric problems and exploring how the parameter value influences the system behavior.

Let us consider the following simple parametric ODE:



with initial condition y(0)=1 on the time interval t=[0, 10]. The problem is parametric because there are parameters ‘A’ and ‘b’ in the equation. Our goal is exploring how the solution (function y(t)) depends on the value of ‘b’ parameter.

First we create the instance of analytical ODE object, here is the code:

var
  A, b: TVariable;
  prms: TArray<TVariable>;
  fv, equations: TArray<string>;
  ode: TAnalyticalODE;
  solver: TODESolverClass;
  y0: TArray<TFloat>;
  t: TArray<TFloat>;
  y: TArray<TArray<TFloat>>;
  i: Integer;
begin
  A:= TRealVariable.Create('A', 1.0);    // 1
  b:= TRealVariable.Create('b', 0.0);    // 2
  prms:= TArray<TVariable>.Create(A, b); // 3
  fv:= TArray<string>.Create('y');       // 4
  equations:= TArray<string>.Create('sin(t)+A*t/y^b'); // 5
  ode:= TScalarODE.Create('t', fv, equations, prms);   // 6
  ...
 
Line 1: Create the variable for ‘A’ parameter.
Line 2: Create the variable for ‘b’ parameter.
Line 3: Create array of parameters.
Line 4: Create array of function names (one name required for the problem).
Line 5: Create array of equations (one equation).
Line 6: Create the instance of analytical ODE system with specified equation and parameters.

After the instance of the analytical ODE system created we must select appropriate solver and specify initial condition for the problem. We will use the Runge-Kutta direct solver of the 4-th order. The code continued:

solver:= TRungeKutta4Solver;          // 7
y0:= TArray.Create(1.0);      // 8
And finally we must solve the initial value problem for various values of ‘b’ parameter, say b=1..8:

for i:=1 to 8 do
begin
  ode.Parameters['b'].Value:= TValue.From(i); // 9
  y:= solver.Solve(ode, y0, 10.0, 1000, t);           // 10
  
  // Code for using the result data ‘y’ and ‘t’.
end; 
Line 9: Change value of ‘b’ parameter using the array property ‘Parameters’ of the analytical ODE class. Line 10: Solving the specified initial value problem for current value of ‘b’ parameter, on the time interval t=[0, 10], with 1000 discretization steps.

The solution result for changing value of ‘b’ parameter presented on the picture below.


TMSFNCChart cross-platform / cross-framework chart displaying the result

As can be seen from the code above, there is no need creating new analytical ODE instance for exploring the parametric problem. As the analytical ODE is parametric, it is solved for the current parameter values and they can be easily changed via parametric interface.

Other advantages of using the numerical ODE tool with the symbolic calculus are:
- Minimal code writing, because there is no need to write special classes for the function method references (delegates) as in other numerical libraries.
- Convenient data representation for the developer and user as math expressions, not as programming code.
- Easily using the user input data (string data) for manipulations in programming code.
- Easily transfer input data via network as strings, easily storing and serializing the data.

The TMS Analytics and Physics pack includes the library with 5 ready-to-use numerical tools totally integrated with analytical features, such as symbolic derivatives. The trial version of TMS Analytics and Physics pack can be downloaded here. Total source code of the example application of ODE tool can be downloaded here.

Bruno Fierens


Bookmarks: 

This blog post has not received any comments yet. Add a comment.




Previous  |  Next  |  Index