Wednesday, June 22, 2016

It's almost three months since we released the first version of the TMS FNC UI Pack, a set of Framework Neutral Components (FNC), and have meanwhile released 2 major updates which include the TTMSFNCTabSet/TTMSFNCPageControl (v1.1), the recently introduced TTMSFNCListBox/TTMSFNCCheckedListBox and significant improvements / new features to the TTMSFNCTreeView such as filtering, sorting, keyboard lookup, clipboard support, ... (v1.2).

As already explained in previous blog posts (http://www.tmssoftware.com/site/blog.asp?post=335 andhttp://tmssoftware.com/site/blog.asp?post=346), the TMS FNC UI Pack is a set of UI controls that can be used from VCL Windows applications, FireMonkey (FMX) Windows, Mac OS-X, iOS, Android applications and LCL framework based Lazarus applications for Windows, Linux, Mac OS-X, ... . The TMS FNC UI Pack contains highly complex & feature-rich components such as grid, planner, rich editor, treeview, toolbars. So, with a single set of controls, you have the freedom of choice to use Delphi, C++Builder or the free Lazarus to create applications for a myriad of operating systems, you have a single learning curve to these components and as demonstrated here, you can use a single source to create apps for multiple targets.

This blog post will cover the TTMSFNCCheckedListBox, which is one of the new components that are added in the latest release (v1.2) of the TMS FNC UI Pack, show how to use myCloudData.net to store data and demonstrate how easy it is to switch between FMX, VCL and LCL with one shared source code. myCloudData is an easy to use & flexible service to make use of structured storage in the cloud from Windows, web, mobile or IoT apps and is offered by tmssoftware.com. myCloudData is OAUTH/JSON REST based and our TMS Cloud Pack includes a component to access the service and thus your data seamlessly.

Click image for more screenshots.

A single shared source

As with our TV-guide sample we have created a single shared source file that is used in a FMX, VCL and LCL project. The unit starts by defining the business logic class that will be instantiated in our application main form unit.

  1. TTODOListLogic = class
  2. private
  3. FTable: TMyCloudDataTable;
  4. FListBox: TTMSFNCCheckedListBox;
  5. FMyCloudDataAccess: TMyCloudDataAccess;
  6. FOnConnected: TNotifyEvent;
  7. FBitmapContainer: TTMSFNCBitmapContainer;
  8. protected
  9. procedure DoConnected(Sender: TObject);
  10. public
  11. destructor Destroy; override;
  12. procedure InitListBox(AListBox: TTMSFNCCheckedListBox);
  13. procedure InitMyCloudData;
  14. procedure Refresh;
  15. procedure InitializeTable;
  16. procedure AddNewItem(AText: string; ADate: TDateTime; APriority: TPriority);
  17. procedure DeleteItem;
  18. procedure Connect;
  19. procedure DoBeforeDrawItem(Sender: TObject; AGraphics: TTMSFNCGraphics; ARect: TRectF; AItem: TTMSFNCListBoxItem; var AAllow: Boolean; var ADefaultDraw: Boolean);
  20. procedure DoItemCheckChanged(Sender: TObject; AItem: TTMSFNCCheckedListBoxItem);
  21. procedure DoItemCompare(Sender: TObject; Item1, Item2: TTMSFNCListBoxItem; var ACompareResult: Integer);
  22. property OnConnected: TNotifyEvent read FOnConnected write FOnConnected;
  23. property BitmapContainer: TTMSFNCBitmapContainer read FBitmapContainer write FBitmapContainer;
  24. end;

Each framework has its own set of units in order to compile succesfully. We use the conditional defines added to our project to make the difference between each framework.

  1. uses
  2. Classes, SysUtils, DB
  3. {$IFDEF VCL}
  4. ,VCL.TMSFNCListBox, VCL.TMSFNCCheckedListBox, CloudMyCloudData, CloudBase, VCL.TMSFNCUtils,
  5. CloudCustomMyCloudData, VCL.TMSFNCGraphics, VCL.Dialogs, VCL.TMSFNCTypes, Types, VCL.TMSFNCBitmapContainer;
  6. {$ENDIF}
  7. {$IFDEF FMX}
  8. ,FMX.TMSFNCListBox, FMX.TMSFNCCheckedListBox, FMX.TMSCloudMyCloudData, FMX.TMSCloudBase,
  9. FMX.TMSFNCUtils, FMX.TMSCloudCustomMyCloudData, FMX.TMSFNCGraphics, FMX.TMSFNCTypes, FMX.Dialogs, Types, FMX.TMSFNCBitmapContainer;
  10. {$ENDIF}
  11. {$IFDEF LCL}
  12. ,LCLTMSFNCListBox, LCLTMSFNCCheckedListBox, LCLTMSCloudMyCloudData, LCLTMSCloudBase,
  13. LCLTMSFNCUtils, LCLTMSCloudCustomMyCloudData, LCLTMSFNCGraphics, Dialogs, LCLTMSFNCTypes, LCLTMSFNCBitmapContainer;
  14. {$ENDIF}

myCloudData

As our todolist is storing its todo items in the cloud we take advantage of our own service, that can virtually store anything we want. The initialization is done programmatically.

  1. procedure TTODOListLogic.InitMyCloudData;
  2. begin
  3. FMyCloudDataAccess := TMyCloudDataAccess.Create(nil);
  4. FMyCloudDataAccess.PersistTokens.Location := plIniFile;
  5. {$IFDEF FMX}
  6. FMyCloudDataAccess.PersistTokens.Key := TTMSFNCUtils.GetDocumentsPath + PthDel + 'myclouddatafmx.ini';
  7. FMyCloudDataAccess.OnConnected := DoConnected;
  8. {$ENDIF}
  9. {$IFDEF VCL}
  10. FMyCloudDataAccess.PersistTokens.Key := TTMSFNCUtils.GetDocumentsPath + PthDel + 'myclouddatavcl.ini';
  11. FMyCloudDataAccess.OnConnected := DoConnected;
  12. {$ENDIF}
  13. {$IFDEF LCL}
  14. FMyCloudDataAccess.PersistTokens.Key := TTMSFNCUtils.GetDocumentsPath + PthDel + 'myclouddatalcl.ini';
  15. FMyCloudDataAccess.OnConnected := @DoConnected;
  16. {$ENDIF}
  17. FMyCloudDataAccess.PersistTokens.Section := 'tokens';
  18. FMyCloudDataAccess.App.Key := MYCLOUDDATAKEY;
  19. FMyCloudDataAccess.App.Secret := MYCLOUDDATASECRET;
  20. FMyCloudDataAccess.App.CallBackPort := 8888;
  21. FMyCloudDataAccess.App.CallBackURL := 'http://127.0.0.1:8888';
  22. end;

You might notice 3 things here. First is the TMyCloudDataAccess class which is common between FMX, VCL and LCL. This is defined earlier in our business logic as the unit names are different for FMX, VCL and LCL.

  1. type
  2. {$IFDEF VCL}
  3. TMyCloudDataAccess = class(TAdvMyCloudData);
  4. {$ENDIF}
  5. {$IFDEF FMX}
  6. TMyCloudDataAccess = class(TTMSFMXCloudMyCloudData);
  7. {$ENDIF}
  8. {$IFDEF LCL}
  9. TMyCloudDataAccess = class(TTMSLCLCloudMyCloudData);
  10. {$ENDIF}

Second, is the event handler assignment, that we also need to wrap with conditional defines because LCL works with an additional @. Third is the ini file that is also created with a framework suffix, as the token and token encryption are unique per application and not shareable. After defining our business logic, it's time to setup our GUI. The form unit is shared between FMX, VCL and LCL and there you will also notice the uses list and the form file is separated with defines. After designing our form (using the TTMSFNCCheckedListBox, some tool bar buttons (TTMSFNCToolBarButton) we are ready to connect to our business logic and create a working todo list that stores its items in the cloud.

  1. procedure TTODOListForm.DoConnected(Sender: TObject);
  2. begin
  3. Panel1.Enabled := True;
  4. Panel2.Enabled := True;
  5. TMSFNCToolBarButton2.Enabled := False;
  6. TMSFNCCheckedListBox1.Enabled := True;
  7. TMSFNCToolBarButton4.Enabled := True;
  8. TMSFNCToolBarButton5.Enabled := True;
  9. TMSFNCToolBarButton6.Enabled := True;
  10. TMSFNCToolBarItemPicker1.Enabled := True;
  11. FTODOListLogic.InitializeTable;
  12. FTODOListLogic.Refresh;
  13. end;
  14. procedure TTODOListForm.FormCreate(Sender: TObject);
  15. begin
  16. FTODOListLogic := TTODOListLogic.Create;
  17. FTODOListLogic.InitListBox(TMSFNCCheckedListBox1);
  18. FTODOListLogic.InitMyCloudData;
  19. {$IFDEF LCL}
  20. FTODOListLogic.OnConnected := @DoConnected;
  21. {$ELSE}
  22. FTODOListLogic.OnConnected := DoConnected;
  23. {$ENDIF}
  24. TMSFNCCheckedListBox1.BitmapContainer := TMSFNCBitmapContainer1;
  25. TMSFNCToolBarItemPicker1.BitmapContainer := TMSFNCBitmapContainer1;
  26. TMSFNCToolBarItemPicker1.Bitmaps.Clear;
  27. TMSFNCToolBarItemPicker1.Bitmaps.AddBitmapName('low');
  28. TMSFNCToolBarItemPicker1.DisabledBitmaps.Assign(TMSFNCToolBarItemPicker1.Bitmaps);
  29. TMSFNCToolBarButton2.DisabledBitmaps.Assign(TMSFNCToolBarButton2.Bitmaps);
  30. TMSFNCToolBarButton4.DisabledBitmaps.Assign(TMSFNCToolBarButton4.Bitmaps);
  31. TMSFNCToolBarButton5.DisabledBitmaps.Assign(TMSFNCToolBarButton5.Bitmaps);
  32. TMSFNCToolBarButton6.DisabledBitmaps.Assign(TMSFNCToolBarButton6.Bitmaps);
  33. dt := TMyDateTimePicker.Create(Self);
  34. {$IFDEF FMX}
  35. dt.Position.X := 5;
  36. dt.Position.Y := 40;
  37. {$ELSE}
  38. dt.Left := 5;
  39. dt.Top := 40;
  40. {$ENDIF}
  41. dt.Date := Now;
  42. dt.Parent := Panel1;
  43. dt.Width := 105;
  44. end;
  45. procedure TTODOListForm.FormDestroy(Sender: TObject);
  46. begin
  47. FTODOListLogic.Free;
  48. end;
  49. procedure TTODOListForm.TMSFNCCheckedListBox1ItemSelected(Sender: TObject;
  50. AItem: TTMSFNCListBoxItem);
  51. begin
  52. TMSFNCToolBarButton6.Enabled := True;
  53. end;
  54. procedure TTODOListForm.TMSFNCToolBarButton1Click(Sender: TObject);
  55. begin
  56. FTODOListLogic.Refresh;
  57. end;
  58. procedure TTODOListForm.TMSFNCToolBarButton2Click(Sender: TObject);
  59. begin
  60. FTODOListLogic.Connect;
  61. end;
  62. procedure TTODOListForm.TMSFNCToolBarButton3Click(Sender: TObject);
  63. begin
  64. FTODOListLogic.DeleteItem;
  65. end;
  66. procedure TTODOListForm.TMSFNCToolBarButton4Click(Sender: TObject);
  67. begin
  68. FTODOListLogic.AddNewItem(Edit1.Text, dt.Date, TPriority(TMSFNCToolBarItemPicker1.SelectedItemIndex));
  69. end;
  70. procedure TTODOListForm.TMSFNCToolBarItemPicker1ItemSelected(Sender: TObject;
  71. AItemIndex: Integer);
  72. begin
  73. TMSFNCToolBarItemPicker1.Bitmaps.Clear;
  74. TMSFNCToolBarItemPicker1.Bitmaps.AddBitmapName(TMSFNCBitmapContainer1.Items[AItemIndex].Name);
  75. TMSFNCToolBarItemPicker1.DisabledBitmaps.Assign(TMSFNCToolBarItemPicker1.Bitmaps);
  76. end;

When starting the application, and clicking the connect button, our business logic unit will do the work. It will create a table in myCloudData, send a notification to our GUI, which will then allow to add items to our listbox, refresh or delete existing items, and this is done with one source code, available on multiple frameworks, multiple platforms.

The full source code is available for download

Click image for more screenshots.

Pieter Scheldeman

http://www.tmssoftware.com/site/blog.asp?post=353

TMS X-Cloud Todolist with FNC的更多相关文章

  1. Everything starts with a dream(A day has only 24 hours and these things take time,所以要抓紧)

    There is the famous quote: "Everything starts with a dream" and many years ago, Michael Va ...

  2. Developing your first FNC custom control

    Friday, May 13, 2016 Some weeks ago, we released the TMS FNC UI Pack, a set of Framework Neutral Com ...

  3. 【Spring Cloud & Alibaba 实战 | 总结篇】Spring Cloud Gateway + Spring Security OAuth2 + JWT 实现微服务统一认证授权和鉴权

    一. 前言 hi,大家好~ 好久没更文了,期间主要致力于项目的功能升级和问题修复中,经过一年时间的打磨,[有来]终于迎来v2.0版本,相较于v1.x版本主要完善了OAuth2认证授权.鉴权的逻辑,结合 ...

  4. On cloud, be cloud native

    本来不想起一个英文名,但是想来想去都没能想出一个简洁地表述该意思的中文释义,所以就用了一个英文名称,望见谅. Cloud Native是一个刚刚由VMware所提出一年左右的名词.其表示在设计并实现一 ...

  5. 在公有云AZURE上部署私有云AZUREPACK以及WEBSITE CLOUD(六)

    (六)在Website Cloud中添加site 1新建Website,并打开 使用前面创建的用户 newbee@waplab.com 登录租户Portal,新建一个website 新建完成后, 可以 ...

  6. 在公有云AZURE上部署私有云AZUREPACK以及WEBSITE CLOUD(五)

    (五)注册Website Cloud 1 注册Website Cloud 添加Website Cloud   连接Website Cloud 注意, endpoint 是使用Management Se ...

  7. 在公有云AZURE上部署私有云AZUREPACK以及WEBSITE CLOUD(四)

    (四)搭建Website Cloud环境 1安装CONTROLLER主机 在开始安装Web site Cloud之前,读者应该对该服务的拓扑结构有个大概了解. 如图: Controller是非常重要的 ...

  8. 在公有云AZURE上部署私有云AZUREPACK以及WEBSITE CLOUD(二)

    前言 (二)建立虚拟网络环境,以及域控和DNS服务器   1搭建虚拟网络环境 在Azure上创建虚拟网络.本例选择的是东南亚数据中心.后面在创建虚机的时候,也选择这个数据中心. VNet Name: ...

  9. spring/spring boot/spring cloud开发总结

    背景        针对RPC远程调用,都在使用dubbo.dubbox等,我们也是如此.由于社区暂停维护.应对未来发展,我们准备尝试新技术(或许这时候也不算什么新技术了吧),选择使用了spring ...

随机推荐

  1. JAVA Stop The World 第八节

    JAVA Stop The World 第八节 小伙伴还记得上一篇中我们留下的一个问题吗?什么是停顿类型!经过上几章的学习,我们知道垃圾回收首先是要经过标记的.对象被标记后就会根据不同的区域采用不同的 ...

  2. 斐波那契数列 的两种实现方式(Java)

    import java.util.Scanner; /* 斐波那契数列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ... 如果设F(n)为该数列的第n ...

  3. Can't load IA 32-bit .dll on a AMD 64-bit platform

    在myeclipse中使用的,tomcat异常:java.lang.UnsatisfiedLinkError: D:\JAVA\ApacheTomcat\bin\tcnative-1.dll: Can ...

  4. Oracle学习之Oracle 树操作(select…start with…connect by…prior)

    转自:http://www.cnblogs.com/linjiqin/archive/2013/06/24/3152674.html oracle树查询的最重要的就是select…start with ...

  5. jQuery 源码分析和使用心得 - 文档遍历 ( traversing.js )

    jQuery之所以这么好用, 首先一点就是$()方法和它强大的选择器. 其中选择器使用的是sizzle引擎, sizzle是jQuery的子项目, 提供高效的选择器查询. 有个好消息告诉大家, 就是s ...

  6. CSS Hack代码与浏览兼容总结

    关于CSS Hack的东西能少尽量少吧.发现这篇文章我写得太复杂了,所以重新精简了一下,把代码粘贴到jsfiddle上,方面修改代码和维护. 1, IE条件注释法,微软官方推荐的hack方式. 只在I ...

  7. 初识JavaScript,感觉整个人都不好了。。。

    学习web前端的开发已经将近一个月了,开发中的三个大兄弟——“html”.“css”.“JavaScript”,小哥我已经深入接触了前两位,并与他俩建立的深厚的友谊.在编写过程中,不能说达到各位大神的 ...

  8. 02-4. BCD解密(10)

    BCD数是用一个字节来表达两位十进制的数,每四个比特表示一位.所以如果一个BCD数的十六进制是0x12,它表达的就是十进制的12.但是小明没学过BCD,把所有的BCD数都当作二进制数转换成十进制输出了 ...

  9. jQuery.fn和jQuery.prototype jquery.extend() jquery.fn.extend()区别介绍

    这里的 jQuery , jQuery.fn , jQuery,fn,init ,jQuery,prototype 都代表什么. 来看下jQuery的源码是怎么样定义的: (function( win ...

  10. cdoj 847 方老师与栈 火车进出战问题

    //其实我是不想写这题的,但是这题让我想起了我年轻的时候 解法:直接模拟栈就好. //另外我年轻时候做的那题数据范围比较小,原理也不一样. //对于序列中的任何一个数其后面所有比它小的数应该是倒序的, ...