Note to self: Icons for Windows applications with multiple resolutions can be created by combining multiple png images using the convert tool that comes with ImageMagcic:
convert 16.png 32.png 48.png 128.png 256.png -colors 256 icon.ico
I just updated the Custom Container Pack sources to support Delphi XE8. It was mostly a matter of creating the packages for the “new” version. I also added XE8 to the compilerversion.inc file.
It now compiles and installs. I have not tested it extensively.
Custom Containers Pack (CCPack) is an integrated tool and component mini-library to produce and maintain composite controls (or simply “composites”) and other containers (forms, data modules and frames). The process of building composite components looks like ActiveForm and Frame creating, but the result is the native VCL component. You can create new composites just as usual forms.
Here is the original documentation in RTF format.
A new release of my experimental GExperts version is available. I fixed yet another issue with Unicode / UTF-8. It works now with some Arabic strings which got converted to question marks before.
The usual warning applies: My unit tests still work so apparently I haven’t broken too much in the process. I also tested it manually, but only with a limited set of IDEs and only some of the functionality. So you might find new bugs. If you do, please contact me through my G+ profile (see upper right).
The download links are on the Experimental GExperts page as usual.
In my last post I announced that the GExperts code formatter is now Unicode aware. Little did I know. Mohamed Kamel sent me a source file with Arabic strings which still got converted to question marks. So today I have dived into the source code again. I nailed the problem with Arabic strings (and added a new unit test). But I am pretty sure I missed some more.
I’ll release a new version as soon as I got feedback from Mohamed.
Anybody got some source code with Japanese and Chinese strings for me?
After getting my Delphi XE8 installation to work again I have released a new experimental GExperts version. It is the first where the code formatter should be fully Unicode aware (for Delphi IDEs supporting Unicode, that is >= 2005). My tests worked and some brave souls also tested it live.
In this process I also found out that most people use UTF-8 encoding for their source code and apparently nobody uses UCS-2 or UCS-4.
So, if you had any problems with the code formatter converting your special characters to question marks, you should update.
The usual warning applies: I did test it, but only with a limited set of IDEs and only some of the functionality. So you might find new bugs. If you do, please contact me through my G+ profile (see upper right).
The download links are on the Experimental GExperts page as usual.
When the Delphi XE8 update1 was released it was also about the time for our company to renew my Delphi subscription. Unfortunately our accounting department fouled up paying the bill so for a short while my subscription was not valid. I knew nothing about this and installed the "Subscription Update". This left me with the following message.
"An Update Subscription for Embarcadero Delphi XE8 is required which has expired prior to this release."
Not quite what you want to read when you update your development environment. The first thing I tried was uninstalling Delphi and reinstalling it from the ISO that included update 1. It didn’t help at all.
Then I got sidetracked (work always interferes with fun, doesn’t it ;-) ).
Only last Friday I came around to submitting a support ticket to Embarcadero, describing the issue. The fix turned out to be very easy:
It just worked.
Yahoo just announced that they will be shutting down Yahoo Pipes on 2015-08-30. Unfortunately that means that DelphiPipe will also die, because I don’t have the resources to move it to anywhere else. At least there is a new service that competes with DelphiFeeds: BeginEnd. It’s even written in Pascal, so that kind of fits.
In this version the formatter now uses unicode strings for all Delphi versions that support them. The previous versions converted native Delphi strings to AnsiString before formatting and converted the result back from AnsiString to native Delphi strings. In rare cases this resulted in some special characters being replaced by ‘?’ after the formatting.
Thanks to Hichem BOUKSANI for providing a test case an checking the result.
PLEASE BE WARNED: This version has not had extensive testing. My unit tests still work for Delphi 2007 and XE8. Make sure you have backups. Use source revision control software so you can spot any errors the formatter might make.
Head over to the Experimental GExperts page to download the new version.
# create archives $ tar cz . | split -b 100GiB - /mnt/8TB/backup.tgz_
This uses the tar command to create a gzip-ed archive of all files in the directory tree starting with the current directory. The output is written to stdout.
This output is then piped into the split command that splits it into multiple files of 100 Gibibyte and writes them using the given prefix, appending aa, ab, ac etc. The "-" tells split to process its stdin rather than a file.
The input amount is massive and contains very may hard links (it’s a daily dirvish backup dating back 2 years).
To restore from this backup, the following command will be used:
# uncompress $ cat /mnt/8TB/backup.tgz_* | tar xz
This uses the cat command to pipe all input files to stdout, concatenating them implicitly in the process. This is then piped to the tar command again which extracts it as a gzip-ed archive to the current directory. (I have to try that yet, the backup is still running.)
In a recent Google+ post Andrea Raimondi was mentioning the JVCL’s JvValidators components and asked whether we use/know them or not. Daniela Osterhagen mentioned that she preferred the input validation from my dzlib which led to a short discussion about how I implemented it.
I added input validation functionality to dzlib because I didn’t like the way JvValidators works. I’ll not go into the reasons but the most important one was performance, the programs using JvValidators felt like running on an old 286 computer. Instead I’m going to show here, how it currently works. Note that I am not satisfied with this yet, see below for the reasons.
First thing you do, is get an instance of the IdzInputValidator interface by calling the InputValidator function from unit u_dzInputValidator. That function takes two optional TColor parameters OKColor and ErrColor which default to clWindow and clYellow respectively.
procedure TMyForm.CheckInput; var iv: IdzInputValidator; begin iv := InputValidator; // we just take the default colours
This interface has a number of overloaded Check methods that take different types of controls, I have implemented Check methods for T(Custom)Edit, T(Custom)ComboBox, T(Custom)Checkbox and TJvDateEdit (but see below). These methods return specialized interfaces that are meant to validate the data in theses controls. I’ll show that using a TEdit for entering an integer number between 5 and 10 (including these limits) as an example.
// continued from above iv.Check(ed_NumberInput).AsInteger.IsBetween(5, 10);
If it is allowed for the TEdit to be left empty, there is this alternative:
// continued from above iv.Check(ed_OptionalNumberInput).AsInteger.IsBetweenOrEmpty(5, 10);
These are actually several function calls wrapped into one line:
Check, returns an IdzEditValidator interface, AsInteger returns a IdzEditIntegerValidator interface and IsBetween / IsBetweenOrEmtpy returns a boolean. I am using interfaces because I am a lazy bastard™. I don’t want the hassle of freeing the classes that are being created on the fly.
After you have validated the input of all these controls, you ask the IdzInputValidator interface for the result. There are two overloaded GetResult methods, one simply returns a boolean, the other also returns an error message. I am assuming here that there is a TStatusBar on the form which will display this error message and an OK button that should be enabled only if the input is valid.
// continued from above b_Ok.Enabled := iv.GetResult(ErrMsg); // note: Declare ErrMsg: string TheStatusBar.SimpleText := ErrMsg; end;
To make CheckInput do anything at all, you need to call it when the data in the form changes, e.g. in the OnChange events of the controls.
procedure TMyForm.ed_NumberInputChange(Sender: TObject); begin CheckInput; end;
Behind the scene IdzInputValidator and friends change the background colour of the input controls based on whether the input is valid or not. If it is valid, the colour is set to the OKColor, if not, it is set to the ErrColor. These colours were passed to the call to the InputValidator function right at the start and default to clWindow and clYellow. It’s a matter of (bad?) taste which colours you prefer. I like yellow because it still allows to read the input easily in contrast to e.g. red. Instead of colouring the controls it is also possible to show a blinking icon with an exclamation mark like JvValidators does but I am not going into that right now.
This implementation is already the second rewrite of the code. In the beginning IdzEditValidator used to have lots of methods like ValidateFloat, ValidateFloatBetween, ValidateInteger, ValidateIntegerBetween, ValidateDate etc. I changed it to have these As<someType> methods that return more specialized interfaces because it became unwieldy. I was pretty satisfied with this implementation until there was a requirement to validate additional controls.
The first one was TJvDateEdit. This required JvToolEdit to be added to the uses clause of u_dzInputValidator. Not every program uses the JVCL, so I added the conditional define NO_JVCL to exclude this code. Not pretty, but I could live with it.
The next one was TSigFilenameEdit (which is an internally developed control at work that is a bit similar to TJvFilenameEdit). It required an ugly hack because I could not simply add the unit that defines it to the uses clause of u_dzInputValidator.
It became worse when there was a requirement to not only validate the controls on a form but the validation was to span several frames which were put on this form.
Generally this problem is referred to as tight a coupling, in this case between the validator interface an the controls. There are a few ideas to resolve this issue:
1. I could create descendants of IdzInputValidator that know additional controls, so there would be additional Check methods that take a TSigFilenameEdit or even a Tfr_MyFrame parameter. This breaks down as soon as there are multiple, mutually exclusive controls to support. e.g. Support for JVCL controls and internal controls, because there is no multiple inheritance support in Delphi. (Hm, I’m not even sure whether mutliple inheritance could solve that problem. Maybe generics or rather my pseudo templates could? I’ll have to thing about this one.)
2. I could create overloaded functions ControlValidator that take a control and an IdzInputValidator interface like this:
function ControlValidator(_ed: TEdit; _iv: IdzInputValidator): IdzEditValidator; overload; function ControlValidator(_ed: TJvDateEdit; _iv: IdzInputValidator): IdzJvDateEditValidator; overload;
These functions, in contrast to the methods of an interface, could be distributed over multiple units so I could include only those units that support the controls I am currently using. (This would be similar to the different IDatasetHelper implementations for BDE, ADO, ZEOS, tdbf etc. in dzlib.) This would sacrifice some convenience but would pretty much work. I don’t like the additional iv parameter, it just clutters the code. Also, the programmer would be responsible to add the unit containing the function declaration, e.g. for supporting TJvDateEdit add u_dzInputValidatorJVCL.
3. I could come up with some kind of registration mechanism for control validators that register validators for various kinds of controls with a central factory. That factory would then return the correct validator interface for a given control. That would add more complexity to the currently simple way of the validation mechanism. Also, how do I then call the actual validation methods? Have a generic interface that takes e.g. a string describing the check I want to do? No, too ugly.
4. I could revert to checking strings rather than control content. Maybe all that is required is a way to get the control’s content as a string, so TCheckbox.Checked would be converted to ‘Y’ and TCombobox.ItemIndex with IntToStr(…), so solution 3. could be simplified to supply an interface that returns a string which then gets checked. That could be even taken further to using regular expressions. (Remember that joke: You have a problem, you decide to solve it with regular expressions, now you have two problems.)
I am currently leaning towards solution 2. It allows the most flexibility without adding too much overhead. But I am going to publish this blog post on G+ to ask for feedback. Maybe somebody else has a brilliant idea?
Here is the G+ post.