Tuesday, September 10, 2019

MVVM Survey results and feedback!

First of all, thanks to everyone who participated in my MVVM survey. Your feedback will influence my decisions!

Here are the Results:

693 Views resulting in 159 completed surveys. (22.9%)


I created 4 different links (my Blog, DelphiPraxis (german only), Twitter and Facebook. The main difference is the View/Fill out ratio.

Facebook : 32,4% // Best of 4 - Thanx
DelphiPraxis : 30,6% // not bad! Danke an meine Leser!
Twitter: 16,5% // I still have no clue why anybody is writing here
This blog: 14,6% // Hey my friend's - you are already reading here!

Perhaps I have to add DelphiPraxis and my blog because some got the RSS-Feed link!


Do you already separate your logic and your UI  with (MVP, MVC or MVVM)

58 from 159 would like to separate logic and UI.
66 already using some kind of separation. // more than I expected

Interfaces?

14 from 159 answered: Don't want to learn how to... // Strange
104 had no problems with interfaces.
41 want to learn how to work with interfaces. // Should I do a Youtube Video for this topic? 

Please leave a comment!

Attributes?

48 of 155 never used
78 of 155 knows how to use
57 of 155 already implemented own Attributes // Good
12 of 155 dislike Attributes in the source code // Ohh... Please give it a try  

Generics?

19 of 159 never used
8 of 159 dislikes generics

If I would use an MVVM-Framework it has to

- match the C# tutorials (12,6%)   // Sorry this won't happen
- work save and fast! (42 %) // Thanx you are my target group
- be freeware (38%) // Sorry this will not be free
- work with VCL (73,3%) // OK, I will implement this too *grumpf*
- work with FMX (50%) // Main target - of course it will work with FMX
- on all platforms (50,6 %) // Of course... With and without ARC I hope for 10.4

If the MVVM framework is not free/opensource what is the chance you would spend money to buy it?



How much would you spend for a Delphi-MVVM-Framework


less than 100€ (58,8%) // For so much work it's a little to low (perhaps as early Bird)
100€-199€ (24%) // Maybe
200€-299€ (8,5%) // It's a good prize
300€-399€ (2,1%) // Good news it would be less
more than 400€ (6,3%) // Thanx, but I think for this price it's unsaleable

Remember it would be with free updates for one year.

How old are you?


How long have you been developing with Pascal/Delphi?


Mark all your Delphi Versions you are still using.


29% are using a Delphi-Version older than Delphi 2007 // Wow why?
14,7% still using 2007 // Welcome in the non Unicode migration club
31,8% Delphi 2009-XE9 // Please update at least to Seattle
12,1% Seattle // OK
24,2% Berlin // Better
41,4% Tokyo // Very good!
70% Rio // NICE!


So far so good, thanx again and leave a comment or give me a call if you want more information!

Saturday, September 7, 2019

Is there a sharp border between MVVM and MVC/MVP?

This is a really good question... And without long thinking about it, you probably would say "yes"!

Ok! But where do you draw this line? And why?

Many MVVM Experts - whatever makes them experts - would tell you: Delphi is unable to do "real" MVVM because we have not the binding stuff like C#. 

And no! We don't compare the live binding with C#'s binding.

So why I'm still on this project since 2015, to prove the experts wrong? No...

The reason why I'm still developing an MVVM-Framework is that I'm looking for the best way - with Delphi - to separate the form from the business logic and the database. 

Perhaps, in the end, we will have some kind of patter that should not be named MVVM, but I don't care if it works as expected. Comparisons with C# should be stopped here immediately. We do not edit XML files by hand and we like to avoid so much typing for every propertychange. :-)

Transferring data from an Edit to a property in the ViewModel, to the Model, to the database is a piece of cake. But even at this point, I do not want to fire an event like "Hey my Name has changed guess what the new value is, or ask me". So I like to broadcast my Name to all listeners!

But when it comes to ListViews or Grids, things getting difficult. What event should I fire or what if the Grid is scrolled, should I preload more rows? Is this part of the binding or the ViewModel or a Cache-Class? Where to store the data?

But back to the topic!

MVVM did not have access to a component, MVVM is only dealing with properties. MVC/MVP has more direct access. So what can we do to get "kind of" access but not the component itself? If I cross this line, will every expert tear me up in the air? So I do not do this.

Of course, you can do some kind of imposer grid that is able to handle a properychanged event and then? Get the complete data to compare or just refresh all data in the grid? Because one "cell" has changed? No sorry, not on my shift.  

The View has - perhaps - some stuff to do with the grid. But not holding the data! That's why I like the FMX, TGrid implementation where you have to provide the Data to the Grid only for the cells that are currently displayed. But how can you connect the Grid to the ViewModel, I mean how could the ViewModel throw some events to do so?
Your GridViewModel could have a property Cell[Row,Cell : Integer] : TValue; But I dislike to have a ViewModel for every Grid! 

Imagine this kind of application:

One Form as Person.View für editing all the Person-Data fields. But at the bottom a nice grid with matching addresses. If you click on the Grid the data is loaded into Edits.

So wouldn't it be nice to have some access/datastore in your Person ViewModel for the grid also?

I think so...  I call it GridProperty and in this case I call it:
fMatchingAddresses : TGridProperty;

On the View I have a normal TGrid, but how to connect to the
Property MatchingAddresses : TGridProperty;?
Just place a TGridAdapter from the MVVM tab on your form and connect your Grid to the GridAdapter. DONE. Everything else is done behind the scenes. You can configure the GridAdapter like the were a database involved, to select the Fields you want from the all-possible-field-list.

I call this a #PropertyChangedTunnel. Is this already not MVVM anymore? Whatever! Then find a better name for my pattern and I will consider changing the framework name... ( Perhaps not )

And there will be some kind of ORM interface stuff to fill the property with the necessary data from the model and/or give a callback to read more data from the Model/Database. 

Does it work?

#FastAsHell

Stay tuned... More info's are in the pipeline.

Wednesday, August 28, 2019

Thursday, August 15, 2019

Missing stats in 10.3.2?

Project statistics are "gone" in 10.3.2!

I love this little time in my projects and I could not understand why other developer is complaining about this feature. Now it is gone...

No, it's optional but you have to create a registry key:

In HKEY_CURRENT_USER\Software\Embarcadero\BDS\20.0\ProjectStatistics, 
create a DWORD value “Enabled”, and set it to 1.

if "ProjectStatistics" is missing just create this key, too

Happy Time-Counting...

Sunday, August 11, 2019

FMXLinux first test.

FMXLinux first test.

I did not test the Linux part of the RAD-Studio ecosystem, because every Server-Stuff is running on my Windows Servers. So I never had the need to play with Linux at all.

And I also never thought about Linux as a Desktop System. I have no customers that want to use Linux and also I never tried anything with or on Linux. 

Perhaps that's why I hate OSX and would never use an Apple for development.

But:

Installing Ubuntu in a VM as not a big deal and with some Sudo Stuff it was easy to install the necessary parts and the Paserver.

So a "Hello World" App is running in seconds with no problems.

For the real-test I want some more, so I tried to compile my Store App ~380k LOC with many kinds of FMX stuff in use.

And here I found some problems. Not all the System units have the necessary IFDEF's for LINUX/LINUX64.

So I had to copy System.Notifications, System.Sensors.Components and System.Sensors to my Application directory and provide empty implementations for System.Linux.Notification and System.Linux.Sensors.

Indy is throwing an exception because of the Thread.Nameing-Stuff has also no Linux part. (But this is only in Debug-Mode).

With these little changes my app got compiled and runs on Ubuntu.

Some UI parts like fonts (font size) and Images are not working as expected. I did not track down the Image-Button problem so far. But it looks that everything else is working.

Nice...

Compile and Deploy time is perfect compared to OSX, because both VM's are running at my development PC (5 GHz, Raid 0, M.2).

Because I have no use-case at the moment, I have nothing to test on Linux at the moment...

(Oh wrong! I'm currently developing a Backup-Cloud-store-Cryping Server on the Raspberry Pi, of cause on Android - too bad my only use-case at the moment would be Linux 32 bit on ARM CPU and this isn't supported with Delphi)

Have fun...





Tuesday, July 23, 2019

Consulting für VCL & FMX Projekte!

Hallo!

Natürlich biete ich weiterhin Consulting und andere Hilfen bei euren Delphi Projekten an.

Die aktuelle Preisliste ist weiterhin online verfügbar unter:

http://www.delphiprofi.de/delphiprofi-preisliste.pdf

Bei Interesse einfach eine mail an Frank(at)delphiprofi.de

Grüsse

Saturday, July 6, 2019

Time shared development.

Good or Bad Idea to shared your development time between projects?


For some time I had no topic to share with you, I'm sorry.

Like most other developers, I have not only one project to do. Of course, there are two or three main projects to handle, but what's about the side project I have to or like to do?

In the past I stopped the development of my main projects and switched the focus to project E. After finishing E in a short time, I came back to A, B, and C. That was fine for a long time.

Sometimes if I got stocked in my development I put project E on holt, to get back to ABC. If the amount of time was too long, I started by zero if I tried to resume project E, in other words: To get back into E it takes too much time.

If I worked for many months on project B - life got boring. So what could I change?

Imagine you like to do a lot of different things - some will earn you money, some will help you with the future project and some are just for fun or you want to try some new stuff.

So with the main projects A, B and C you start 4 more or even interesting projects D-G. at this point, you have 7 active projects one for every day of the week (if you work 7/days/week). ;-)

So every day I decide what's the topic for today between A-G. Nice! Every day a new task to do. Sometimes the same for two or three days in a row, but then resume another project.

This was a nice idea and improved my work a lot.

There is - of course - a backside of the medal: Projects that normally takes 3 months now takes 12! That's the only drawback you have to deal with... It feels like you are not getting any progress because no project get's finished or even shipping state.
So do scrump with no team? Perhaps some kind of project Gantt graph thing, to see progress in all your projects… If I find good software, I like to try this.
Or add project H for that topic to my list… ;-)

Friday, February 15, 2019

Be carefull with inline vars.

The new inline var is a great feature. You can save time and your code looks more cleaner.

But are there any problems with inline vars and the auto-type functionality?

Let's take a look at a small example.

Procedure Foo
var
  i : int32;
  x : uint32;
begin
  x := 0;
  for i:=0 to x-1 do
    Bar(i); // Bar would never be called.     
end;

Procedure Foo;
var
  i : int32;
begin
  for i:=0 to MyList.Count - 1 do
    DoSomeThing(MyList[i]); // Should work as expected
end;

Procedure Foo;
begin
  for var I := 0 to MyList.Count - 1 do
    DoSimeThing(MyList[i]); // Are you sure this is working?
end;

At this point, you are unable to decide!!! You have to take a look at the function result of Count. if the result is an uint32 this is not working, because the compiler takes an uint32 for I and the for is running "forever" ( from 0 to $FFFFFFFF ).

If your implementation of this list auto-creates elements on reading access you have a problem...

Edit:
Sorry about the late comments - I did not know I have to approve them.

Tuesday, February 12, 2019

Simple 3D Hello World in Firemonkey!

Games with FMX!

Is Firemonkey ready for game development - of course! There are many games out in the wild written with Delphi and also with FMX.

Why this blogpost? Because in the last weeks there are so many questions in forums or FB about this topic.

But where to start?

Do you want to go 2D? 


Great simple answer:

1.) Use a TRectangle with a PNG for your sprite(s).
2.) Use a Timer with 16ms for your game-loop.

Go and write - like me in 2015 - funny games like this:



Perhaps sometime in the future, I will release this game, if I find the time and change the stolen ROM-Images with new creations. ;-)

Do you want 3D? 


Then you might want to use a "3D Engine". Why an engine, because you do not want to do the hard work for all platforms by hand. Or you just use FMX as your engine.

This could look like this:

  1. Create a new FMX 3D application.
  2. Put a dummy object on the form
  3. Put a camera on the form
  4. Put a light on the form
  5. Place the camera at 0,0,-20
  6. Set the light to Point
  7. Place the light at 0,0,-20
  8. Put a Timer on the form and set it to 16ms
  9. In the onTimer event call Invalidate;
  10. In the onRender event call your 3D stuff.
The Form should look like this:


type
  THello3DWorld = class(TForm3D)
    Dummy1: TDummy;
    Camera1: TCamera;
    Timer1: TTimer;
    Light1: TLight;
    procedure Timer1Timer(Sender: TObject);
    procedure Form3DCreate(Sender: TObject);
    procedure Form3DDestroy(Sender: TObject);
    procedure Form3DRender(Sender: TObject; Context: TContext3D);
  private
    { Private-Deklarationen }
    fColorMaterial : TColorMaterial;
    fModelMatrix,
    fRotate        : TMatrix3D;
    fVertexBuffer  : TVertexBuffer;
    fIndexBuffer   : TIndexBuffer;
    Procedure DoInit;
    Procedure DoRotate;
  public
    { Public-Deklarationen }
  end;

In the FormCreate you can create, like in the example - a 3D object. I use a simple Triangle, but you can, of course, create any 3D Mesh or object. You also have to create Material. You can use your own Material (shader) or use the build-in.

This looks like this:

procedure THello3DWorld.Form3DCreate(Sender: TObject);
begin
  fColorMaterial := TColorMaterial.Create;
  fModelMatrix   := TMatrix3D.Identity;

  // 3 for a Triangle 
  fVertexBuffer := TVertexBuffer.Create([TVertexFormat.Vertex],3);
  fIndexBuffer  := TIndexBuffer.Create(3,TIndexFormat.UInt16);

  DoInit;
  Timer1.Enabled := true;
end;

In the DoInit, I setup a triangle for this little demo:

procedure THello3DWorld.DoInit;
var
  lVector : TVector3D;
  lMatrix : TMatrix3D;
begin
  // Create a Rotation Matrix for a equilateral triangle
  lMatrix := TMatrix3D.CreateRotationZ(120*Pi/180);
  LVector := TVector3D.Create(3,0,0); // Size 3

  fVertexBuffer.Vertices[0] := LVector;

  LVector := LVector * LMatrix; // Rotate to next point

  fVertexBuffer.Vertices[1] := LVector;

  LVector := LVector * LMatrix; // Rotate to next point

  fVertexBuffer.Vertices[2] := LVector;

  // Draw Clockwise
  fIndexBuffer.Indices[0]   := 0;
  fIndexBuffer.Indices[1]   := 1;
  fIndexBuffer.Indices[2]   := 2;

  // Create Rotation Matrix for later use 
  fRotate := TMatrix3D.CreateRotationZ(3*Pi/180);
end;

In the on Form3DRender event you can provide all your generated objects to the renderer.

procedure THello3DWorld.Form3DRender(Sender: TObject; Context: TContext3D);
begin
  if ( Context = nil ) or not( Context.BeginScene ) then
    exit;

  try
    Context.SetContextState( TContextState.cs3DScene );
    Context.Clear( TAlphaColorRec.Black ); // or any Color

    // Set ModelMatrix
    Context.SetMatrix( fModelmatrix );

    fColorMaterial.Color := TAlphaColorRec.Yellow;

    // Render Model
    Context.DrawTriangles( fVertexBuffer, fIndexBuffer,
                                          fColorMaterial, 1 );
  finally
    Context.EndScene;
  end;
end;

That's it. Now your FMX program could render any 3D object to the scene.

For entertainment, the object should rotate or do whatever you like. That's why this demo has a DoRotate method.

procedure THello3DWorld.DoRotate;
begin
  fModelMatrix := fModelMatrix * fRotate;
end;

This is a simple Matrix3D rotation. To use this rotation just call DoRotate before you call the invalidate. Normally you would measure the time difference between two frames and do the calculation for this deltaT to get even rotation speeds on all platform / CPUs. But with our timer we are fine for this demo.




With a collection of elements and some logic you can build your own 3D Engine and create some nice 3D stuff or games.





If you like to see more 3D Stuff write me a message.



Saturday, February 9, 2019

The lovely Microsoft hotline...

A very good hotline is the most important part of a software company (if you really on customer satisfaction).

I update my Mainboard, CPU, RAM. Everything was ok...

After that I copied my VM from a single M.2 to a Raid-Stripe-Set of M.2's.

A suddenly: Office wants activation a Windows, too

First, try on the Microsoft Hotline. A very grumpy man: Your Windows Key is not Valid ( I've used this key since upgraded from Windows 8 ). You have to buy a new Key.  Have a nice day. Tuuuuuut. He just hangs up.

Second try: A not so grumpy man - more helpfully - No problem Sir, please gibe my the 8 Digits from these 8 groups. Two tries. and then the same answer: You have to buy a new Key. Have a good day. By By.

And now - Windows wants a new key and office, too

Amazon: New Windows Key for 1,48€ -  yes under 2€ - the hotline cost was higher!
Windows working.

eBay: New Office Key for 7,25€ - upgraded my office from 2016 to 2019... Nice, now everything is working.

Monday, December 3, 2018

{$IFDEF Version Problem

Inspired by Thomas Mueller (dummzeuch) here is a repost of my ifdef version maintained since 2015.

Since Day one of my FDK I had the same problem: How to maintain the distribution with different Delphi versions.

The reason for writing my FDK is/was a better and faster development of iOS and Android apps, but after a short, while it became more and more like a Swiss-knife for my daily work.

Since XE 2 all my new Programs are written with FMX and since 2015 I've used it every day for developing my Windows Programs, too.

So here is my version of the {$I Versions.inc}

unit Delphi.VersionConsts;

// =====>     FFFFFF  DDDDD   K    K    FireMonkey Development Kit
// ====>     F       D    D  K  KK        (c) F. Lauter   aka Mavarik
// ===>     FFFF    D    D  KKK               O. Münzberg aka Sir Rufo
// ==>     F       D    D  K  KK
// =>     F       DDDDD   K    K        Version 2015, 2016, 2017, 2018

{******************************************************************************
 * Changes:
 * 01.10.15 Everybody should use this Unit - I hate the $I Version.inc files
 *          I hope that someday EMBT will always provide this Unit with every
 *          new Version.
 ******************************************************************************}

interface

{$IF Declared(CompilerVersion)}
{$ELSE}
const
  CompilerVersion = 0.0;
{$ENDIF}

const
  CompilerVersion_RIO     = 33.0;
  CompilerVersion_TOKYO   = 32.0;
  CompilerVersion_BERLIN  = 31.0;
  CompilerVersion_SEATTLE = 30.0;
  CompilerVersion_XE8     = 29.0;
  CompilerVersion_XE7     = 28.0;
  CompilerVersion_XE6     = 27.0;
  CompilerVersion_XE5     = 26.0;
  CompilerVersion_XE4     = 25.0;
  CompilerVersion_XE3     = 24.0;
  CompilerVersion_XE2     = 23.0;
  CompilerVersion_XE      = 22.0;
  CompilerVersion_2010    = 21.0;
  CompilerVersion_2009    = 20.0;
  CompilerVersion_2007    = 18.5;
  CompilerVersion_2006    = 18.0;
  CompilerVersion_2005    = 17.0;
  CompilerVersion_8_NET   = 16.0;
  CompilerVersion_7       = 15.0;
  CompilerVersion_6_2     = 14.2;
  CompilerVersion_6_1     = 14.1;
  CompilerVersion_6       = 14.0;

const
  Compiler_RIO     = CompilerVersion = CompilerVersion_RIO;   // Carnival
  Compiler_TOKYO   = CompilerVersion = CompilerVersion_TOKYO; // Godzilla
  Compiler_BERLIN  = CompilerVersion = CompilerVersion_BERLIN;
  Compiler_SEATTLE = CompilerVersion = CompilerVersion_SEATTLE;
  Compiler_XE8     = CompilerVersion = CompilerVersion_XE8;
  Compiler_XE7     = CompilerVersion = CompilerVersion_XE7;
  Compiler_XE6     = CompilerVersion = CompilerVersion_XE6;
  Compiler_XE5     = CompilerVersion = CompilerVersion_XE5;
  Compiler_XE4     = CompilerVersion = CompilerVersion_XE4;
  Compiler_XE3     = CompilerVersion = CompilerVersion_XE3;
  Compiler_XE2     = CompilerVersion = CompilerVersion_XE2;
  Compiler_XE      = CompilerVersion = CompilerVersion_XE;
  Compiler_2010    = CompilerVersion = CompilerVersion_2010;
  Compiler_2009    = CompilerVersion = CompilerVersion_2009;
  Compiler_2007    = CompilerVersion = CompilerVersion_2007;
  Compiler_2006    = CompilerVersion = CompilerVersion_2006;
  Compiler_2005    = CompilerVersion = CompilerVersion_2005;
  Compiler_8_NET   = CompilerVersion = CompilerVersion_8_NET;
  Compiler_7       = CompilerVersion = CompilerVersion_7;
  Compiler_6_2     = CompilerVersion = CompilerVersion_6_2;
  Compiler_6_1     = CompilerVersion = CompilerVersion_6_1;
  Compiler_6       = CompilerVersion = CompilerVersion_6;

const
  {$IF Compiler_RIO}    PackageVersion = '260';StudioVersion = '20.0'; {$ENDIF} 
  {$IF Compiler_TOKYO}  PackageVersion = '250';StudioVersion = '19.0'; {$ENDIF} 
  {$IF Compiler_BERLIN} PackageVersion = '240';StudioVersion = '18.0'; {$ENDIF}
  {$IF Compiler_SEATTLE}PackageVersion = '230';StudioVersion = '17.0'; {$ENDIF}
  {$IF Compiler_XE8}    PackageVersion = '220';StudioVersion = '16.0'; {$ENDIF}
  {$IF Compiler_XE7}    PackageVersion = '210';StudioVersion = '15.0'; {$ENDIF}
  {$IF Compiler_XE6}    PackageVersion = '200';StudioVersion = '14.0'; {$ENDIF}
  {$IF Compiler_XE5}    PackageVersion = '190';StudioVersion = '13.0'; {$ENDIF}
  {$IF Compiler_XE4}    PackageVersion = '180';StudioVersion = '12.0'; {$ENDIF}
  {$IF Compiler_XE3}    PackageVersion = '170';StudioVersion = '11.0'; {$ENDIF}
  {$IF Compiler_XE2}    PackageVersion = '160';StudioVersion = '10.0'; {$ENDIF}
  {$IF Compiler_XE}     PackageVersion = '150';StudioVersion = '9.0'; {$ENDIF}
  {$IF Compiler_2010}   PackageVersion = '140';StudioVersion = '8.0'; {$ENDIF}
  {$IF Compiler_2009}   PackageVersion = '120';StudioVersion = '7.0'; {$ENDIF}
  {$IF Compiler_2007}   PackageVersion = '110';StudioVersion = '6.0'; {$ENDIF}
  {$IF Compiler_2006}   PackageVersion = '100';StudioVersion = '5.0'; {$ENDIF}
  {$IF Compiler_2005}   PackageVersion =  '90';StudioVersion = '4.0'; {$ENDIF}
  {$IF Compiler_8_NET}  PackageVersion =  '80';StudioVersion = '3.0'; {$ENDIF}
  {$IF Compiler_7}      PackageVersion =  '70';StudioVersion = '2.0'; {$ENDIF}
  {$IF Compiler_6_2}    PackageVersion =  '60';StudioVersion = '1.2'; {$ENDIF}
  {$IF Compiler_6_1}    PackageVersion =  '60';StudioVersion = '1.1'; {$ENDIF}
  {$IF Compiler_6}      PackageVersion =  '60';StudioVersion = '1.0'; {$ENDIF}

type
  TDelphiVersion = Record
                     Name          : String;
                     StudioVersion : String;
                   end;

const
  TDelphiVersions : array[0..6] of TDelphiVersion  = ((Name:'Delphi XE6';StudioVersion:'14.0'),
                                                      (Name:'Delphi XE7';StudioVersion:'15.0'),
                                                      (Name:'Delphi XE8';StudioVersion:'16.0'),
                                                      (Name:'Delphi 10 Seattle';StudioVersion:'17.0'),
                                                      (Name:'Delphi 10.1 Berlin';StudioVersion:'18.0'),
                                                      (Name:'Delphi 10.2 Tokyo';StudioVersion:'19.0'),
                                                      (Name:'Delphi 10.3 Rio';StudioVersion:'20.0'));

const
  Compiler_RIO_UP     = CompilerVersion >= CompilerVersion_RIO;
  Compiler_TOKYO_UP   = CompilerVersion >= CompilerVersion_TOKYO;
  Compiler_BERLIN_UP  = CompilerVersion >= CompilerVersion_BERLIN;
  Compiler_SEATTLE_UP = CompilerVersion >= CompilerVersion_SEATTLE;
  Compiler_XE8_UP     = CompilerVersion >= CompilerVersion_XE8;
  Compiler_XE7_UP     = CompilerVersion >= CompilerVersion_XE7;
  Compiler_XE6_UP     = CompilerVersion >= CompilerVersion_XE6;
  Compiler_XE5_UP     = CompilerVersion >= CompilerVersion_XE5;
  Compiler_XE4_UP     = CompilerVersion >= CompilerVersion_XE4;
  Compiler_XE3_UP     = CompilerVersion >= CompilerVersion_XE3;
  Compiler_XE2_UP     = CompilerVersion >= CompilerVersion_XE2;
  Compiler_XE_UP      = CompilerVersion >= CompilerVersion_XE;
  Compiler_2010_UP    = CompilerVersion >= CompilerVersion_2010;
  Compiler_2009_UP    = CompilerVersion >= CompilerVersion_2009;
  Compiler_2007_UP    = CompilerVersion >= CompilerVersion_2007;
  Compiler_2006_UP    = CompilerVersion >= CompilerVersion_2006;
  Compiler_2005_UP    = CompilerVersion >= CompilerVersion_2005;
  Compiler_8_NET_UP   = CompilerVersion >= CompilerVersion_8_NET;
  Compiler_7_UP       = CompilerVersion >= CompilerVersion_7;
  Compiler_6_2_UP     = CompilerVersion >= CompilerVersion_6_2;
  Compiler_6_1_UP     = CompilerVersion >= CompilerVersion_6_1;
  Compiler_6_UP       = CompilerVersion >= CompilerVersion_6;

  Compiler_RIO_DOWN     = CompilerVersion <= CompilerVersion_RIO;
  Compiler_TOKYO_DOWN   = CompilerVersion <= CompilerVersion_TOKYO;
  Compiler_BERLIN_DOWN  = CompilerVersion <= CompilerVersion_BERLIN;
  Compiler_SEATTLE_DOWN = CompilerVersion <= CompilerVersion_SEATTLE;
  Compiler_XE8_DOWN     = CompilerVersion <= CompilerVersion_XE8;
  Compiler_XE7_DOWN     = CompilerVersion <= CompilerVersion_XE7;
  Compiler_XE6_DOWN     = CompilerVersion <= CompilerVersion_XE6;
  Compiler_XE5_DOWN     = CompilerVersion <= CompilerVersion_XE5;
  Compiler_XE4_DOWN     = CompilerVersion <= CompilerVersion_XE4;
  Compiler_XE3_DOWN     = CompilerVersion <= CompilerVersion_XE3;
  Compiler_XE2_DOWN     = CompilerVersion <= CompilerVersion_XE2;
  Compiler_XE_DOWN      = CompilerVersion <= CompilerVersion_XE;
  Compiler_2010_DOWN    = CompilerVersion <= CompilerVersion_2010;
  Compiler_2009_DOWN    = CompilerVersion <= CompilerVersion_2009;
  Compiler_2007_DOWN    = CompilerVersion <= CompilerVersion_2007;
  Compiler_2006_DOWN    = CompilerVersion <= CompilerVersion_2006;
  Compiler_2005_DOWN    = CompilerVersion <= CompilerVersion_2005;
  Compiler_8_NET_DOWN   = CompilerVersion <= CompilerVersion_8_NET;
  Compiler_7_DOWN       = CompilerVersion <= CompilerVersion_7;
  Compiler_6_2_DOWN     = CompilerVersion <= CompilerVersion_6_2;
  Compiler_6_1_DOWN     = CompilerVersion <= CompilerVersion_6_1;
  Compiler_6_DOWN       = CompilerVersion <= CompilerVersion_6;

{$IF DEFINED( IOS ) or DEFINED(ANDROID)}

type
   Compiler = class sealed
     public
       Const
         HasArc      = true;
   end;

const
  CompilerIsMobil     = true;

  PlattFormOSX        = false;
  SupportsAnsiStrings = false; //Compiler_BERLIN_UP;
{$DEFINE CompilerIsMobil}

{$ELSE}
type
   Compiler = class sealed
     public
       Const
         HasArc      = false;
   end;

const
{$IFDEF MACOS}
  PlattFormOSX        = true;
{$ENDIF}

{$REGION 'Documentation'}
  /// <summary>
  ///   true if target ist iOS or Android
  /// </summary>
{$ENDREGION}
  CompilerIsMobil     = false;
  SupportsAnsiStrings = true;
{$ENDIF}

implementation

end.