Turbopower Visual PlanIt

From Lazarus wiki
Revision as of 19:16, 2 June 2017 by Swen (talk | contribs) (Printing and print preview: typo)

English (en) português (pt) русский (ru)


Visual PlanIt is a set of synchronized, data-aware components for adding time, task, & contact management capabilities to applications. Get that Outlook look & feel without the hassle.

This component was designed for cross-platform applications.




Author: Turbo Power Software
LCL Port: Christian Ulrich and Werner Pamler


Mozilla Public Licence 1.1



You can checkout the actual source from https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr/components/tvplanit

The commandline to do this is

svn co https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr/components/tvplanit

Bug reporting / Feature request

Bug reports and feature requests should be sent to the Lazarus/Free Pascal Bug Tracker; please specify the "Lazarus-CCR" project: http://bugs.freepascal.org/

Change Log

  • Feb 02, 2008 - Initial port (version 1.03)
  • Aug 01, 2016 - (Almost) complete port (version 1.04)
  • Nov 28, 2016 - Drag and drop, mORMot datastore, new fields, holiday support, designtime and runtime packages (version 1.06)

Dependencies / System Requirements

  • FPC 2.6.4 or newer
  • Lazarus 1.4.4 or newer
  • These versions were available at the time of writing this update. It is not excluded that the package can be used with older versions as well.


  • Create a directory for the components, such as lazarus\components\tvplanit
  • In this directory, unzip the files from the zip file, or execute the svn commandline from above.
  • Open lazarus
  • In the release verison 1.04 the library has designtime and runtime code in the same package. Open the package laz_visualplanit.lpk from the folder source with Package/Open file (-lpk) and click Compile. Click Use > Install if you want to install the components into the IDE.
  • Beginning with version 1.06 the library will be split into designtime and runtime packages
    • Open the runtime package laz_visualplanit.lpk from the library root folder with Package/Open package file (.lpk) and click Compile to compile it.
    • Open the designtime package laz_visualplanit_design.lpk from the same folder, click Use > Install.
  • If you need the Zeos datastore repeat with package laz_visualplanit_zeos.lpk (and laz_visualplanit_zeos_design.lpk) from folder source/addons/zeos. Make sure that the Zeos components are installed.


If you need a full documentation of the the VisualPlanIt suite get TurboPower's original 300-page pdf file from the official SourceForge site of the Delphi version (https://sourceforge.net/projects/tpvplanit/files/tpvplanit_docs/).

Using the planner components

Getting started

tvplanit tutorial.png

A simple project

Here is a quick tutorial for your first steps with the VisualPlanIt components.

  • Create a new application. Save it into its own folder.
  • Add a TPageControl with three sheets. Name them "Events", "Tasks", and "Contacts".
  • In the component palette seek for the tab Visual PlanIt.
  • Pick TVpDayView and add it to the "Events" sheet of PageControl. This is a day calendar and displays events (appointments, meetings, etc) for the entire day with a resolution as defined by its so-called Granularity.
    • If you are used to times in the 24-hour format switch TimeFormat to tf24Hours.
    • If the calendar is sufficiently wide you may want to change NumDays to - say - 2 to see two days at once.
    • Give the components a more modern look by setting DrawingStyle to dsFlat.
    • Similarly you can add a TVpWeekView (a week calendar) and/or a TVpMonthView (a month calendar) to the "Events" sheet. They give an overview of the same events, but with less resolution. Text ellipsis ("...") are shown if the event text cannot be fully displayed.
  • Now add a TVpTaskList to the "Tasks" sheet of the PageControl. It is a listing of to-do items along with their due dates. Overdue tasks are written in red. Completed tasks are striked out. Note that DisplayOptions.ShowCompleted or .ShowAll must be checked in order to see completed tasks.
  • Finally add a TVpContactGrid to sheet "Contacts" of the PageControl.
  • Again, you may want to use DrawingStyle dsFlat for a more modern look.
  • Play with the properties to setup all these visual controls according to your preferences. The TVpWeekView, for example, has a property to define whether the week starts on Monday or Sunday (WeekStartsOn).
  • Two ingredient are missing: the DataStore and the ControlLink.
    • The Datastore is a component which stores the data to be displayed in the visual controls. The Visual PlanIt package contains a series of predefined datastores - see below. We select here a TVpIniDatastore or TVpXmlDatastore which store the data in an ini or xml file - these stores do not require a database like the other datastores.
    • In the property Filename, enter a name for the datastore file, e.g. data.ini or data.xml, respectively. Using a relative filename here means that the path will be relative to the location of the exe file of the program which is convenient for this tutorial. In a "real" application, however, an absolute path may be preferrable. And it may also be advantageous to enter the filename at runtime, e.g. in the FormCreate event handler.
    • If the filename is known at designtime you can set AutoConnect to true in order to open the datastore automatically when the program starts. If the filename is specified at runtime leave AutoConnect at false and set the datastore's Connected property to true.
    • The ControlLink automatically establishes a link between the datastore and the visual controls and makes sure that the controls get their data if needed and are synchronized.
  • Now it's time to run the program
  • How to add data? This is done by double-clicking on any of the controls that we added to open a specific built-in editor for convenient entering of the data needed.
  • At the first time, however, a dialog pops up saying that "no resources have been defined". A resource is everything which can be administrated by the VisualPlanIt tools, such as an employee, a meeting room, a library of books, etc. Enter the name of the resource. If your program will deal with various resources you can add a TVpResourceCombobox to select the resource needed for the program run. Make sure to use unique resource names because VisualPlanIt will throw a duplicate-resource exception otherwise.
  • When you restart the program the next time you will notice that the data are no longer visible. No reason to be alarmed - the data are still there, but the program just does not know which resource to open. Enter this code in the FormCreate event, after connecting to the datastore:
procedure TForm1.FormCreate(Sender: TObject);
  // Use this code if the filename is not set in the Object Inspector...
  VpXmlDatastore1.FileName := name_of_the_datastore_file;
  // ... and the datastore is not autoconnected.
  VpXmlDatastore1.Connected := true;
  // This code selects the first resource (index 0) found in the datastore.
  if VpXmlDatastore1.Resources.Count > 0 then
    VpXmlDatastore1.Resource := VpXmlDatastore1.Resources.Items[0];  

Event categories

tvplanit eventeditor.png

The event editor is used to enter or edit event details. You'll find here a combobox labeled "Category". The combobox items can be used to classify the events, like "Business", "Private", "Birthday" etc. The items, however, only have generic names, such as "Category 1", "Category 2", etc. You can select more descriptive names by visiting the datastore property CategoryColorMap. The field "Descriptions" defines the text to be displayed in the combobox. In order to be able to distinguish the categories in the DayView control you can also set up a background color and a bitmap here.

Playing an event sound

The planner components are prepared to play a sound some pre-defined time ahead of the occurence of an event. For this to happen the "Reminder" checkbox must be checked in the event editor.

There are several ways to set up the sound:

  • The datastore exposes a property DefaultSound. The sound file specified here will be played whenever an event with checked "Reminder" box happens.
  • Additionally, an individual sound file can be selected for each particular event by clicking at the loudspeaker icon next to the reminder interval.

In Windows, the sounds are played automatically without further code because there universal sound utilities are embedded. In Linux, however, this is less standardized. But the datastore provides an event OnPlaySound where the correct sound playing command can be executed. The fulldemo project in the examples folder contains a unit which checks for the sound engines typically available in various systems; this unit is an adapted version of the playsound component by Gordon Bamber in the Lazarus components and code repository (https://sourceforge.net/p/lazarus-ccr/svn/HEAD/tree/components/playsoundpackage/).


Datastores are responsible for persistent storage of event, task and contact data records.

The ancestor of this hierachy of classes is TVpCustomDatastore. It implements the basic functionality and provides fundamental abstract methods, such as LoadEvents, LoadTasks, LoadContacts, PostResources, PostEvents, PostTasks, PostContacts. Its member class Resources (type: TVpResources) stores all resources in a list as TVpResource items. Such a resource item, in turn, contains other lists: Schedule, Tasks, and Contacts for all event, task and contact records. The currently selected resource can be accessed by the datastore's Resource or ResourceID properties (the latter is a unique numerical ID to identify the resource).

TVpCustomDBDatastore inherited directly from TVpCustomDatastore. It is another (pseudo-) abstract class which provides the basic database functionality by means of four datasets, ResourceTable, EventsTable, TasksTable, and ContactsTable. Since datebases have very efficient methods of searching and filterung these datastores provide a property DayBuffer which defines a date range before and after the currently selected date for which records are loaded.


This is a simple file datastore which inherits from TVpCustomDatastore. It stores the data records in a simple ini file structure. The name of the ini file must be specified in the corresponding property. The file is loaded after the datastore has been created if the design-time property AutoConnect is true, or when the run-tim property Connected is switched to true. The file is saved automatically when Connected goes back to false - this happens before the datstore is destroyed.

The demo project examples/datastores/ini is an example how the ini datastore can be used.


This is another simple file datastore. It works similarly as the ini datastore except that the file is an xml file now. The datastore's tree of xml nodes can be inserted into any existing xml file, e.g. files written by TXMLDataStorage. For this purpose, the node must be specified to which the datastore's nodes will be attached (property ParentNode).

Have a look at the demo project in examples/datastores/xml to see the xml datastore at work.


The following datastores inherit from TVpCustomDBDatastore. The first one, TBufDSDataset, uses simple TBufDataset tables for storage of the planner data. The four required files are named "Resources.db", "Events.db", "Contacts.db" and "Tasks.db", and are stored in the folder specified by the property Directory. If AutoCreate is true then the tables are created automatically when the program runs for the first time; otherwise the datastore method CreateTables must be called.

Application of this datastore is demonstrated in examples/datastores/bufdataset and in examples/fulldemo.


This datastore is a specialized storage for SQLite3 tables. It uses SQLDB components for this purpose. You must add a TSQLite3Connection and a TSQLTransaction to the form, link them together using the corresponding properties. Link the SQLite3Connection to the Connection of the datastore. The SQLQueries required are created automatically if the datastore's AutoCreate is true or after CreateTables is called. The database is stored in the file specified by the connection's DatabaseName.

The project in examples/datastores/sqlite3 demonstrates how the sqlite3 datastore can be used.


A Firebird database provides the storage for TVpFirebirdDatastore. Again, SQLDB components are used here. To establish a connection to the database, a TIBConnection must be linked to the datastore's Connection. It must provide all information to connect to the database, such as database name, user name and password. In addition, a TSQlTransaction component is needed. The database should be created by the tools provided by Firebird or by third-party database administration tools. It is possible to do this also from the datastore, but this results in an exception. If the datastore's AutoCreate the required tables are created automatically when not found; alternatively call CreateTables for the datastore.

Usage of the datastore is demonstrated in examples/datastores/fb.


TvPlanit FieldMapping.png

The TVpZeosDatastore works with the ZEOS database components. Since they are not contained in the standard Lazarus distribution it is contained in a separate package, laz_visualplanit_zeos, which is found in the source/addons/zeos folder and must be installed after laz_visualplanit.

A TZConnection is required to establishe a connection to the database. The tables are created internally, either automatically if AutoCreate is true, or manually by calling CreateTable.

The demo project can be found in examples/datastores/zeos.


In the database-aware datastores mentioned so far, the tables are created by the datastore. This makes sure that the fields are named in the way as expected by the datastore. If, on the other hand, tables are already existing or are provided by other applications it is very likely that field names will not be reckognized. TVpFlexDatastore can be a solution. Its name indicates that this is a very flexible datastore. In particular, it is possible to link to any database system if a TDataset-descendent is available.

You must add four TDataset components to the form, each one corresponding to one of the Resources, Events, Contacts, and Tasks data, and link them to the DataSsource of the datastore via TDataSource components. Then double-click on the TvVpFlexDatastore to open the FieldMapper. This is a tool to assign the database fields to the internal fields of the datastore. For each database field that you want to include in the planner select the corresponding datastore field in the right list box. After clicking "Add" the pair of fields is shown in the "Field Mappings" listbox.

There are two sample projects

  • examples/datastores/flex/access demonstrates how an MS Access database can serve for storage using an ODBCConnection and other SQLDB components (there is also a readme.txt with step-by-step instructions).
  • examples/datastores/flex/sqlite3 repeats the same with a SQLite3 database.

Other datastores

The following datastores from the original Delphi distribution are included in the source folder, but not added to the package because they require the BDE which is not available for Lazarus:

  • TVpBDEDatastore for database access by means of the Borland Database Engine (BDE) (unit vpbdeds)
  • TVpAdvDatastore for Advantage Database (unit vpadvds)
  • TVpFF2Datastore for FlashFiler 2 databases (unit vpff2ds)
  • TVpDBISAMDatastore for DBISAM database access (unit vpdbisamds)
  • TVpSQLDatastore (unit vpsqlds): This is a very general datastore for any sql database. An interfaced class to the TDataset-descendent must be provided, and there must be a class specifying the particular sql dialect. For application in Lazarus, some restructuring of BDE-related properties will be required. The package contains an example for BDE access.

Overlaying events

The DayView and WeekView components primarily display events of a single resource. It is possible, however, to switch into an overlay mode where other resources can be displayed within the same controls. This can be achieved by assigning a TVResourceGroup to the resource (property Group):

  TVpOverlayPattern = (opSolid, opClear, opHorizontal, opVertical, opFDiagonal, opBDiagonal, opCross, opDiagCross);

  TVpOverlayDetail = (odResource, odEventDescription, odEventCategory);
  TVpOverlayDetails = set of TVpOverlayDetail;  

  TVpResourceGroup = class
    property Caption: String;
    property Count: Integer;
    property Items[AIndex: Integer]: TVpResource;
    property Pattern: TVpOverlayPattern;
    property ResourceID: Integer;
    property ReadOnly: boolean read FReadOnly;
    property ShowDetails: TVpOverlayDetails;

procedure TMainForm.CreateResourceGroup;
  NAME_OF_GROUP = '';  // empty --> use resource descriptions instead
  PARENT_ID = 1;
  datastore: TVpCustomDatastore;
  grp: TVpResourceGroup;
  datastore := VpControlLink1.Datastore;
  grp := datastore.Resources.AddResourceGroup([PARENT_ID, OVERLAYED_ID], NAME_OF_GROUP);
  grp.ReadOnly := true;
  grp.Pattern := opDiagCross;
  if datastore.Resource <> nil then
    datastore.Resource.Group := grp else
    datastore.Resource.Group := nil;
  datastore.RefreshEvents;  // or: datastore.UpdateGroupEvents;

The IDs of the overlayed resources are specified as an array in the first parameter of the call to AddResourceGroup. The first id plays a special role: it refers to the resource to which the group is attached. If this resource is displayed in a Dayview or WeekView component then the events of the other specified ID(s) are overlayed within the same control.

The level of detail visible to the user seeing overlayed events is controlled by the property ShowDetails of the resource group. By default, only the name of the overlayed resource is visible. If more details are to be exposed you can add the other elements of TVpOverlayDetails. The background of overlayed events in the dayview is hatched as specified by the Pattern property of the resource group if the event category is not excluded from the visible details; otherwise the event is drawn as specified by the property HiddenCategories of the Datastore.

Editing, deleting, drag-and-drop of overlayed events is off by default, but can be allowed by setting the ReadOnly property of their resource group to false.

In order to turn resource groups on and off the context menu of DayView and WeekView components is extended by a corresponding submenu. The submenu contains an item "none" meaning "no overlayed events" as well as an item for each resource group in which the currently selected resource is the parent. The caption of the menu items is defined by the (optional) second parameter of the AddResourceGroup call (NAME_OF_GROUP); if empty the group name is derived from the descriptions of the overlayed resources.

Printing and print preview

tvplanit printformatdesigner.png

The VisualPlanIt package contains routines for printing the planner controls. Even a print preview is implemented. The printing process is defined by means of templates which are called "print formats" here. They can be created at designtime or by means of an xml file loaded at runtime, contain a list of the components to be printed.

The heart of printing support is the TVpPrinter class - it is accessible by the Printer property of the TVpControlLink. It contains extra information needed for the printing process and contains a list of the available PrintFormats.

In order to quickly access the print format designer double-click on the TVpControlLink component. Click on the upper "New" button to open the basic format editor. Here you can assign a reasonable name to the print format. Clicking on the lower "Edit" opens the "Element" editor - this is the tool to define the contents on the print print format, similar to a report designer, however less comfortable. In addition to the planner controls, DayView, WeekView, MonthView, TaskList and ContactGrid, the editor allows also to add additional text and shape objects to the format. Multiple elements can be contained within the same format. Position the elements by using the Top/Left/Width/Height specifications at the right. In addition, the entire format page can be rotated in 90° steps.

A print preview can be generated by means of a TVpPrintPreview component. Assign the ControlLink of the form to the ControlLink and the Printer of the Printers units to the Printer property of the preview component. For printing to work correctly, you must have the package Printer4Lazarus in the requirements of the project; this can be done most easily by adding a standard TPrintDialog to the form which you will probably need anyway. Open the print preview by calling its Execute method. It should be mentioned that the print preview itself does not issue any printing commands. Therefore, extra printing code must be written if the user decides to initiate a print-out from the preview, something like this:

if VpPrintPreviewDialog1.Execute then
  if PrintDialog1.Execute then begin

See the fulldemo project in the examples folder for a worked-out example.


All internal strings used by the VisualPlanIt package can be localized by means of the translation utilities available within Lazarus. The translated po files can be found in the folder languages of the distribution. Copy them to the language folder of your application, and translate them by calling

  langdir: String;  // language folder of your application 
  lang: String;     // language abbreviation, e.g. "de" for German
  TranslateUnitResourceStrings('vpsr', langdir + 'vpsr.' + lang + 'po');

Note: Users are cordially invited to submit translations of the resource strings to their native language

In addition to providing translated strings a variety of date/time related properties of the planner controls should be adapted:

  • Set VpDateView.DateLabelFormat to DefaultFormatSettings.LongDateFormat, dto. with VpWeekView.DayHeadAttributes.DateFormat and VpWeekView.DateLabelFormat.
  • Set VpMonthView.DatelabelFormat to the string 'mmmm yyyy' which means "month in words + year".
  • Set VpTaskView.DisplayOptions.DueDateFormat to DefaultFormatSettings.ShortDateformat.
  • Determine the TVpTimeFormat of your system by calling GetTimeFormat (in Unit vpmisc). The result is either tf12Hour or tf24Hour and should be assigned to the TimeFormat properties of VpDayView, VpWeekView and VpMonthView.
  • Set the properties WeekStartsOn of VpMonthView and VpWeekView to the day code of the first day of a week (1 = Sunday, ..., 7 = Saturday).

Finally, the TVpControlLink implements procedures for localizing addresses in the Contact Editor Dialog. For this purpose, the file vplocalize.xml accompanies the VisualPlanIt package. It contains rules for construction of addresses in the correct format varying from country to country. If this filename is assigned to the property LocalizationFile of the ControlLink then these rule are effective when the Contact Editor Dialog is created. Please note that this file is not translated by the po files.

Using the navigation bar


TVpNavBar, seen in the left of this screenshot of the navbar demo, is a navigation tool smiliar to the one known from Outlook. It consists of several folders represented by button-like controls and several items - these are the labelled icons in the large space between two buttons. The folder button - which can be drawn in several button- or tab-like styles - is always shown above the associated item area. Clicking on a folder divides the stack of folders in an upper and lower part, and displays the items assigned to this folder between the corresponding folder at the top and the next folder at the bottom. The index of the currently expanded folder is given by the property ActiveFolder, and the index of the clicked items within this folder is given by property ActiveItem. An event OnItemClick fires when an item is clicked, it has the index of the clicked item as a parameter.

Populating a TNavBar at designtime is a bit complicated. In the original version of VisualPlainIt there exists a component editor, but this does not work and was not ported/adapted to Lazarus so far. Therefore, it is best to learn this task by means of the object inspector:

  • Add a TVpNavBar component to the form.
  • Add an imagelist with, ideally 32x32 images, and assign it to the Images property of the NavBar.
  • Click on the "..." button next to FolderCollection to open the collection editor for the folders.
  • Click "Add" to add a new folder.
  • Select the new folder in the collection editor, its properties appear in the object inspector.
  • Specify the Caption of the folder - this is the text to appear on the button/tab assigned to the folder.
  • Leave IconSize at isLarge if you want to use large icons for this folder's items. In this case, icons and their captions will be centered, the caption will be below the icon and word-wrapped if the text is longer than the width of the NavBar. If you select isSmall, on the other hand, icons and captions are left aligned, and the (non-wrapped) captions are drawn at the right of the icons. If the image size is larger than 16x16 pixels, images will be scaled down to this size. IconSize can change from folder to folder. If you plan to use both small and large images you should ideally add a second ImageList with 16x16 images to the form and switch ImageLists in the OnfolderChanged event.
  • Do not set the FolderType to ftContainer - this feature of adding other controls to the folder is not working at the time of this writing in Lazarus.
  • In order to add icons to the folder click on ItemCollection. This opens the collection editor fot the items belonging to the current folder.
  • Again click "Add" to create a new item, and select it in the collection editor to show its properties in the object inspector.
  • Caption is the text assigned to the item.
  • IconIndex identifies the icon to be drawn for this item. It is the index in the ImageList assigned to the NavBar's Images.



In addition to the planner components the Visual PlanIt package contains also two stand-alone gadgets:


This is a 14-segment LED display which can display any ASCII string. The string is defined by means of the property Caption, but the count of LED characters must be defined explicitly using the property Columns


This is a digital or analog clock - depending on the property DisplayMode. A variety of settings can be adjusted for each mode separately by using the properties in AnalogOptions and DigitalOptions. The properties are pretty much self-explanatory, except maybe the DigitalOptions.MilitaryTime which activates the 24-hour display if true, or the 12-hour am/pm mode if false. The AnalogOptions.ClockFace replaces the default-drawn clock face by a bitmap - see screenshot above.

With the property ClockMode the operation of the clock can be changed from standard clock (count-up or count-down timer, cmClock, cmTimer, cmCountdownTimer, respectively).