Generic surprises

Generic surprises

1. The generic type is constrained, but cannot be used for class references?

type

TBase = class

procedure NothingAbstractHere;

constructor Create; virtual;

end;

TGenericWrapper = class

type

TBaseClass = class of TB; <– [dcc32 Error]: E2021 Class type required

end;

Is there any logical reason for why this should not be possible?

2. Constructing an instance from a generic type does not flag construction of a class with unimplemented virtual abstract methods. This one I can understand, but it still is annoying. I guess I could factory functions to work around it.

My local Embarcadero pusher, Alfacode, indicates in a newsletter that Tokyo 10.

My local Embarcadero pusher, Alfacode, indicates in a newsletter that Tokyo 10.2 will go official on April 24th. corrected to March 27th.

There will be half-day preview seminars in Stockholm on April 20th

https://www.alfasoft.com/no/events/embarcadero/648-rad-studio-10-1-berlin-live-stockholm.html

and Gothenburg on April 21st

https://www.alfasoft.com/no/events/embarcadero/649-rad-studio-10-1-berlin-live-stockholm.html

(Yeah, someone screwed up that last link name :))

Let the Linux WTFs commence 🙂

It’s not always easy to pick a good color that will show well on displays with limited color depths.

It’s not always easy to pick a good color that will show well on displays with limited color depths.

If anyone knows if this exists – or have some time on their hands, it would be good to have a simple application that could render the System.UITypes TColors constants for lines/text/brushes on different color depths (8 bit, 16-bit, 32-bit). Showing the name of the color (or atleast the hex value) would be good and being able to copy it to the clipboard as a string would be great.

#application #suggestion

CodeRage XI – NOVEMBER 15-17, 2016

CodeRage XI – NOVEMBER 15-17, 2016

Article at

https://community.embarcadero.com/article/news/16433-coderage-xi-productivity-platforms-and-performance

“We’ve got 3 jam-packed days of engaging content—for developers like you. Please note that Day 3 is by invitation only to Update subscribers. We’re offering a wide variety of topics that center around Embarcadero products, related technologies, Object Pascal, and C++.”

Sign up for the webinars here:

http://forms.embarcadero.com/CodeRageRegistration

Internal types and scoping

Internal types and scoping

The code below shows something that is a bit of a mystery to me.

  TQuerySetToGrid = class(TQuerySet); // simplified

  TQuerySetXML = class(TQuerySetToGrid)

  public

    Id: TQuerySet.TFieldInteger;

    TimeStamp: TQuerySet.TFieldDateTime;

    PID: TQuerySet.TFieldInteger;

    TID: TQuerySet.TFieldInteger;

    Level: TQuerySet.TFieldEnum;

    Category: TQuerySet.TFieldEnum;

    App: TQuerySet.TFieldString;

    Client: TQuerySet.TFieldString;

    Title: TQuerySet.TFieldString;

    constructor Create; override;

  end;

Apart from “it works that way” – is there a reasonable explanation of why I have to qualify the TFieldxxxx types which all are public types declared inside TQuerySet, when referring the types inside a descendant class? I wonder!

/off-topic

FYI, this is actual code and part of a log viewer in our monitoring and maintenance tool, and to give you an idea of what I am trying to achieve…

This is the scaffolding code needed for link a grid and a query to display the results from a TDataSet.

Initialize and set up the look of the grid:

  XMLQueryLog := TQuerySetXML.Create;

  XMLQueryLog.Grid := sgLog;

sgLog is a TAdvStringGrid dropped on a frame, and there is some grid specific code to get the desired look, and ofcourse code to handle grid operations – but for the content, this is the only scaffolding needed.

Execute the query and fill the grid:

  XMLQueryLog.Refresh(SQLStatement);

The “real” scaffolding happens in that Create you saw in the initial class.

constructor TQuerySetXML.Create;

begin

  inherited;

  Id := Add(‘Id’, 64);

  TimeStamp := Add(‘TimeStamp’, ‘Dato og tid’, 120);

  PID := Add(‘ProcessId’, ‘PID’, 64);

  TID := Add(‘ThreadId’, ‘TID’, 64);

  Level := Add<TFieldEnum>(‘XLevel’, ‘Nivå’, 70);

  Level.Formatter :=

    function (const Lvl: TLogEventLevel):String

    begin

      Result := LogEventLevelToString(Lvl);

    end;

  Category := Add<TFieldEnum>(‘XCategory’, ‘Kategori’, 70);

  Category.Formatter :=

    function (const Cat: TLogEventCategory):String

    begin

      Result := LogEventCategoryToString(Cat);

    end;

  App := Add(‘AppShortName’, ‘App’, 30);

  Client := Add(‘ClientName’, ‘Client’, 140);

  Client.HAlighment := taRightJustify;

  Title := Add(‘Title’, ‘Beskrivelse’, 800);

end;

which is a lot less code than I needed before.

Basically, I Add(‘sqlcolumn’, ‘Grid Col Title’, width in px);

If I don’t add any field specifications to the QuerySet, they will be generated based on the query results and the name/TFieldType of each column.

The old code also read individual log objects from the database and then moved them to the grid – while this uses SQL -> Grid – so it is quite a bit faster.

I could also use owner draw and a virtual grid to avoid duplicating the query results as strings in the grid – but that would rob me of some of the nice features of TAdvStringGrid.

Right now, there are only two conversions for each cell – first DB result to native, and then native to string – and there are no case statements 😉

Still work in progress, but I am reasonably happy so far – except from that internal type scope thing?