Browse Source

design: added inline CSS style property editor

mattias 2 years ago
parent
commit
76b78ea0dd

+ 45 - 3
design/fresnel.register.pas

@@ -8,7 +8,7 @@
  for details about the license.
 *****************************************************************************
 }
-unit fresnel.register;
+unit Fresnel.Register;
 
 {$mode objfpc}{$H+}
 
@@ -17,7 +17,7 @@ interface
 uses
   LCLProc, LCLType, Classes, SysUtils, FormEditingIntf, PropEdits, LCLIntf,
   Graphics, Controls, Forms, ProjectIntf, LazLoggerBase, Fresnel.DOM,
-  Fresnel.Controls, Fresnel.LCLControls;
+  Fresnel.Controls, Fresnel.LCLControls, Fresnel.StylePropEdit;
 
 type
 
@@ -68,6 +68,14 @@ type
     function GetLocalizedDescription: string; override;
   end;
 
+  { TFresnelStylePropertyEditor }
+
+  TFresnelStylePropertyEditor = class(TStringPropertyEditor)
+  public
+    function GetAttributes: TPropertyAttributes; override;
+    procedure Edit; override;
+  end;
+
 procedure Register;
 
 implementation
@@ -78,7 +86,8 @@ begin
   RegisterComponents('Fresnel',[TFresnelDiv,TFresnelSpan,TFresnelLabel,TFresnelBody]);
   RegisterProjectFileDescriptor(TFileDescPascalUnitWithFresnelForm.Create,
                                 FileDescGroupName);
-  RegisterPropertyEditor(TypeInfo(String), TFresnelForm, 'Style', THiddenPropertyEditor);
+
+  RegisterPropertyEditor(TypeInfo(String), TFresnelElement, 'Style', TFresnelStylePropertyEditor);
 end;
 
 { TFresnelFormMediator }
@@ -308,5 +317,38 @@ begin
   Result:='Create a new Fresnel form';
 end;
 
+{ TFresnelStylePropertyEditor }
+
+function TFresnelStylePropertyEditor.GetAttributes: TPropertyAttributes;
+begin
+  Result := [paMultiSelect, paDialog, paRevertable];
+end;
+
+procedure TFresnelStylePropertyEditor.Edit;
+var
+  TheDialog : TStylePropEditDialog;
+  AString : string;
+  LineEndPos: Integer;
+begin
+  AString := GetStrValue;
+  TheDialog := TStylePropEditDialog.Create(nil);
+  try
+    TheDialog.Editor := Self;
+    TheDialog.CSSSynEdit.Text := AString;
+    TheDialog.CSSSynEditChange(nil);
+    if (TheDialog.ShowModal = mrOK) then
+    begin
+      AString := TheDialog.CSSSynEdit.Text;
+      LineEndPos := Length(AString) - Length(LineEnding) + 1;
+      //erase the last lineending if any
+      if Copy(AString, LineEndPos, Length(LineEnding)) = LineEnding then
+        Delete(AString, LineEndPos, Length(LineEnding));
+      SetStrValue(AString);
+    end;
+  finally
+    TheDialog.Free;
+  end;
+end;
+
 end.
 

+ 625 - 0
design/fresnel.stylepropedit.lfm

@@ -0,0 +1,625 @@
+object StylePropEditDialog: TStylePropEditDialog
+  Left = 480
+  Height = 414
+  Top = 254
+  Width = 445
+  ActiveControl = CSSSynEdit
+  Caption = 'StylePropEditDialog'
+  ClientHeight = 414
+  ClientWidth = 445
+  Constraints.MinHeight = 160
+  Constraints.MinWidth = 180
+  OnClose = FormClose
+  OnCreate = FormCreate
+  Position = poScreenCenter
+  LCLVersion = '2.3.0.0'
+  object TextGroupBox: TGroupBox
+    AnchorSideLeft.Control = Owner
+    AnchorSideTop.Control = Owner
+    AnchorSideRight.Control = Owner
+    AnchorSideRight.Side = asrBottom
+    AnchorSideBottom.Control = BtnPanel
+    Left = 6
+    Height = 348
+    Top = 6
+    Width = 433
+    Align = alTop
+    Anchors = [akTop, akLeft, akRight, akBottom]
+    BorderSpacing.Around = 6
+    ClientHeight = 346
+    ClientWidth = 431
+    TabOrder = 0
+    object StatusLabel: TLabel
+      AnchorSideBottom.Control = TextGroupBox
+      AnchorSideBottom.Side = asrBottom
+      Left = 9
+      Height = 15
+      Top = 325
+      Width = 63
+      Anchors = [akLeft, akBottom]
+      BorderSpacing.Around = 6
+      Caption = 'StatusLabel'
+    end
+    inline CSSSynEdit: TSynEdit
+      AnchorSideLeft.Control = TextGroupBox
+      AnchorSideRight.Control = SortButton
+      AnchorSideBottom.Control = StatusLabel
+      Left = 6
+      Height = 319
+      Top = 0
+      Width = 338
+      BorderSpacing.Around = 6
+      Anchors = [akTop, akLeft, akRight, akBottom]
+      Font.Height = 13
+      Font.Name = 'DejaVu Sans Mono'
+      Font.Pitch = fpFixed
+      Font.Quality = fqNonAntialiased
+      ParentColor = False
+      ParentFont = False
+      TabOrder = 0
+      Gutter.Width = 57
+      Gutter.MouseActions = <>
+      RightGutter.Width = 0
+      RightGutter.MouseActions = <>
+      Highlighter = SynCssSyn1
+      Keystrokes = <      
+        item
+          Command = ecUp
+          ShortCut = 38
+        end      
+        item
+          Command = ecSelUp
+          ShortCut = 8230
+        end      
+        item
+          Command = ecScrollUp
+          ShortCut = 16422
+        end      
+        item
+          Command = ecDown
+          ShortCut = 40
+        end      
+        item
+          Command = ecSelDown
+          ShortCut = 8232
+        end      
+        item
+          Command = ecScrollDown
+          ShortCut = 16424
+        end      
+        item
+          Command = ecLeft
+          ShortCut = 37
+        end      
+        item
+          Command = ecSelLeft
+          ShortCut = 8229
+        end      
+        item
+          Command = ecWordLeft
+          ShortCut = 16421
+        end      
+        item
+          Command = ecSelWordLeft
+          ShortCut = 24613
+        end      
+        item
+          Command = ecRight
+          ShortCut = 39
+        end      
+        item
+          Command = ecSelRight
+          ShortCut = 8231
+        end      
+        item
+          Command = ecWordRight
+          ShortCut = 16423
+        end      
+        item
+          Command = ecSelWordRight
+          ShortCut = 24615
+        end      
+        item
+          Command = ecPageDown
+          ShortCut = 34
+        end      
+        item
+          Command = ecSelPageDown
+          ShortCut = 8226
+        end      
+        item
+          Command = ecPageBottom
+          ShortCut = 16418
+        end      
+        item
+          Command = ecSelPageBottom
+          ShortCut = 24610
+        end      
+        item
+          Command = ecPageUp
+          ShortCut = 33
+        end      
+        item
+          Command = ecSelPageUp
+          ShortCut = 8225
+        end      
+        item
+          Command = ecPageTop
+          ShortCut = 16417
+        end      
+        item
+          Command = ecSelPageTop
+          ShortCut = 24609
+        end      
+        item
+          Command = ecLineStart
+          ShortCut = 36
+        end      
+        item
+          Command = ecSelLineStart
+          ShortCut = 8228
+        end      
+        item
+          Command = ecEditorTop
+          ShortCut = 16420
+        end      
+        item
+          Command = ecSelEditorTop
+          ShortCut = 24612
+        end      
+        item
+          Command = ecLineEnd
+          ShortCut = 35
+        end      
+        item
+          Command = ecSelLineEnd
+          ShortCut = 8227
+        end      
+        item
+          Command = ecEditorBottom
+          ShortCut = 16419
+        end      
+        item
+          Command = ecSelEditorBottom
+          ShortCut = 24611
+        end      
+        item
+          Command = ecToggleMode
+          ShortCut = 45
+        end      
+        item
+          Command = ecCopy
+          ShortCut = 16429
+        end      
+        item
+          Command = ecPaste
+          ShortCut = 8237
+        end      
+        item
+          Command = ecDeleteChar
+          ShortCut = 46
+        end      
+        item
+          Command = ecCut
+          ShortCut = 8238
+        end      
+        item
+          Command = ecDeleteLastChar
+          ShortCut = 8
+        end      
+        item
+          Command = ecDeleteLastChar
+          ShortCut = 8200
+        end      
+        item
+          Command = ecDeleteLastWord
+          ShortCut = 16392
+        end      
+        item
+          Command = ecUndo
+          ShortCut = 32776
+        end      
+        item
+          Command = ecRedo
+          ShortCut = 40968
+        end      
+        item
+          Command = ecLineBreak
+          ShortCut = 13
+        end      
+        item
+          Command = ecSelectAll
+          ShortCut = 16449
+        end      
+        item
+          Command = ecCopy
+          ShortCut = 16451
+        end      
+        item
+          Command = ecBlockIndent
+          ShortCut = 24649
+        end      
+        item
+          Command = ecLineBreak
+          ShortCut = 16461
+        end      
+        item
+          Command = ecInsertLine
+          ShortCut = 16462
+        end      
+        item
+          Command = ecDeleteWord
+          ShortCut = 16468
+        end      
+        item
+          Command = ecBlockUnindent
+          ShortCut = 24661
+        end      
+        item
+          Command = ecPaste
+          ShortCut = 16470
+        end      
+        item
+          Command = ecCut
+          ShortCut = 16472
+        end      
+        item
+          Command = ecDeleteLine
+          ShortCut = 16473
+        end      
+        item
+          Command = ecDeleteEOL
+          ShortCut = 24665
+        end      
+        item
+          Command = ecUndo
+          ShortCut = 16474
+        end      
+        item
+          Command = ecRedo
+          ShortCut = 24666
+        end      
+        item
+          Command = ecGotoMarker0
+          ShortCut = 16432
+        end      
+        item
+          Command = ecGotoMarker1
+          ShortCut = 16433
+        end      
+        item
+          Command = ecGotoMarker2
+          ShortCut = 16434
+        end      
+        item
+          Command = ecGotoMarker3
+          ShortCut = 16435
+        end      
+        item
+          Command = ecGotoMarker4
+          ShortCut = 16436
+        end      
+        item
+          Command = ecGotoMarker5
+          ShortCut = 16437
+        end      
+        item
+          Command = ecGotoMarker6
+          ShortCut = 16438
+        end      
+        item
+          Command = ecGotoMarker7
+          ShortCut = 16439
+        end      
+        item
+          Command = ecGotoMarker8
+          ShortCut = 16440
+        end      
+        item
+          Command = ecGotoMarker9
+          ShortCut = 16441
+        end      
+        item
+          Command = ecSetMarker0
+          ShortCut = 24624
+        end      
+        item
+          Command = ecSetMarker1
+          ShortCut = 24625
+        end      
+        item
+          Command = ecSetMarker2
+          ShortCut = 24626
+        end      
+        item
+          Command = ecSetMarker3
+          ShortCut = 24627
+        end      
+        item
+          Command = ecSetMarker4
+          ShortCut = 24628
+        end      
+        item
+          Command = ecSetMarker5
+          ShortCut = 24629
+        end      
+        item
+          Command = ecSetMarker6
+          ShortCut = 24630
+        end      
+        item
+          Command = ecSetMarker7
+          ShortCut = 24631
+        end      
+        item
+          Command = ecSetMarker8
+          ShortCut = 24632
+        end      
+        item
+          Command = ecSetMarker9
+          ShortCut = 24633
+        end      
+        item
+          Command = EcFoldLevel1
+          ShortCut = 41009
+        end      
+        item
+          Command = EcFoldLevel2
+          ShortCut = 41010
+        end      
+        item
+          Command = EcFoldLevel3
+          ShortCut = 41011
+        end      
+        item
+          Command = EcFoldLevel4
+          ShortCut = 41012
+        end      
+        item
+          Command = EcFoldLevel5
+          ShortCut = 41013
+        end      
+        item
+          Command = EcFoldLevel6
+          ShortCut = 41014
+        end      
+        item
+          Command = EcFoldLevel7
+          ShortCut = 41015
+        end      
+        item
+          Command = EcFoldLevel8
+          ShortCut = 41016
+        end      
+        item
+          Command = EcFoldLevel9
+          ShortCut = 41017
+        end      
+        item
+          Command = EcFoldLevel0
+          ShortCut = 41008
+        end      
+        item
+          Command = EcFoldCurrent
+          ShortCut = 41005
+        end      
+        item
+          Command = EcUnFoldCurrent
+          ShortCut = 41003
+        end      
+        item
+          Command = EcToggleMarkupWord
+          ShortCut = 32845
+        end      
+        item
+          Command = ecNormalSelect
+          ShortCut = 24654
+        end      
+        item
+          Command = ecColumnSelect
+          ShortCut = 24643
+        end      
+        item
+          Command = ecLineSelect
+          ShortCut = 24652
+        end      
+        item
+          Command = ecTab
+          ShortCut = 9
+        end      
+        item
+          Command = ecShiftTab
+          ShortCut = 8201
+        end      
+        item
+          Command = ecMatchBracket
+          ShortCut = 24642
+        end      
+        item
+          Command = ecColSelUp
+          ShortCut = 40998
+        end      
+        item
+          Command = ecColSelDown
+          ShortCut = 41000
+        end      
+        item
+          Command = ecColSelLeft
+          ShortCut = 40997
+        end      
+        item
+          Command = ecColSelRight
+          ShortCut = 40999
+        end      
+        item
+          Command = ecColSelPageDown
+          ShortCut = 40994
+        end      
+        item
+          Command = ecColSelPageBottom
+          ShortCut = 57378
+        end      
+        item
+          Command = ecColSelPageUp
+          ShortCut = 40993
+        end      
+        item
+          Command = ecColSelPageTop
+          ShortCut = 57377
+        end      
+        item
+          Command = ecColSelLineStart
+          ShortCut = 40996
+        end      
+        item
+          Command = ecColSelLineEnd
+          ShortCut = 40995
+        end      
+        item
+          Command = ecColSelEditorTop
+          ShortCut = 57380
+        end      
+        item
+          Command = ecColSelEditorBottom
+          ShortCut = 57379
+        end>
+      MouseActions = <>
+      MouseTextActions = <>
+      MouseSelActions = <>
+      VisibleSpecialChars = [vscSpace, vscTabAtLast]
+      SelectedColor.BackPriority = 50
+      SelectedColor.ForePriority = 50
+      SelectedColor.FramePriority = 50
+      SelectedColor.BoldPriority = 50
+      SelectedColor.ItalicPriority = 50
+      SelectedColor.UnderlinePriority = 50
+      SelectedColor.StrikeOutPriority = 50
+      BracketHighlightStyle = sbhsBoth
+      BracketMatchColor.Background = clNone
+      BracketMatchColor.Foreground = clNone
+      BracketMatchColor.Style = [fsBold]
+      FoldedCodeColor.Background = clNone
+      FoldedCodeColor.Foreground = clGray
+      FoldedCodeColor.FrameColor = clGray
+      MouseLinkColor.Background = clNone
+      MouseLinkColor.Foreground = clBlue
+      LineHighlightColor.Background = clNone
+      LineHighlightColor.Foreground = clNone
+      OnChange = CSSSynEditChange
+      inline SynLeftGutterPartList1: TSynGutterPartList
+        object SynGutterMarks1: TSynGutterMarks
+          Width = 24
+          MouseActions = <>
+        end
+        object SynGutterLineNumber1: TSynGutterLineNumber
+          Width = 17
+          MouseActions = <>
+          MarkupInfo.Background = clBtnFace
+          MarkupInfo.Foreground = clNone
+          DigitCount = 2
+          ShowOnlyLineNumbersMultiplesOf = 1
+          ZeroStart = False
+          LeadingZeros = False
+        end
+        object SynGutterChanges1: TSynGutterChanges
+          Width = 4
+          MouseActions = <>
+          ModifiedColor = 59900
+          SavedColor = clGreen
+        end
+        object SynGutterSeparator1: TSynGutterSeparator
+          Width = 2
+          MouseActions = <>
+          MarkupInfo.Background = clWhite
+          MarkupInfo.Foreground = clGray
+        end
+        object SynGutterCodeFolding1: TSynGutterCodeFolding
+          MouseActions = <>
+          MarkupInfo.Background = clNone
+          MarkupInfo.Foreground = clGray
+          MouseActionsExpanded = <>
+          MouseActionsCollapsed = <>
+        end
+      end
+    end
+    object SortButton: TButton
+      AnchorSideLeft.Control = CSSSynEdit
+      AnchorSideLeft.Side = asrBottom
+      AnchorSideRight.Control = TextGroupBox
+      AnchorSideRight.Side = asrBottom
+      Left = 350
+      Height = 31
+      Top = 6
+      Width = 75
+      Anchors = [akTop, akRight]
+      AutoSize = True
+      BorderSpacing.Around = 6
+      Caption = 'Sort'
+      Constraints.MinWidth = 75
+      OnClick = SortButtonClick
+      TabOrder = 1
+    end
+    object ClearButton: TButton
+      AnchorSideLeft.Control = SortButton
+      AnchorSideTop.Control = SortButton
+      AnchorSideTop.Side = asrBottom
+      AnchorSideRight.Control = SortButton
+      AnchorSideRight.Side = asrBottom
+      Left = 350
+      Height = 31
+      Top = 43
+      Width = 75
+      Anchors = [akTop, akLeft, akRight]
+      AutoSize = True
+      Caption = 'Clear'
+      OnClick = ClearButtonClick
+      TabOrder = 2
+    end
+    object SaveButton: TButton
+      AnchorSideLeft.Control = SortButton
+      AnchorSideTop.Control = ClearButton
+      AnchorSideTop.Side = asrBottom
+      AnchorSideRight.Control = SortButton
+      AnchorSideRight.Side = asrBottom
+      Left = 350
+      Height = 31
+      Top = 80
+      Width = 75
+      Anchors = [akTop, akLeft, akRight]
+      AutoSize = True
+      BorderSpacing.Top = 6
+      Caption = 'Save'
+      OnClick = SaveButtonClick
+      TabOrder = 3
+    end
+  end
+  object BtnPanel: TButtonPanel
+    Left = 6
+    Height = 48
+    Top = 360
+    Width = 433
+    OKButton.Name = 'OKButton'
+    OKButton.DefaultCaption = True
+    HelpButton.Name = 'HelpButton'
+    HelpButton.DefaultCaption = True
+    CloseButton.Name = 'CloseButton'
+    CloseButton.DefaultCaption = True
+    CancelButton.Name = 'CancelButton'
+    CancelButton.DefaultCaption = True
+    TabOrder = 1
+    ShowButtons = [pbOK, pbCancel]
+    ShowBevel = False
+  end
+  object SaveDialog1: TSaveDialog
+    DefaultExt = '.txt'
+    Options = [ofOverwritePrompt, ofEnableSizing, ofViewDetail]
+    Left = 183
+    Top = 148
+  end
+  object SynCssSyn1: TSynCssSyn
+    DefaultFilter = 'Cascading Stylesheets (*.css)|*.css'
+    Enabled = False
+    Left = 180
+    Top = 146
+  end
+end

+ 117 - 0
design/fresnel.stylepropedit.pas

@@ -0,0 +1,117 @@
+unit Fresnel.StylePropEdit;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ButtonPanel, StdCtrls,
+  PropEdits, ObjInspStrConsts, IDEWindowIntf, TextTools, SynEdit,
+  SynHighlighterCss, LazUTF8;
+
+type
+
+  { TStylePropEditDialog }
+
+  TStylePropEditDialog = class(TForm)
+    BtnPanel: TButtonPanel;
+    ClearButton: TButton;
+    SaveButton: TButton;
+    SaveDialog1: TSaveDialog;
+    StatusLabel: TLabel;
+    SortButton: TButton;
+    TextGroupBox: TGroupBox;
+    CSSSynEdit: TSynEdit;
+    SynCssSyn1: TSynCssSyn;
+    procedure ClearButtonClick(Sender: TObject);
+    procedure FormClose(Sender: TObject; var {%H-}CloseAction: TCloseAction);
+    procedure FormCreate(Sender: TObject);
+    procedure CSSSynEditChange(Sender: TObject);
+    procedure SaveButtonClick(Sender: TObject);
+    procedure SortButtonClick(Sender: TObject);
+  private
+
+  public
+    Editor: TStringPropertyEditor;
+  end;
+
+var
+  StylePropEditDialog: TStylePropEditDialog;
+
+implementation
+
+{$R *.lfm}
+
+{ TStylePropEditDialog }
+
+procedure TStylePropEditDialog.ClearButtonClick(Sender: TObject);
+begin
+  CSSSynEdit.Clear;
+end;
+
+procedure TStylePropEditDialog.FormClose(Sender: TObject;
+  var CloseAction: TCloseAction);
+begin
+  IDEDialogLayoutList.SaveLayout(Self);
+end;
+
+procedure TStylePropEditDialog.FormCreate(Sender: TObject);
+begin
+  Caption := 'CSS Inline Style Editor';
+  StatusLabel.Caption := ois0Lines0Chars;
+  SortButton.Caption := oisSort;
+  ClearButton.Caption := oisClear;
+  IDEDialogLayoutList.ApplyLayout(Self);
+end;
+
+procedure TStylePropEditDialog.CSSSynEditChange(Sender: TObject);
+var
+  NumChars: Integer;
+  I: Integer;
+begin
+  NumChars := 0;
+  for I := 0 to CSSSynEdit.Lines.Count - 1 do
+    Inc(NumChars, UTF8Length(CSSSynEdit.Lines[I]));
+
+  if CSSSynEdit.Lines.Count = 1 then
+    StatusLabel.Caption := Format(ois1LineDChars, [NumChars])
+  else
+    StatusLabel.Caption := Format(oisDLinesDChars, [CSSSynEdit.Lines.Count, NumChars]);
+end;
+
+procedure TStylePropEditDialog.SaveButtonClick(Sender: TObject);
+begin
+  SaveDialog1.Title:=sccsSGEdtSaveDialog;
+  if SaveDialog1.Execute then
+    CSSSynEdit.Lines.SaveToFile(SaveDialog1.FileName);
+end;
+
+procedure TStylePropEditDialog.SortButtonClick(Sender: TObject);
+var
+  OldText, NewSortedText: String;
+  SortOnlySelection: Boolean;
+begin
+  if not Assigned(ShowSortSelectionDialogFunc) then
+  begin
+    SortButton.Enabled := False;
+    Exit;
+  end;
+
+  SortOnlySelection := True;
+  OldText := CSSSynEdit.SelText;
+  if OldText = '' then
+  begin
+    SortOnlySelection := False;
+    OldText := CSSSynEdit.Lines.Text;
+  end;
+
+  NewSortedText:='';
+  if ShowSortSelectionDialogFunc(OldText, nil, NewSortedText) <> mrOk then Exit;
+  if SortOnlySelection then
+    CSSSynEdit.SelText := NewSortedText
+  else
+    CSSSynEdit.Lines.Text := NewSortedText;
+end;
+
+end.
+

+ 11 - 1
design/fresneldsgn.lpk

@@ -17,10 +17,20 @@
       <Item>
         <Filename Value="fresnel.register.pas"/>
         <HasRegisterProc Value="True"/>
-        <UnitName Value="fresnel.register"/>
+        <UnitName Value="Fresnel.Register"/>
+      </Item>
+      <Item>
+        <Filename Value="fresnel.stylepropedit.pas"/>
+        <UnitName Value="Fresnel.StylePropEdit"/>
       </Item>
     </Files>
     <RequiredPkgs>
+      <Item>
+        <PackageName Value="SynEditDsgn"/>
+      </Item>
+      <Item>
+        <PackageName Value="SynEdit"/>
+      </Item>
       <Item>
         <PackageName Value="Fresnel"/>
       </Item>

+ 2 - 2
design/fresneldsgn.pas

@@ -8,13 +8,13 @@ unit FresnelDsgn;
 interface
 
 uses
-  fresnel.register, LazarusPackageIntf;
+  Fresnel.Register, Fresnel.StylePropEdit, LazarusPackageIntf;
 
 implementation
 
 procedure Register;
 begin
-  RegisterUnit('fresnel.register', @fresnel.register.Register);
+  RegisterUnit('Fresnel.Register', @Fresnel.Register.Register);
 end;
 
 initialization