I had a requirement in the Daily Exchange Rate screen to display a date and time. There are a number of tables in the database that contain date and time elements and up to now we have not had a way of displaying times without resorting to manual code - and we had no way to display times in the grid at all. In every case times are stored in the database as seconds in the day - i.e. an integer value between 0 and 86399, so when a time field is included in a grid it appears as a numeric integer - not a typical time like 10:00.
So I have now added functionality to the code generator and YAML parser so that an OpenPetra integer time can be displayed as either a short time string or a long time string. In addition you can validate a time column using a new TTimeChecks.IsValidIntegerTime method.
[color=#0000FF]YAML For the Grid[/color]
All that you have to do is specify your chosen Type attribute in the YAML file corresponding to the grid column. So, for example...
grdDetails:
Dock: Fill
Columns: [DetailFromCurrencyCode, DetailToCurrencyCode, DetailDateEffectiveFrom, DetailTimeEffectiveFrom, DetailRateOfExchange]
CustomColumns:
DetailRateOfExchange: {Label=Rate of Exchange, Type=Currency(10)}
DetailTimeEffectiveFrom: {Label=Time, Type=ShortTime}
ActionFocusRow: FocusedRowChanged
The above shows that the TimeEffectiveFrom column of the database (which is an integer) has a Type of ShortTime, because I want it displayed as 10:00.
If you want your time display to include seconds, you can specify the Type as LongTime.
The YAML specification results in the column for the grid being added as a ShortTimeColumn as follows
grdDetails.AddShortTimeColumn("Time", FMainDS.ADailyExchangeRate.ColumnTimeEffectiveFrom);
The grid uses a new Type Converter that handles times. This TimeConverter is located in the same file as the DateConverter we already have. There are two new time converters: TShortTimeConverter and TLongTimeConverter. Since the code for both is almost identical, except for the string format expression, the code that does the work is factored out into a private internal class that can handle conversion of times between various integer and string formats.
When the converter converts TO a string it displays the time in the users preferred short or long format. This means, for example, that it might be displayed as 24 hour time or am/pm time - depending on the PC settings. This does not matter to OpenPetra because, unlike dates, we never actually store the time string in the database (as opposed to the date string which is stored, so has to be in a fixed format). Conversely, when the user has to enter a time, any format that the .NET parser can interpret as a time will be valid for data entry. If the user enters an invalid time string, the converter returns -1 as the integer value. It is this return value that can be validated as an invalid time by the standard data validation.
If the database contains an invalid time, such as -1, due to bad data entry, the TimeConverter will convert this to the string "??:??" or "??:??:??". So if you have enabled validation and you enter a badly formed time, like 10:040, the tooltip will pop up with a special (new) bad time format message and at the same time the grid will have the "??:??" string in the cell for that row, until you correct your typing. (I would show you a screenshot if I knew how to upload an image to the forum!)
The new validation routine in the new TTimeChecks class is this.
public static TVerificationResult IsValidIntegerTime(Int64? AValue, String ADescription,
object AResultContext = null, System.Data.DataColumn AResultColumn = null, System.Windows.Forms.Control AResultControl = null)
It checks that AValue is in the range 0..86399. Any value outside fails validation.
[color=#0000FF]YAML For the TextBox[/color]
You need to specify Type=ShortTime or Type=LongTime in the YAML file for the Text Box as well, as shown for example here.
txtDetailTimeEffectiveFrom: {Label=Time Effective, Width=70, Type=ShortTime, Validation=true}
This specification will enable the code generator to handle all the data display automatically. So the code that is generated for this control's ShowDetails is as follows.
txtDetailTimeEffectiveFrom.Text = new Ict.Common.TypeConverter.TShortTimeConverter().ConvertTo(ARow.TimeEffectiveFrom, typeof(string)).ToString();
while the code that is auto-generated for GetDetailsFromControls is this.
ARow.TimeEffectiveFrom = (int)new Ict.Common.TypeConverter.TShortTimeConverter().ConvertTo(txtDetailTimeEffectiveFrom.Text, typeof(int));
The new UndoData code that is part of data validation also uses code that incorporates the new converter. As a result there is no manual code to write to enjoy the benefits of adding times to our data displays.
At the time of writing, this code is not yet checked in, but when it is you can see the results in action on the Daily Exchange Rate screen, which you can access from the Finance Setup main menu.