Recent

Author Topic: TDateTimePicker - Make the date/time separator configurable  (Read 534 times)

AlexanderT

  • New Member
  • *
  • Posts: 34
Hello,

Is it possible to remove the extra spacing between the date and time in TDateTimePicker, or perhaps add an option to configure the date/time separator as a string?

I only need a single space between the date and time. Currently, I have to include and maintain the entire module just to change this behavior.

Would it be possible to make this configurable?

Is there a way to request this change from the author? If so, where would be the best place to do that?
« Last Edit: July 11, 2026, 10:42:04 am by AlexanderT »

wp

  • Hero Member
  • *****
  • Posts: 13649
Re: TDateTimePicker - Make the date/time separator configurable
« Reply #1 on: July 11, 2026, 12:55:06 pm »
As far as I understand this control, the extra space is not due to added space characters but due to the calculation of the position of the date/time parts. All these are separate strings in order to achieve the special click behaviour for this control. If you want to bring the time closer to the date you must dive deeply into the code of this control to understand the positioning of the parts.

I don't know whether the original author of TDateTimePicker is still around here. But the component has been included in the LCL and, thus, is maintained by the Lazarus team. Please report your request in the bug tracker (https://gitlab.com/freepascal.org/lazarus/lazarus/-/work_items).

What is the reason why you want the space between date and time to be reduced? Just optical reasons? It is my feeling that you'll need good arguments to convince the developers to change the controls just for this reason.

AlexanderT

  • New Member
  • *
  • Posts: 34
Re: TDateTimePicker - Make the date/time separator configurable
« Reply #2 on: July 11, 2026, 04:23:28 pm »
I had a look at the implementation, and the extra gap is actually not caused by additional space characters. It comes from this code:

Code: Pascal  [Select][+][-]
  1. if FTimeWidth > 0 then
  2.   R.Right := R.Right + 2 * FDigitWidth;

where FDigitWidth is calculated as the maximum width of the characters 0 through 9 in the current font. So the separator width is effectively hardcoded to twice the width of the widest digit.

In my local copy, I simply changed this to use the width of a single space, and it produces the appearance I need.

Code: Pascal  [Select][+][-]
  1. if FTimeWidth > 0 then
  2.   R.Right := R.Right + Canvas.TextWidth(' ');

The only remaining issue is that the mouse hit-testing still uses the hardcoded 2 * FDigitWidth spacing. It should use the same configurable spacing as the rendering code.
To keep the mouse hit-testing in sync with the rendering, the following code in TCustomDateTimePicker.SelectTextPartUnderMouse should also be updated:

Code: Pascal  [Select][+][-]
  1. if NX >= FDateWidth + FDigitWidth then
  2. begin
  3.   InTime := True;
  4.   NX := NX - FDateWidth - 2 * FDigitWidth;
  5. end;

to use the same spacing value as the rendering code, for example:

Code: Pascal  [Select][+][-]
  1. Gap := Canvas.GetTextWidth(' ');
  2.  
  3. if NX >= FDateWidth + Gap then
  4. begin
  5.   InTime := True;
  6.   NX := NX - FDateWidth - Gap;
  7. end;

This ensures that the mouse hit-testing uses the same spacing as the rendering.

My use case is that I use TDateTimePicker as an in-place editor inside a grid cell. When editing starts, the time shifts noticeably to the right because of this large gap. This creates an undesirable visual artifact, as the contents of the edited cell no longer line up with the other cells in the grid.

I'm not suggesting changing the default behavior. However, it would be very useful if this spacing could be made configurable. For example, by exposing the gap width as a property, or at least making the calculation virtual/protected so descendant classes can override it without having to maintain a patched copy of the entire unit.
« Last Edit: July 11, 2026, 05:20:37 pm by AlexanderT »

Zoran

  • Hero Member
  • *****
  • Posts: 1993
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: TDateTimePicker - Make the date/time separator configurable
« Reply #3 on: July 11, 2026, 06:21:13 pm »

I don't know whether the original author of TDateTimePicker is still around here.

I am... Not closely as often as I used to be, though...


But the component has been included in the LCL and, thus, is maintained by the Lazarus team. Please report your request in the bug tracker (https://gitlab.com/freepascal.org/lazarus/lazarus/-/work_items).


If you report it, please post the link here.


to use the same spacing value as the rendering code, for example:

Code: Pascal  [Select][+][-]
  1. Gap := Canvas.GetTextWidth(' ');
  2.  
  3. if NX >= FDateWidth + Gap then
  4. begin
  5.   InTime := True;
  6.   NX := NX - FDateWidth - Gap;
  7. end;

This ensures that the mouse hit-testing uses the same spacing as the rendering.


Just a small correction -- if you take a closer look at the current implementation only one "DigitWidth" is in "if" line, but then, it's 2*Digit with inside.

So, the gap should be replaced with half of the gap, but only in "if" line:
Code: Pascal  [Select][+][-]
  1. Gap := Canvas.GetTextWidth(' ');
  2.  
  3. if NX >= FDateWidth + Gap div 2 then // div 2 added here
  4. begin
  5.   InTime := True;
  6.   NX := NX - FDateWidth - Gap; // here, it should remain so
  7. end;

Then the code will behave as it behaves now, when Gap is set to 2*DigitWidth.
When you click closer to time, the control decides to select the first part of time (the hour), not the last part of date. That's why the gap should be divided by two.


I'm not suggesting changing the default behavior. However, it would be very useful if this spacing could be made configurable. For example, by exposing the gap width as a property, or at least making the calculation virtual/protected so descendant classes can override it without having to maintain a patched copy of the entire unit.


How to implement the property without breaking the current implementation? Should the property be an Integer which represent pixels? Then, what should be the default?

Better -- it could be a Float value which would multiply the calculated "DigitWidth", so the default would be 2.0.

But too many properties make a mess — the programmer needs to search through documentation to understand how to control the control's behaviour. I don't know.
« Last Edit: July 11, 2026, 06:24:25 pm by Zoran »
Swan, ZX Spectrum emulator https://github.com/zoran-vucenovic/swan

AlexanderT

  • New Member
  • *
  • Posts: 34
Re: TDateTimePicker - Make the date/time separator configurable
« Reply #4 on: July 11, 2026, 07:46:48 pm »
I am... Not closely as often as I used to be, though...

It's nice to meet the original author! Thank you for creating this very useful component.

If you report it, please post the link here.

I will. At the moment I have a working solution by including a modified copy of the unit directly in my project, so it isn't urgent. I'll create a work item when I have some time.

When you click closer to time, the control decides to select the first part of time (the hour), not the last part of date. That's why the gap should be divided by two.

Now I understand, thank you for the explanation!

Better -- it could be a Float value which would multiply the calculated "DigitWidth", so the default would be 2.0.

I think it might be difficult to match the width of a normal space accurately by using a multiplier. A shift by two full spaces may be slightly noticeable, but a shift by just one pixel can be even more annoying :)

Perhaps it would be simpler to keep the current behavior as the default and just add a Boolean property to enable or disable the extra spacing between the date and time? (To be honest, I'm still not sure what the purpose of the extra spacing is...)

Or perhaps make the gap calculation a protected virtual method instead of adding another property, for example:

Code: Pascal  [Select][+][-]
  1. protected
  2.   function GetDateTimeGap: Integer; virtual;

and then replace the relevant occurrences of 2 * FDigitWidth with GetDateTimeGap.
« Last Edit: July 11, 2026, 08:14:23 pm by AlexanderT »

wp

  • Hero Member
  • *****
  • Posts: 13649
Re: TDateTimePicker - Make the date/time separator configurable
« Reply #5 on: July 11, 2026, 08:20:10 pm »
My use case is that I use TDateTimePicker as an in-place editor inside a grid cell. When editing starts, the time shifts noticeably to the right because of this large gap. This creates an undesirable visual artifact, as the contents of the edited cell no longer line up with the other cells in the grid.
Reasonable point.

I don't know whether the original author of TDateTimePicker is still around here.
I am...
Sorry. There used to be a "ZV" prefix at the component name in the old times, but since you obviously dropped the "V" in your nick name I did not make the connection to you...

Did you get commit rights when you donated the component? If yes, you can handle the request yourself, otherwise I can do it for you.

How to implement the property without breaking the current implementation? Should the property be an Integer which represent pixels? Then, what should be the default?
In my opinion, there is a need of only two options: the current setting with the wide spacing, just to keep compatibility, and a setting with the "narrow" spacing to get the same layout as in FormatDateTime. Therefore, I'd propose a property DateTimeSpacing: TDateTimeSpacing = (dtsWide, dtsNarrow). And there should be an internal variable, FDateTimeDistance, for the current pixel distance between the date and time parts. In case of dtsWide FDateTimeDistance should be calculated as 2*FDigitWidth, and in case of dtsNarrow it would be the width of the space character.

I am attaching a patch which implements this on the basis of your input. I also tried to adapt autosizing when the spacing setting changes, but I must have missed something because the picker's size does not change in this case.

Zoran

  • Hero Member
  • *****
  • Posts: 1993
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: TDateTimePicker - Make the date/time separator configurable
« Reply #6 on: July 12, 2026, 12:21:29 am »

Did you get commit rights when you donated the component? If yes, you can handle the request yourself, otherwise I can do it for you.

Would you commit it? You've prepared the patch already. :)
You could also add the property to published section in db aware control (dbdatetimepicker.pas).

I had commit rights in svn, but... I'm a bit embarrassed to admit that when Lazarus moved to git, I stopped.



I also tried to adapt autosizing when the spacing setting changes, but I must have missed something because the picker's size does not change in this case.

Near the bottom of RecalculateTextSizesIfNeeded procedure, take a look at this code (currently lines 1475-1477 in datetimepicker.pas):
Code: Pascal  [Select][+][-]
  1.     FTextWidth := FDateWidth + FTimeWidth;
  2.     if (DateParts > 0) and (TimeParts > 0) then
  3.       FTextWidth := FTextWidth + 2 * FDigitWidth;
  4.  

In the last line "2 * FDigitWidth" should be replaced. I think that should be enough (FTextWidth is used in CalculatePrefferedSize, so it should be calculated correctly).
Swan, ZX Spectrum emulator https://github.com/zoran-vucenovic/swan

wp

  • Hero Member
  • *****
  • Posts: 13649
Re: TDateTimePicker - Make the date/time separator configurable
« Reply #7 on: July 12, 2026, 12:59:57 am »
OK, committed, the link to this discussion is in the commit notes.

@AlexanderT: There is no need any more to write a bug report. The new version is in the main branch of Lazarus and will be contained in the next major release, v5.0.

AlexanderT

  • New Member
  • *
  • Posts: 34
Re: TDateTimePicker - Make the date/time separator configurable
« Reply #8 on: July 12, 2026, 09:57:05 am »
That was unexpectedly fast! Thank you both for the quick response and implementation.

 

TinyPortal © 2005-2018