diff --git a/components/buildintf/ideoptionsintf.pas b/components/buildintf/ideoptionsintf.pas index 1cac78cf59..0b29fc343f 100644 --- a/components/buildintf/ideoptionsintf.pas +++ b/components/buildintf/ideoptionsintf.pas @@ -184,8 +184,9 @@ const EdtOptionsCodetools = 600; EdtOptionsCodeFolding = 700; EdtOptionsCodeFoldingMouse = 701; - EdtOptionsDrawDivider = 800; - EdtOptionsMultiWindow = 900; + EdtOptionsLineWrap = 800; + EdtOptionsDrawDivider = 900; + EdtOptionsMultiWindow = 1000; GroupCodetools = 300; CdtOptionsGeneral = 100; diff --git a/ide/SourceSynWrap.pas b/ide/SourceSynWrap.pas new file mode 100644 index 0000000000..9ee884bab8 --- /dev/null +++ b/ide/SourceSynWrap.pas @@ -0,0 +1,48 @@ +unit SourceSynWrap; + +{$mode objfpc}{$H+} + +interface + +uses SynEditWrappedView, SynEditViewedLineMap, SynEdit, LazSynEditText, SynEditFoldedView, Classes; + +type + + { TLazSynSourceEditLineWrapPlugin } + + TLazSynSourceEditLineWrapPlugin = class(TLazSynEditLineWrapPlugin) + public + constructor Create(AnOwner: TComponent); override; + end; + +implementation + +{ TLazSynSourceEditLineWrapPlugin } + +constructor TLazSynSourceEditLineWrapPlugin.Create(AnOwner: TComponent); +var + Syn: TSynEdit absolute AnOwner; + Fld: TSynEditStringsLinked; + ALineMapView: TSynEditLineMappingView; + FldIdx: Integer; +begin + Fld := Syn.TextViewsManager.SynTextViewByClass[TSynEditFoldedView]; + + ALineMapView := TSynEditLineMappingView(Syn.TextViewsManager.SynTextViewByClass[TSynEditLineMappingView]); + if ALineMapView = nil then + ALineMapView := TSynEditLineMappingView.Create + else + Syn.TextViewsManager.RemoveSynTextView(ALineMapView); + + if Fld <> nil then + FldIdx := Syn.TextViewsManager.IndexOf(Fld) + else + FldIdx := Syn.TextViewsManager.Count; + + Syn.TextViewsManager.AddTextView(ALineMapView, FldIdx); + + inherited Create(AnOwner); +end; + +end. + diff --git a/ide/editoroptions.pp b/ide/editoroptions.pp index 11b16ec68a..7c2e60219d 100644 --- a/ide/editoroptions.pp +++ b/ide/editoroptions.pp @@ -64,7 +64,7 @@ uses SynHighlighterIni, SynHighlighterPo, SynHighlighterPike, SynPluginMultiCaret, SynEditMarkupFoldColoring, SynEditMarkup, SynGutterLineOverview, SynBeautifierPascal, SynEditTextDynTabExpander, SynEditTextTabExpander, - SynTextMateSyn, SynEditStrConst, SynHighlighterPosition, SynGutterMarks, + SynTextMateSyn, SynEditStrConst, SynHighlighterPosition, SynGutterMarks, SynEditWrappedView, // codetools LinkScanner, CodeToolManager, // BuildIntf @@ -1593,6 +1593,11 @@ type fDbgHintAutoTypeCastClass: Boolean; // Code Folding fReverseFoldPopUpOrder: Boolean; + // Wordwrap + FWordWrapCaretWrapPos: TLazSynEditWrapCaretPos; + FWordWrapEnabled: Boolean; + FWordWrapMinWidth: Integer; + fUseTabHistory: Boolean; fMultiCaretOnColumnSelect: Boolean; @@ -1671,6 +1676,12 @@ type // Code Folding property ReverseFoldPopUpOrder: Boolean read fReverseFoldPopUpOrder write fReverseFoldPopUpOrder default True; + + // wordwrap + property WordWrapEnabled: Boolean read FWordWrapEnabled write FWordWrapEnabled; + property WordWrapCaretWrapPos: TLazSynEditWrapCaretPos read FWordWrapCaretWrapPos write FWordWrapCaretWrapPos; + property WordWrapMinWidth: Integer read FWordWrapMinWidth write FWordWrapMinWidth default 10; + property UseTabHistory: Boolean read fUseTabHistory write fUseTabHistory; property MultiCaretOnColumnSelect: Boolean @@ -5464,6 +5475,8 @@ begin fDbgHintUseBackendDebugConverter := True; // Code folding fReverseFoldPopUpOrder := True; + // wordwrap + FWordWrapMinWidth := 10; // pas highlighter fPasExtendedKeywordsMode := False; fPasStringKeywordMode := spsmDefault; @@ -6818,6 +6831,16 @@ begin ASynEdit.Gutter.Width := fGutterWidth; + if ASynEdit is TIDESynEditor then begin + TIDESynEditor(ASynEdit).WordWrapEnabled := WordWrapEnabled; + TIDESynEditor(ASynEdit).WordWrapCaretWrapPos := WordWrapCaretWrapPos; + TIDESynEditor(ASynEdit).WordWrapMinWidth := WordWrapMinWidth; + if WordWrapEnabled then begin + ASynEdit.Options := ASynEdit.Options - [eoScrollPastEol]; + ASynEdit.Options2 := ASynEdit.Options2 - [eoScrollPastEolAddPage, eoScrollPastEolAutoCaret]; + end; + end; + ASynEdit.RightEdge := fRightMargin; if fVisibleRightMargin then ASynEdit.Options := ASynEdit.Options - [eoHideRightMargin] diff --git a/ide/frames/editor_wordwrap_options.lfm b/ide/frames/editor_wordwrap_options.lfm new file mode 100644 index 0000000000..c76ad2ac85 --- /dev/null +++ b/ide/frames/editor_wordwrap_options.lfm @@ -0,0 +1,76 @@ +object EditorWordWrapOptionsFrame: TEditorWordWrapOptionsFrame + Left = 0 + Height = 380 + Top = 0 + Width = 428 + ClientHeight = 380 + ClientWidth = 428 + TabOrder = 0 + DesignLeft = 534 + DesignTop = 48 + object cbEnableWordWrap: TCheckBox + AnchorSideLeft.Control = Owner + AnchorSideTop.Control = Owner + AnchorSideRight.Control = Owner + AnchorSideRight.Side = asrBottom + Left = 6 + Height = 19 + Top = 6 + Width = 416 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Around = 6 + Caption = 'cbEnableWordWrap' + TabOrder = 0 + end + object rgCaretWrapPos: TRadioGroup + AnchorSideLeft.Control = Owner + AnchorSideTop.Control = cbEnableWordWrap + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = Owner + AnchorSideRight.Side = asrBottom + Left = 6 + Height = 19 + Top = 31 + Width = 416 + Anchors = [akTop, akLeft, akRight] + AutoFill = True + AutoSize = True + BorderSpacing.Around = 6 + Caption = 'rgCaretWrapPos' + ChildSizing.LeftRightSpacing = 6 + ChildSizing.EnlargeHorizontal = crsHomogenousChildResize + ChildSizing.EnlargeVertical = crsHomogenousChildResize + ChildSizing.ShrinkHorizontal = crsScaleChilds + ChildSizing.ShrinkVertical = crsScaleChilds + ChildSizing.Layout = cclLeftToRightThenTopToBottom + ChildSizing.ControlsPerLine = 2 + Columns = 2 + TabOrder = 1 + end + object lbWinWordWrapWidth: TLabel + AnchorSideLeft.Control = Owner + AnchorSideTop.Control = edWinWordWrapWidth + AnchorSideTop.Side = asrCenter + Left = 6 + Height = 15 + Top = 60 + Width = 120 + BorderSpacing.Around = 6 + Caption = 'lbWinWordWrapWidth' + end + object edWinWordWrapWidth: TSpinEdit + AnchorSideLeft.Control = lbWinWordWrapWidth + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = rgCaretWrapPos + AnchorSideTop.Side = asrBottom + Left = 132 + Height = 23 + Top = 56 + Width = 124 + BorderSpacing.Around = 6 + MaxValue = 9999 + MinValue = 1 + TabOrder = 2 + Value = 10 + end +end diff --git a/ide/frames/editor_wordwrap_options.pas b/ide/frames/editor_wordwrap_options.pas new file mode 100644 index 0000000000..039895b005 --- /dev/null +++ b/ide/frames/editor_wordwrap_options.pas @@ -0,0 +1,84 @@ +unit editor_wordwrap_options; + +{$mode ObjFPC}{$H+} + +interface + +uses + // LCL + Forms, Controls, StdCtrls, ExtCtrls, Spin, + // IdeIntf + IDEOptEditorIntf, IDEOptionsIntf, SynEditWrappedView, + // IDE + EditorOptions, LazarusIDEStrConsts + ; + +type + + { TEditorWordWrapOptionsFrame } + + TEditorWordWrapOptionsFrame = class(TAbstractIDEOptionsEditor) + cbEnableWordWrap: TCheckBox; + lbWinWordWrapWidth: TLabel; + rgCaretWrapPos: TRadioGroup; + edWinWordWrapWidth: TSpinEdit; + private + + public + function GetTitle: String; override; + procedure Setup(ADialog: TAbstractOptionsEditorDialog); override; + procedure ReadSettings(AOptions: TAbstractIDEOptions); override; + procedure WriteSettings(AOptions: TAbstractIDEOptions); override; + class function SupportedOptionsClass: TAbstractIDEOptionsClass; override; + end; + +implementation + +{$R *.lfm} + +{ TEditorWordWrapOptionsFrame } + +function TEditorWordWrapOptionsFrame.GetTitle: String; +begin + Result := dlgOptWordWrap; +end; + +procedure TEditorWordWrapOptionsFrame.Setup(ADialog: TAbstractOptionsEditorDialog); +begin + cbEnableWordWrap.Caption := dlgOptWordWrapUseWordwrap; + rgCaretWrapPos.Caption := dlgOptWordWrapDisplayCaretAtWrapPositio; + rgCaretWrapPos.Items.Add(dlgOptWordWrapEndOfLine); + rgCaretWrapPos.Items.Add(dlgOptWordWrapStartOfNextLine); + lbWinWordWrapWidth.Caption := dlgOptWordWrapMinimumLineLength; +end; + +procedure TEditorWordWrapOptionsFrame.ReadSettings(AOptions: TAbstractIDEOptions); +begin + cbEnableWordWrap.Checked := (AOptions as TEditorOptions).WordWrapEnabled; + case (AOptions as TEditorOptions).WordWrapCaretWrapPos of + wcpEOL: rgCaretWrapPos.ItemIndex := 0; + wcpBOL: rgCaretWrapPos.ItemIndex := 1; + end; + edWinWordWrapWidth.Value := (AOptions as TEditorOptions).WordWrapMinWidth; +end; + +procedure TEditorWordWrapOptionsFrame.WriteSettings(AOptions: TAbstractIDEOptions); +begin + (AOptions as TEditorOptions).WordWrapEnabled := cbEnableWordWrap.Checked; + case rgCaretWrapPos.ItemIndex of + 0: (AOptions as TEditorOptions).WordWrapCaretWrapPos := wcpEOL; + 1: (AOptions as TEditorOptions).WordWrapCaretWrapPos := wcpBOL; + end; + (AOptions as TEditorOptions).WordWrapMinWidth := edWinWordWrapWidth.Value; + +end; + +class function TEditorWordWrapOptionsFrame.SupportedOptionsClass: TAbstractIDEOptionsClass; +begin + Result := TEditorOptions; +end; + +initialization + RegisterIDEOptionsEditor(GroupEditor, TEditorWordWrapOptionsFrame, EdtOptionsLineWrap); +end. + diff --git a/ide/lazarus.lpi b/ide/lazarus.lpi index 96afa5b09c..e43137378e 100644 --- a/ide/lazarus.lpi +++ b/ide/lazarus.lpi @@ -1468,6 +1468,13 @@ + + + + + + + diff --git a/ide/lazarusidestrconsts.pas b/ide/lazarusidestrconsts.pas index 081252cb3b..f1bcda3e62 100644 --- a/ide/lazarusidestrconsts.pas +++ b/ide/lazarusidestrconsts.pas @@ -1652,6 +1652,14 @@ resourcestring dlgCodeFoldEnableHide = 'Hide'; dlgCodeFoldEnableBoth = 'Both'; dlgCodeFoldPopUpOrder = 'Reverse fold-order in Popup'; + + dlgOptWordWrap = 'Word-wrap'; + dlgOptWordWrapUseWordwrap = 'Use Word-wrap'; + dlgOptWordWrapDisplayCaretAtWrapPositio = 'Display caret at wrap-position...'; + dlgOptWordWrapEndOfLine = 'end of line'; + dlgOptWordWrapStartOfNextLine = 'start of next line'; + dlgOptWordWrapMinimumLineLength = 'Minimum line length'; + dlfMousePredefinedScheme = 'Use predefined scheme'; dlfNoPredefinedScheme = '< None >'; dlfMouseSimpleGenericSect = 'General'; diff --git a/ide/main.pp b/ide/main.pp index ca6cffcb58..553d1125ac 100644 --- a/ide/main.pp +++ b/ide/main.pp @@ -131,7 +131,7 @@ uses Backup_Options, naming_options, fpdoc_options, idecoolbar_options, editortoolbar_options, editor_display_options, editor_keymapping_options, editor_mouseaction_options, editor_mouseaction_options_advanced, editor_color_options, editor_color_tml_options, - editor_markup_options, + editor_markup_options, editor_wordwrap_options, editor_markup_userdefined, editor_codetools_options, editor_codefolding_options, editor_general_misc_options, editor_dividerdraw_options, editor_multiwindow_options, editor_indent_options, diff --git a/ide/sourcesyneditor.pas b/ide/sourcesyneditor.pas index f383f48994..690f4f238b 100644 --- a/ide/sourcesyneditor.pas +++ b/ide/sourcesyneditor.pas @@ -61,8 +61,8 @@ uses SynEditHighlighter, SynEditHighlighterFoldBase, SynHighlighterPas, SynEditMarkupHighAll, SynEditKeyCmds, SynEditMarkupIfDef, SynEditMiscProcs, SynPluginMultiCaret, SynEditPointClasses, - SynEditMarkupFoldColoring, SynEditTextTabExpander, SynEditMouseCmds, - etSrcEditMarks, LazarusIDEStrConsts, SourceMarks; + SynEditMarkupFoldColoring, SynEditTextTabExpander, SynEditMouseCmds, SynEditWrappedView, + etSrcEditMarks, LazarusIDEStrConsts, SourceMarks, SourceSynWrap; type @@ -258,6 +258,7 @@ type FMarkupIdentComplWindow: TSynMarkupIdentComplWindow; FShowTopInfo: boolean; FFoldView: TSynEditFoldedView; + FWrapView: TLazSynSourceEditLineWrapPlugin; FTopInfoNestList: TLazSynEditNestedFoldsList; FSyncroEdit: TSynPluginSyncroEdit; FTemplateEdit: TSynPluginTemplateEdit; @@ -286,12 +287,16 @@ type function GetOnMultiCaretBeforeCommand: TSynMultiCaretBeforeCommand; procedure GetTopInfoMarkupForLine(Sender: TObject; {%H-}Line: integer; var Special: boolean; aMarkup: TSynSelectedColor); + function GetWordWrapEnabled: Boolean; procedure SetCaretColor(AValue: TColor); procedure SetHighlightUserWordCount(AValue: Integer); procedure SetOnMultiCaretBeforeCommand(AValue: TSynMultiCaretBeforeCommand); procedure SetShowTopInfo(AValue: boolean); procedure SetTopInfoMarkup(AValue: TSynSelectedColor); procedure DoHighlightChanged(Sender: TSynEditStrings; {%H-}AIndex, {%H-}ACount : Integer); + procedure SetWordWrapCaretWrapPos(AValue: TLazSynEditWrapCaretPos); + procedure SetWordWrapEnabled(AValue: Boolean); + procedure SetWordWrapMinWidth(AValue: Integer); procedure SrcSynCaretChanged(Sender: TObject); function GetHighlighter: TSynCustomFoldHighlighter; protected @@ -299,6 +304,8 @@ type function CreateGutter(AOwner : TSynEditBase; ASide: TSynGutterSide; ATextDrawer: TheTextDrawer): TSynGutter; override; procedure SetHighlighter(const Value: TSynCustomHighlighter); override; + procedure AddLineWrapView; + procedure RemoveLineWrapView; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; @@ -331,6 +338,10 @@ type property OnMultiCaretBeforeCommand: TSynMultiCaretBeforeCommand read GetOnMultiCaretBeforeCommand write SetOnMultiCaretBeforeCommand; property CaretStamp: Int64 read FCaretStamp; property CaretColor: TColor read FCaretColor write SetCaretColor; + + property WordWrapEnabled: Boolean read GetWordWrapEnabled write SetWordWrapEnabled; + property WordWrapCaretWrapPos: TLazSynEditWrapCaretPos write SetWordWrapCaretWrapPos; + property WordWrapMinWidth: Integer write SetWordWrapMinWidth; end; TIDESynHighlighterPasRangeList = class(TSynHighlighterPasRangeList) @@ -1559,6 +1570,29 @@ begin SrcSynCaretChanged(nil); end; +procedure TIDESynEditor.SetWordWrapCaretWrapPos(AValue: TLazSynEditWrapCaretPos); +begin + if FWrapView <> nil then + FWrapView.CaretWrapPos := AValue; +end; + +procedure TIDESynEditor.SetWordWrapEnabled(AValue: Boolean); +begin + if AValue = WordWrapEnabled then + exit; + + if AValue then + AddLineWrapView + else + RemoveLineWrapView; +end; + +procedure TIDESynEditor.SetWordWrapMinWidth(AValue: Integer); +begin + if FWrapView <> nil then + FWrapView.MinWrapWidth := AValue; +end; + procedure TIDESynEditor.SrcSynCaretChanged(Sender: TObject); function RealTopLine: Integer; begin @@ -1694,6 +1728,11 @@ begin aMarkup.Assign(FTopInfoMarkup); end; +function TIDESynEditor.GetWordWrapEnabled: Boolean; +begin + Result := FWrapView <> nil; +end; + procedure TIDESynEditor.SetCaretColor(AValue: TColor); begin if FCaretColor = AValue then Exit; @@ -1897,6 +1936,18 @@ begin end; end; +procedure TIDESynEditor.AddLineWrapView; +begin + if FWrapView <> nil then + RemoveLineWrapView; + FWrapView := TLazSynSourceEditLineWrapPlugin.Create(Self); +end; + +procedure TIDESynEditor.RemoveLineWrapView; +begin + FreeAndNil(FWrapView); +end; + constructor TIDESynEditor.Create(AOwner: TComponent); var MarkupFoldColors: TSynEditMarkupFoldColors; @@ -1967,6 +2018,7 @@ end; destructor TIDESynEditor.Destroy; begin + RemoveLineWrapView; UnRegisterMouseActionSearchHandler(@CatchMouseForTopInforLine); ViewedTextBuffer.RemoveChangeHandler(senrHighlightChanged, @DoHighlightChanged); HighlightUserWordCount := 0;