Recent

Author Topic: Modern UI in Lazarus  (Read 190287 times)

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Modern UI in Lazarus
« Reply #195 on: November 24, 2019, 11:54:51 am »
I wouldn't call subpixel calculation of DeltaX and DeltaY for coloring pixels in integer based coordinating system a complex math. 
That is also a form of oversampling. That was my point.
Specialize a type, not a var.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11382
  • FPC developer.
Re: Modern UI in Lazarus
« Reply #196 on: November 24, 2019, 12:03:41 pm »
Really cool stuff. Looks really good!

lainz

  • Hero Member
  • *****
  • Posts: 4460
    • https://lainz.github.io/
Re: Modern UI in Lazarus
« Reply #197 on: November 24, 2019, 01:39:58 pm »
I would like to combine LCL with CSS in many cases:

...

5. As Helper for custom Controls
   For example I would like to create TButton with Top text, left Icon, right icon and etc. I can create classic control with "css inside"
Code: Pascal  [Select][+][-]
  1.    TMyCoolButton = class(TCustomButton)
  2.    private
  3.      Froot,
  4.      FLeftIcon,
  5.      FRightIcon, FTopText: THtmlNode;
  6.   ...
  7.      procedure CalculatePrefferedSize ( .... )
  8.      begin
  9.        Froot.LayouTo(AWidth, AHeight);
  10.      end;
  11.      procedure Paint ( .... ); override;
  12.      begin
  13.        Froot.PaintTo(Self.Canvas, ClientRect);
  14.      end;
  15.     procedure SetIconColor(AValue: TColor);
  16.     begin
  17.       FLeftIcon.InlineStyle := 'color:#' + LCLToHtml(AValue);
  18.       FRoot.Changed;
  19.     end;
  20.  
  21.   published
  22.     property TopText: String read ... write ;
  23.     property LeftIconColor: TColor read write ;

Cool. I like the idea of custom controls with this. So we can have regular controls that can be placed directly on the form without code.

Is not hard to create checkbox, radiobutton, combobox (we created these for bgracontrols too) with styles, but with CSS will be another story.

Edit: Is not hard to put it at github (at any stage, I put things that are simply toy applications so what's the problem  :D ), so I don't need to patch my installation and can do a fetch to get the latest version, please  :)
« Last Edit: November 24, 2019, 02:03:33 pm by lainz »

ps

  • Full Member
  • ***
  • Posts: 136
    • CSS
Re: Modern UI in Lazarus
« Reply #198 on: November 30, 2019, 01:08:28 pm »
Cool. I like the idea of custom controls with this. So we can have regular controls that can be placed directly on the form without code.
Is not hard to create checkbox, radiobutton, combobox (we created these for bgracontrols too) with styles, but with CSS will be another story.
Edit: Is not hard to put it at github (at any stage, I put things that are simply toy applications so what's the problem  :D ), so I don't need to patch my installation and can do a fetch to get the latest version, please  :)
Yes. I have many complex controls like more buttons "inside", hover links etc. and when I would like to change something it's ...

ok. github will be shortly. I have some progress with borders (without antialiasing). It was really hard for me to do this and have correct css corners (too many math for me :) ).
Small simple CSS/box model implementation: https://github.com/pst2d/csscontrols/tree/dev

gii

  • Jr. Member
  • **
  • Posts: 53
Re: Modern UI in Lazarus
« Reply #199 on: November 30, 2019, 02:21:20 pm »
Do you have plans to support other components like TEdit, TComboBox and TDBGrid?

ps

  • Full Member
  • ***
  • Posts: 136
    • CSS
Re: Modern UI in Lazarus
« Reply #200 on: November 30, 2019, 09:26:38 pm »
you can create any control with easy. For example TEdit with icon, help text and rounded corners :)

Code: Pascal  [Select][+][-]
  1.   { TCSSEdit }
  2.  
  3.   TCSSEdit = class(TCSSShape)
  4.   private
  5.     FEdit: TEdit;
  6.   protected
  7.     procedure SetParent(NewParent: TWinControl); override;
  8.   public
  9.     constructor Create(AOwner: TComponent); override;
  10.   end;  

and implementation:

Code: Pascal  [Select][+][-]
  1. procedure TCSSEdit.SetParent(NewParent: TWinControl);
  2. begin
  3.   inherited SetParent(NewParent);
  4.   if Assigned(NewParent) then FEdit.Parent := NewParent;
  5. end;
  6.  
  7. constructor TCSSEdit.Create(AOwner: TComponent);
  8. begin
  9.   inherited Create(AOwner);
  10.   FEdit := TEdit.Create(Self);
  11.   FEdit.BorderStyle := bsNone;  // remove native UI frame
  12.   Body.InlineStyle := 'padding:10px;margin:10px; border:3px solid #0060DF;border-radius:10px; background-color:white;'; // create border 3px outter margin 10px and inner padding 10px
  13.   Body.AddNode( HTMLFa('', 'f002'));  // nice search icon
  14.   Body.AddNode( HTMLSpan('margin-left:10px;', 'Search here:'));   // move text 10px away from icon
  15.   Body.AddNode( HTMLDiv('padding-top:5px;', '').SetAlignControl(FEdit)); // make space 5 px from search "text" and place our TEdit.
  16. end;      

That's all (yes we can override focus) :)
« Last Edit: November 30, 2019, 09:40:30 pm by ps »
Small simple CSS/box model implementation: https://github.com/pst2d/csscontrols/tree/dev

gii

  • Jr. Member
  • **
  • Posts: 53
Re: Modern UI in Lazarus
« Reply #201 on: November 30, 2019, 10:25:06 pm »
you can create any control with easy. For example TEdit with icon, help text and rounded corners :)

Code: Pascal  [Select][+][-]
  1.   { TCSSEdit }
  2.  
  3.   TCSSEdit = class(TCSSShape)
  4.   private
  5.     FEdit: TEdit;
  6.   protected
  7.     procedure SetParent(NewParent: TWinControl); override;
  8.   public
  9.     constructor Create(AOwner: TComponent); override;
  10.   end;  

and implementation:

Code: Pascal  [Select][+][-]
  1. procedure TCSSEdit.SetParent(NewParent: TWinControl);
  2. begin
  3.   inherited SetParent(NewParent);
  4.   if Assigned(NewParent) then FEdit.Parent := NewParent;
  5. end;
  6.  
  7. constructor TCSSEdit.Create(AOwner: TComponent);
  8. begin
  9.   inherited Create(AOwner);
  10.   FEdit := TEdit.Create(Self);
  11.   FEdit.BorderStyle := bsNone;  // remove native UI frame
  12.   Body.InlineStyle := 'padding:10px;margin:10px; border:3px solid #0060DF;border-radius:10px; background-color:white;'; // create border 3px outter margin 10px and inner padding 10px
  13.   Body.AddNode( HTMLFa('', 'f002'));  // nice search icon
  14.   Body.AddNode( HTMLSpan('margin-left:10px;', 'Search here:'));   // move text 10px away from icon
  15.   Body.AddNode( HTMLDiv('padding-top:5px;', '').SetAlignControl(FEdit)); // make space 5 px from search "text" and place our TEdit.
  16. end;      

That's all (yes we can override focus) :)

Amazing!

Got any predictions for the official release?

RazorGrass

  • Newbie
  • Posts: 2
Re: Modern UI in Lazarus
« Reply #202 on: December 07, 2019, 03:21:11 pm »
Hi ps,
Any update on the GitHub? Or, how can one download this and start to learn/use it?

RazorGrass

ps

  • Full Member
  • ***
  • Posts: 136
    • CSS
Re: Modern UI in Lazarus
« Reply #203 on: December 09, 2019, 12:38:27 pm »
This is only work in progress version. I would like to have some basic features before official release. I can place unstable version here if is needed ...

Here is some example of progress with "display:flex" support. As you can see text-align is needed to make it beautiful.

Code: Pascal  [Select][+][-]
  1.  
  2. { TCSSCalendar }
  3.  TCSSCalendar = class(TCSSShape)
  4.   private
  5.     FActiveMonth,
  6.     FActiveDay: TDateTime;
  7.     procedure Changed;
  8.     procedure GoNextMonth(Sender: TObject);
  9.     procedure GoPrevMonth(Sender: TObject);
  10.   public
  11.     constructor Create(AOwner: TComponent); override;
  12.   end;
 
and full source:
Code: Pascal  [Select][+][-]
  1. procedure TCSSCalendar.Changed;
  2. var
  3.   Node: THtmlNode;
  4.   I, X: Integer;
  5.   DayLoop,
  6.   FirstDay: TDateTime;
  7.   W,
  8.   AYear, AMonth, ADay,
  9.   Year, Month, Day: Word;
  10.   Style: String;
  11.   fs: TFormatSettings;
  12. begin
  13.   // date time calculations
  14.   DecodeDate(FActiveDay, AYear, AMonth, ADay);
  15.   FirstDay := EncodeDate(AYear, AMonth, 1);
  16.   FirstDay := IncDay(FirstDay, - DayOfWeek(FirstDay) +1);
  17.   w := WeekOfTheYear(FirstDay);
  18.   fs := DefaultFormatSettings;
  19.  
  20.   // build top navigation section:  Month Year  < >
  21.   Body.InlineStyle := 'width:400px; background-color: white;margin:10px;padding:5px;';
  22.   Body.Clear;
  23.   Node := HTMLDiv('display:flex;color:#808080;', '');
  24.   Node.AddNode( HTMLDiv('flex-grow:1;padding:5px;')
  25.     .AddNode( HTMLSpan('font:18px;font-weight:bold;color:black;', fs.LongMonthNames[AMonth] ))
  26.     .AddNode( HTMLSpan('font:18px;color:#F0403C;margin-left:5px;', AYear.ToString))
  27.     );
  28.   Node.AddNode( HTMLFa('font:12px;padding:5px;cursor:pointer;', 'f053').SetOnClick(@GoPrevMonth).SetHover('color:#2AAEF5;'));               // prev month button
  29.   Node.AddNode( HTMLFa('font:12px;padding:5px;cursor:pointer;', 'f054').SetOnClick(@GoNextMonth).SetHover('color:#2AAEF5;'));               // next month button
  30.   Body.AddNode(Node);
  31.  
  32.   // build day names header
  33.   Node := HTMLDiv('display:flex;font-weight:bold;color:#999999;', '');
  34.   Node.AddNode( HTMLSpan('width:50px;', 'CW'));
  35.   for X := 0 to 6 do
  36.     Node.AddNode( HTMLSpan('flex-grow:1;margin:2px auto;', AnsiUpperCase(fs.ShortDayNames[DayOfWeek( IncDay(FirstDay,X))])));
  37.   Body.AddNode(Node);
  38.  
  39.   DayLoop := FirstDay;
  40.   // build week rows
  41.   for I := 0 to 5 do begin
  42.     Node := HTMLDiv('display:flex;', '').SetHover('background-color:#F2F2F2;border-radius:8px;color:#2AAEF5;');
  43.     Node.AddNode( HTMLSpan('width:30px;color:#999999;font-weight:bold;padding:5px;margin-right:5px;border-right:2px solid #E5E5E5;', (w + I).ToString));
  44.     // build days in columns
  45.     for X := 0 to 6 do begin
  46.       DecodeDate(DayLoop, Year, Month, Day);
  47.       Style := 'font:13px;color:black;flex-grow:1;';
  48.       if Month <> AMonth then Style := Style + 'color:#E5E5E5;';     // make days from different month less visible
  49.       Node.AddNode( HTMLSpan(Style, AddChar('0',(Day).ToString, 2)).SetHover('background-color:#2AAEF5;color:white;border-radius:5px;cursor:pointer;'));
  50.       DayLoop := IncDay(DayLoop);
  51.     end;
  52.     Body.AddNode(Node);
  53.   end;
  54.   InvalidatePreferredSize;
  55.   AdjustSize;
  56.   Invalidate;
  57. end;
  58.  
  59. procedure TCSSCalendar.GoNextMonth(Sender: TObject);
  60. begin
  61.   FActiveDay := IncMonth(FActiveDay, 1);
  62.   Changed;
  63. end;
  64.  
  65. procedure TCSSCalendar.GoPrevMonth(Sender: TObject);
  66. begin
  67.   FActiveDay := IncMonth(FActiveDay, -1);
  68.   Changed;
  69. end;  
  70.  
  71. constructor TCSSCalendar.Create(AOwner: TComponent);
  72. begin
  73.   inherited Create(AOwner);
  74.   FActiveDay := Now;
  75.   FActiveMonth := Now;
  76.   Changed;
  77. end;  
  78.    
Small simple CSS/box model implementation: https://github.com/pst2d/csscontrols/tree/dev

ps

  • Full Member
  • ***
  • Posts: 136
    • CSS
Re: Modern UI in Lazarus
« Reply #204 on: December 12, 2019, 05:33:45 pm »
My friends I'm completely lost ...

It's really hard to fight with bugs in LCL and nobody cares  :'( . Maybe it's time to move project to Delphi/FMX? Or can somebody  fix few bugs for me? :)

https://bugs.freepascal.org/view.php?id=36186
https://bugs.freepascal.org/view.php?id=32934
https://bugs.freepascal.org/view.php?id=36187
https://bugs.freepascal.org/view.php?id=34829
https://bugs.freepascal.org/view.php?id=36423
https://bugs.freepascal.org/view.php?id=36286

BTW I have next little progress with lot of bugs fixed. Next step will be border-shadow and it will be done for first release.
In attachments there is little "more desktop like"  example with component TCSSCalendar (yes this calendar compoment have 150 lines of code).

It's easy to create complex controls and side effect we can "style" it :) (or change behavior)

Small simple CSS/box model implementation: https://github.com/pst2d/csscontrols/tree/dev

garlar27

  • Hero Member
  • *****
  • Posts: 652
Re: Modern UI in Lazarus
« Reply #205 on: December 12, 2019, 06:34:45 pm »
I can help you only with control layout change (32934, 36187). To avoid that sort of problems, I use the anchor properties (the anchor editor or by code).

FTurtle

  • Sr. Member
  • ****
  • Posts: 292
Re: Modern UI in Lazarus
« Reply #206 on: December 12, 2019, 07:55:58 pm »
« Last Edit: December 12, 2019, 08:05:08 pm by FTurtle »

ps

  • Full Member
  • ***
  • Posts: 136
    • CSS
Re: Modern UI in Lazarus
« Reply #207 on: December 15, 2019, 10:32:33 pm »
Thank's guys. Borderspacing is "removed" with margin (we don't need to use it). But it's bug for LCL. My initial idea was to set borderspacing with CSS, this is impossible due bug. But this 3 bugs is most important for me (it's possible contact Lazarus devs?):  ;)
https://bugs.freepascal.org/view.php?id=36423 (this is huge performance impact for all controls in LCL)
https://bugs.freepascal.org/view.php?id=36286 (maybe I can found another solution, but how?)
https://bugs.freepascal.org/view.php?id=34829 (this is nearly show stopper for Cocoa apps :( )

But I have some GOOD news :). Now we have better renderer than Chrome! (or I have luck for finding bugs :) ).

PS: delphihtmlcomponents.com demo editor was used to test (maybe viewer have better results, I don't have this lib).
Code: Text  [Select][+][-]
  1. <html lang=en>
  2.  <body>
  3. <div style="display:inline-block;background-color:#5B6DCD;border:35px solid green; border-top:15px solid red;border-bottom:5px solid red;margin:30px;padding:30px;border-radius:10px 15px 20px 125px;">
  4.   <div style="display:inline-block;background-color:red;color:white;border:3px solid white;padding:20px;margin:30px;">Hi there!</div>
  5.   <div style="display:inline-block;background-color:blue;color:white;border:3px solid white;padding:20px;margin:10px auto;width:10%;text-align:center;">10%</div>
  6.   <div style="display:inline-block;background-color:red;color:white;border:3px solid white;padding:20px;margin:30px;">Hi there!</div>
  7.   <div style="display:block;background-color:blue;color:white;border:3px solid white;padding:20px;margin:10px auto; width:50%;"><div style="display:block;border:3px solid red;padding:30px;">i'm inside</div><div style="display:inline-block;border:3px solid olive;padding:10px;">me too</div><div style="display:inline-block;border:13px solid white;padding:20px;border-bottom-right-radius:100px 60px;border-top:12px solid red;border-right:1px solid white;">me too</div></div>
  8.   <div style="display:inline-block;background-color:red;color:white;border:3px solid white;padding:20px;margin:30px;">Hi there!</div>
  9.   <div style="display:inline-block;background-color:red;color:white;border:3px solid white;padding:30px;margin:30px;border-top-right-radius:30px 60px;border-right:15px solid gray;">Hi there!</div>
  10.   <div style="display:inline-block;background-color:red;color:white;border:3px solid white;padding:20px;margin:30px;">Hi there!</div>
  11. </div>
  12.  
  13. <h1>test</h1>
  14. </body>
  15. </html>
Small simple CSS/box model implementation: https://github.com/pst2d/csscontrols/tree/dev

lainz

  • Hero Member
  • *****
  • Posts: 4460
    • https://lainz.github.io/
Re: Modern UI in Lazarus
« Reply #208 on: December 15, 2019, 11:08:59 pm »
Congratulations, this is the missing component in Lazarus  :)

ps

  • Full Member
  • ***
  • Posts: 136
    • CSS
Re: Modern UI in Lazarus
« Reply #209 on: December 18, 2019, 08:48:05 pm »
Congratulations, this is the missing component in Lazarus  :)
It's far away from perfect. But good for start :). Firefox have 15 000 lines of code only for borders. My little lib is whole 2.500 :).
Now I can say I hate CSS, why we can set width in percentage for children based on future width of parent(calculated from childrens) ??? ... 

Source code is here: https://github.com/pst2d/csscontrols. Test app is in attachment. It will be fine if someone can test it under different platforms (Cocoa/Linux/Raspberry Pi ...). Thanks' all.

Next step will be basic documentation and vacation :)
Small simple CSS/box model implementation: https://github.com/pst2d/csscontrols/tree/dev

 

TinyPortal © 2005-2018