diff --git a/.gitattributes b/.gitattributes index 3aeaee626a..1b612975c9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,6 @@ * text=auto !eol components/synedit/allunits.pp svneol=native#text/pascal +components/synedit/syncompletion.pas svneol=native#text/pascal components/synedit/synedit.inc svneol=native#text/pascal components/synedit/synedit.pp svneol=native#text/pascal components/synedit/syneditautocomplete.pp svneol=native#text/pascal diff --git a/components/synedit/syncompletion.pas b/components/synedit/syncompletion.pas new file mode 100644 index 0000000000..b291fab031 --- /dev/null +++ b/components/synedit/syncompletion.pas @@ -0,0 +1,1175 @@ +{------------------------------------------------------------------------------- +The contents of this file are subject to the Mozilla Public License +Version 1.1 (the "License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at +http://www.mozilla.org/MPL/ + +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +the specific language governing rights and limitations under the License. + +The Original Code is: SynCompletionProposal.pas, released 2000-04-11. +The Original Code is based on mwCompletionProposal.pas by Cyrille de Brebisson, +part of the mwEdit component suite. +Portions created by Cyrille de Brebisson are Copyright (C) 1999 +Cyrille de Brebisson. All Rights Reserved. + +Contributors to the SynEdit and mwEdit projects are listed in the +Contributors.txt file. + +Alternatively, the contents of this file may be used under the terms of the +GNU General Public License Version 2 or later (the "GPL"), in which case +the provisions of the GPL are applicable instead of those above. +If you wish to allow use of your version of this file only under the terms +of the GPL and not to allow others to use your version of this file +under the MPL, indicate your decision by deleting the provisions above and +replace them with the notice and other provisions required by the GPL. +If you do not delete the provisions above, a recipient may use your version +of this file under either the MPL or the GPL. + +$Id$ + +You may retrieve the latest version of this file at the SynEdit home page, +located at http://SynEdit.SourceForge.net + +Known Issues: +-------------------------------------------------------------------------------} + +unit SynCompletion; + +{$I SynEdit.inc} + +interface + +uses +{$IFDEF SYN_LAZARUS} + LCLLinux, LMessages, +{$ELSE} + Windows, +{$ENDIF} + Classes, Messages, Graphics, Forms, Controls, StdCtrls, Menus, + SysUtils, SynEditTypes, SynEditKeyCmds, SynEditHighlighter, SynEdit; + +type + TSynBaseCompletionPaintItem = function(AKey: string; ACanvas: TCanvas; + X, Y: integer): boolean of object; + TCodeCompletionEvent = procedure(var Value: string; Shift: TShiftState) + of object; + TValidateEvent = procedure(Sender: TObject; Shift: TShiftState) of object; + + TSynBaseCompletionForm = class(TForm) + protected + FCurrentString: string; + FOnKeyPress: TKeyPressEvent; + FOnKeyDelete: TNotifyEvent; + FOnPaintItem: TSynBaseCompletionPaintItem; + FItemList: TStrings; + FPosition: Integer; + FNbLinesInWindow: Integer; + FFontHeight: integer; + Scroll: TScrollBar; + FOnValidate: TValidateEvent; + FOnCancel: TNotifyEvent; + FClSelect: TColor; + FAnsi: boolean; + procedure SetCurrentString(const Value: string); + procedure KeyDown(var Key: Word; Shift: TShiftState); override; + procedure KeyPress(var Key: char); override; + procedure Paint; override; + procedure ScrollGetFocus(Sender: TObject); + procedure Deactivate; override; + procedure SelectPrec; + procedure SelectNext; + procedure ScrollChange(Sender: TObject); + procedure SetItemList(const Value: TStrings); + procedure SetPosition(const Value: Integer); + procedure SetNbLinesInWindow(const Value: Integer); + procedure MouseDown(Button: TMouseButton; Shift: TShiftState; + X, Y: Integer); override; + procedure StringListChange(Sender: TObject); + private + Bitmap: TBitmap; // used for drawing + fCurrentEditor: TComponent; + public + constructor Create(AOwner: Tcomponent); override; + destructor destroy; override; + published + property CurrentString: string read FCurrentString write SetCurrentString; + property OnKeyPress: TKeyPressEvent read FOnKeyPress write FOnKeyPress; + property OnKeyDelete: TNotifyEvent read FOnKeyDelete write FOnKeyDelete; + property OnPaintItem: TSynBaseCompletionPaintItem read FOnPaintItem + write FOnPaintItem; + property OnValidate: TValidateEvent read FOnValidate write FOnValidate; + property OnCancel: TNotifyEvent read FOnCancel write FOnCancel; + property ItemList: TStrings read FItemList write SetItemList; + property Position: Integer read FPosition write SetPosition; + property NbLinesInWindow: Integer read FNbLinesInWindow + write SetNbLinesInWindow; + property ClSelect: TColor read FClSelect write FClSelect; + property ffAnsi: boolean read fansi write fansi; + property CurrentEditor: tComponent read fCurrentEditor write fCurrentEditor; + end; + + TSynBaseCompletion = class(TComponent) + private + Form: TSynBaseCompletionForm; + FOnExecute: TNotifyEvent; + FWidth: Integer; + function GetClSelect: TColor; + procedure SetClSelect(const Value: TColor); + function GetCurrentString: string; + function GetItemList: TStrings; + function GetNbLinesInWindow: Integer; + function GetOnCancel: TNotifyEvent; + function GetOnKeyPress: TKeyPressEvent; + function GetOnPaintItem: TSynBaseCompletionPaintItem; + function GetOnValidate: TValidateEvent; + function GetPosition: Integer; + procedure SetCurrentString(const Value: string); + procedure SetItemList(const Value: TStrings); + procedure SetNbLinesInWindow(const Value: Integer); + procedure SetOnCancel(const Value: TNotifyEvent); + procedure SetOnKeyPress(const Value: TKeyPressEvent); + procedure SetOnPaintItem(const Value: TSynBaseCompletionPaintItem); + procedure SetPosition(const Value: Integer); + procedure SetOnValidate(const Value: TValidateEvent); + function GetOnKeyDelete: TNotifyEvent; + procedure SetOnKeyDelete(const Value: TNotifyEvent); + procedure RFAnsi(const Value: boolean); + function SFAnsi: boolean; + procedure SetWidth(Value: Integer); + public + constructor Create(Aowner: TComponent); override; + destructor Destroy; override; + procedure Execute(s: string; x, y: integer); + procedure Deactivate; + property OnKeyPress: TKeyPressEvent read GetOnKeyPress write SetOnKeyPress; + property OnKeyDelete: TNotifyEvent read GetOnKeyDelete write SetOnKeyDelete; + property OnValidate: TValidateEvent read GetOnValidate write SetOnValidate; + property OnCancel: TNotifyEvent read GetOnCancel write SetOnCancel; + property CurrentString: string read GetCurrentString write SetCurrentString; + published + property OnExecute: TNotifyEvent read FOnExecute write FOnExecute; + property OnPaintItem: TSynBaseCompletionPaintItem + read GetOnPaintItem write SetOnPaintItem; + property ItemList: TStrings read GetItemList write SetItemList; + property Position: Integer read GetPosition write SetPosition; + property NbLinesInWindow: Integer read GetNbLinesInWindow + write SetNbLinesInWindow; + property ClSelect: TColor read GetClSelect write SetClSelect; + property AnsiStrings: boolean read SFAnsi write RFAnsi; + property Width: Integer read FWidth write SetWidth; + end; + + TSynCompletion = class(TSynBaseCompletion) + private + FShortCut: TShortCut; + fEditors: TList; + fEditstuffs: TList; + FEndOfTokenChr: string; + FOnCodeCompletion: TCodeCompletionEvent; + procedure SetEditor(const Value: TCustomSynEdit); + procedure backspace(Senter: TObject); + procedure Cancel(Senter: TObject); + procedure Validate(Senter: TObject; Shift: TShiftState); + procedure KeyPress(Sender: TObject; var Key: Char); + procedure EditorKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); + procedure EditorKeyPress(Sender: TObject; var Key: char); + function GetPreviousToken(FEditor: TCustomSynEdit): string; + function GetFEditor: TCustomSynEdit; + function GetEditor(i: integer): TCustomSynEdit; + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); + override; + procedure SetShortCut(Value: TShortCut); + public + constructor Create(AOwner: TComponent); override; + destructor destroy; override; + property Editors[i: integer]: TCustomSynEdit read GetEditor; + procedure AddEditor(aEditor: TCustomSynEdit); + function RemoveEditor(aEditor: TCustomSynEdit): boolean; + function EditorsCount: integer; + published + property ShortCut: TShortCut read FShortCut write SetShortCut; + property Editor: TCustomSynEdit read GetFEditor write SetEditor; + property EndOfTokenChr: string read FEndOfTokenChr write FEndOfTokenChr; + property OnCodeCompletion: TCodeCompletionEvent + read FOnCodeCompletion write FOnCodeCompletion; + end; + + TSynAutoComplete = class(TComponent) + private + FShortCut: TShortCut; + fEditors: TList; + fEditstuffs: TList; + fAutoCompleteList: TStrings; + FEndOfTokenChr: string; + procedure SetAutoCompleteList(List: TStrings); + function GetEditor(i: integer): TCustomSynEdit; + function GetEdit: TCustomSynEdit; + procedure SetEdit(const Value: TCustomSynEdit); + protected + procedure SetShortCut(Value: TShortCut); + procedure Notification(AComponent: TComponent; Operation: TOperation); + override; + procedure EditorKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); + virtual; + procedure EditorKeyPress(Sender: TObject; var Key: char); virtual; + function GetPreviousToken(aEditor: TCustomSynEdit): string; + public + constructor Create(AOwner: TComponent); override; + destructor destroy; override; + procedure Execute(token: string; aEditor: TCustomSynEdit); + property Editors[i: integer]: TCustomSynEdit read GetEditor; + procedure AddEditor(aEditor: TCustomSynEdit); + function RemoveEditor(aEditor: TCustomSynEdit): boolean; + function EditorsCount: integer; + function GetTokenList: string; + function GetTokenValue(Token: string): string; + published + property AutoCompleteList: TStrings read fAutoCompleteList + write SetAutoCompleteList; + property EndOfTokenChr: string read FEndOfTokenChr write FEndOfTokenChr; + property Editor: TCustomSynEdit read GetEdit write SetEdit; + property ShortCut: TShortCut read FShortCut write SetShortCut; + end; + +procedure PretyTextOut(c: TCanvas; x, y: integer; s: string); + +implementation + +uses + SynEditStrConst; + +{ TSynBaseCompletionForm } + +constructor TSynBaseCompletionForm.Create(AOwner: TComponent); +begin +{$IFDEF SYN_CPPB_1} + CreateNew(AOwner, 0); +{$ELSE} + {$IFDEF FPC} + CreateNew(AOwner,0); + {$ENDIF} +{$ELSE} + CreateNew(AOwner); +{$ENDIF} + FItemList := TStringList.Create; + BorderStyle := bsNone; + Scroll := TScrollBar.Create(self); + Scroll.Kind := sbVertical; + Scroll.ParentCtl3D := False; + Scroll.OnChange := {$IFDEF FPC}@{$ENDIF}ScrollChange; + Scroll.Parent := self; + Scroll.OnEnter := {$IFDEF FPC}@{$ENDIF}ScrollGetFocus; + Visible := false; + FFontHeight := Canvas.TextHeight('Cyrille de Brebisson'); + Color := clWindow; + ClSelect := clHighlight; + TStringList(FItemList).OnChange := {$IFDEF FPC}@{$ENDIF}StringListChange; + bitmap := TBitmap.Create; + NbLinesInWindow := 6; +end; + +procedure TSynBaseCompletionForm.Deactivate; +begin + Visible := False; +end; + +destructor TSynBaseCompletionForm.destroy; +begin + bitmap.free; + Scroll.Free; + FItemList.Free; + inherited destroy; +end; + +procedure TSynBaseCompletionForm.KeyDown(var Key: Word; + Shift: TShiftState); +var + i: integer; +begin + case Key of +// added the VK_XXX codes to make it more readable / maintainable + VK_RETURN: + if Assigned(OnValidate) then OnValidate(Self, Shift); + VK_ESCAPE, VK_SPACE: + if Assigned(OnCancel) then OnCancel(Self); + // I do not think there is a worst way to do this, but laziness rules :-) + VK_PRIOR: + for i := 1 to NbLinesInWindow do + SelectPrec; + VK_NEXT: + for i := 1 to NbLinesInWindow do + SelectNext; + VK_END: + if ssCtrl in Shift then Position := ItemList.count - 1; + VK_HOME: + if ssCtrl in Shift then Position := 0; + VK_UP: + if ssCtrl in Shift then + Position := 0 + else + SelectPrec; + VK_DOWN: + if ssCtrl in Shift then + Position := ItemList.count - 1 + else + SelectNext; + VK_BACK: + if (Shift = []) and (Length(CurrentString) > 0) then begin + CurrentString := Copy(CurrentString, 1, Length(CurrentString) - 1); + if Assigned(OnKeyDelete) then OnKeyDelete(Self); + end; + end; + Paint; +end; + +procedure TSynBaseCompletionForm.KeyPress(var Key: char); +begin + case key of // + #33..'z': begin + CurrentString := CurrentString + key; + if Assigned(OnKeyPress) then + OnKeyPress(self, Key); + end; + #8: + if Assigned(OnKeyPress) then OnKeyPress(self, Key); + else if Assigned(OnCancel) then + OnCancel(Self); + end; // case + paint; +end; + +procedure TSynBaseCompletionForm.MouseDown(Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); +begin + y := (y - 1) div FFontHeight; + Position := Scroll.Position + y; +end; + +procedure TSynBaseCompletionForm.Paint; +var + i: integer; + function Min(a, b: integer): integer; + begin + if a < b then + Result := a + else + Result := b; + end; + +begin + // update scrool bar + if ItemList.Count - NbLinesInWindow < 0 then + Scroll.Max := 0 + else + Scroll.Max := ItemList.Count - NbLinesInWindow; + Position := Position; + Scroll.LargeChange := NbLinesInWindow; + + // draw a rectangle around the window + Canvas.Pen.Color := ClBlack; + Canvas.Moveto(0, 0); + Canvas.LineTo(Width - 1, 0); + Canvas.LineTo(Width - 1, Height - 1); + Canvas.LineTo(0, Height - 1); + Canvas.LineTo(0, 0); + + with bitmap do begin + canvas.pen.color := color; + canvas.brush.color := color; + canvas.Rectangle(0, 0, Width, Height); + for i := 0 to min(NbLinesInWindow - 1, ItemList.Count - 1) do begin + if i + Scroll.Position = Position then begin + Canvas.Brush.Color := ClSelect; + Canvas.Pen.Color := ClSelect; + Canvas.Rectangle(0, FFontHeight * i, width, FFontHeight * (i + 1)); + Canvas.Pen.Color := ClBlack; + end else + Canvas.Brush.Color := Color; + + if not Assigned(OnPaintItem) + or not OnPaintItem(ItemList[Scroll.Position + i], Canvas, 0, FFontHeight * i) + then + Canvas.TextOut(2, FFontHeight * i, ItemList[Scroll.Position + i]); + end; + end; + canvas.Draw(1, 1, bitmap); +end; + +procedure TSynBaseCompletionForm.ScrollChange(Sender: TObject); +begin + if Position < Scroll.Position then + Position := Scroll.Position + else if Position > Scroll.Position + NbLinesInWindow - 1 then + Position := Scroll.Position + NbLinesInWindow - 1; + Paint; +end; + +procedure TSynBaseCompletionForm.ScrollGetFocus(Sender: TObject); +begin + ActiveControl := nil; +end; + +procedure TSynBaseCompletionForm.SelectNext; +begin + if Position < ItemList.Count - 1 then + Position := Position + 1; +end; + +procedure TSynBaseCompletionForm.SelectPrec; +begin + if Position > 0 then + Position := Position - 1; +end; + +procedure TSynBaseCompletionForm.SetCurrentString(const Value: string); +var + i: integer; +begin + FCurrentString := Value; + if ffAnsi then begin + for i := 0 to Pred(ItemList.Count) do + if 0 = CompareText(fCurrentString, + Copy(ItemList[i], 1, Length(fCurrentString))) + then begin + Position := i; + break; + end; + end else begin + for i := 0 to Pred(ItemList.Count) do + if 0 = CompareStr(fCurrentString, + Copy(ItemList[i], 1, Length(fCurrentString))) + then begin + Position := i; + break; + end; + end; +end; + +procedure TSynBaseCompletionForm.SetItemList(const Value: TStrings); +begin + FItemList.Assign(Value); +end; + +procedure TSynBaseCompletionForm.SetNbLinesInWindow( + const Value: Integer); +begin + FNbLinesInWindow := Value; + Height := fFontHeight * NbLinesInWindow + 2; + Scroll.Top := 1; + Scroll.Left := ClientWidth - Scroll.Width - 1; + Scroll.Height := Height - 2; + Bitmap.Width := Scroll.Left; + Bitmap.Height := Height - 2; +end; + +procedure TSynBaseCompletionForm.SetPosition(const Value: Integer); +begin + if Value <= ItemList.Count - 1 then begin + if FPosition <> Value then begin + FPosition := Value; + if Position < Scroll.Position then + Scroll.Position := Position + else if Scroll.Position < Position - NbLinesInWindow + 1 then + Scroll.Position := Position - NbLinesInWindow + 1; + invalidate; + end; + end; +end; + +procedure TSynBaseCompletionForm.StringListChange(Sender: TObject); +begin + if ItemList.Count - NbLinesInWindow < 0 then + Scroll.Max := 0 + else + Scroll.Max := ItemList.Count - NbLinesInWindow; + Position := Position; +end; + +{ TSynBaseCompletion } + +constructor TSynBaseCompletion.Create(Aowner: TComponent); +begin + FWidth := 262; + inherited Create(AOwner); + Form := TSynBaseCompletionForm.Create(Self); + Form.Width := FWidth; +end; + +destructor TSynBaseCompletion.Destroy; +begin + form.Free; + inherited Destroy; +end; + +procedure TSynBaseCompletion.Execute(s: string; x, y: integer); +begin + form.top := y; + form.left := x; + CurrentString := s; + if assigned(OnExecute) then + OnExecute(Self); + form.Show; +end; + +function TSynBaseCompletion.GetCurrentString: string; +begin + result := Form.CurrentString; +end; + +function TSynBaseCompletion.GetItemList: TStrings; +begin + result := Form.ItemList; +end; + +function TSynBaseCompletion.GetNbLinesInWindow: Integer; +begin + Result := Form.NbLinesInWindow; +end; + +function TSynBaseCompletion.GetOnCancel: TNotifyEvent; +begin + Result := Form.OnCancel; +end; + +function TSynBaseCompletion.GetOnKeyPress: TKeyPressEvent; +begin + Result := Form.OnKeyPress; +end; + +function TSynBaseCompletion.GetOnPaintItem: TSynBaseCompletionPaintItem; +begin + Result := Form.OnPaintItem; +end; + +function TSynBaseCompletion.GetOnValidate: TValidateEvent; +begin + Result := Form.OnValidate; +end; + +function TSynBaseCompletion.GetPosition: Integer; +begin + Result := Form.Position; +end; + +procedure TSynBaseCompletion.SetCurrentString(const Value: string); +begin + form.CurrentString := Value; +end; + +procedure TSynBaseCompletion.SetItemList(const Value: TStrings); +begin + form.ItemList := Value; +end; + +procedure TSynBaseCompletion.SetNbLinesInWindow(const Value: Integer); +begin + form.NbLinesInWindow := Value; +end; + +procedure TSynBaseCompletion.SetOnCancel(const Value: TNotifyEvent); +begin + form.OnCancel := Value; +end; + +procedure TSynBaseCompletion.SetOnKeyPress(const Value: TKeyPressEvent); +begin + form.OnKeyPress := Value; +end; + +procedure TSynBaseCompletion.SetOnPaintItem(const Value: + TSynBaseCompletionPaintItem); +begin + form.OnPaintItem := Value; +end; + +procedure TSynBaseCompletion.SetPosition(const Value: Integer); +begin + form.Position := Value; +end; + +procedure TSynBaseCompletion.SetOnValidate(const Value: TValidateEvent); +begin + form.OnValidate := Value; +end; + +function TSynBaseCompletion.GetClSelect: TColor; +begin + Result := Form.ClSelect; +end; + +procedure TSynBaseCompletion.SetClSelect(const Value: TColor); +begin + Form.ClSelect := Value; +end; + +function TSynBaseCompletion.GetOnKeyDelete: TNotifyEvent; +begin + result := Form.OnKeyDelete; +end; + +procedure TSynBaseCompletion.SetOnKeyDelete(const Value: TNotifyEvent); +begin + form.OnKeyDelete := Value; +end; + +procedure TSynBaseCompletion.RFAnsi(const Value: boolean); +begin + form.ffAnsi := value; +end; + +function TSynBaseCompletion.SFAnsi: boolean; +begin + result := form.ffansi; +end; + +procedure TSynBaseCompletion.SetWidth(Value: Integer); +begin + FWidth := Value; + Form.Width := FWidth; + Form.SetNbLinesInWindow(Form.FNbLinesInWindow); +end; + +procedure TSynBaseCompletion.Deactivate; +begin + if Assigned(Form) then Form.Deactivate; +end; + +procedure PretyTextOut(c: TCanvas; x, y: integer; s: string); +var + i: integer; + b: TBrush; + f: TFont; +begin + b := TBrush.Create; + b.Assign(c.Brush); + f := TFont.Create; + f.Assign(c.Font); + try + i := 1; + while i <= Length(s) do + case s[i] of + #1: begin + C.Font.Color := (Ord(s[i + 3]) shl 8 + Ord(s[i + 2])) shl 8 + Ord(s[i + 1]); + inc(i, 4); + end; + #2: begin + C.Font.Color := (Ord(s[i + 3]) shl 8 + Ord(s[i + 2])) shl 8 + Ord(s[i + 1]); + inc(i, 4); + end; + #3: begin + case s[i + 1] of + 'B': c.Font.Style := c.Font.Style + [fsBold]; + 'b': c.Font.Style := c.Font.Style - [fsBold]; + 'U': c.Font.Style := c.Font.Style + [fsUnderline]; + 'u': c.Font.Style := c.Font.Style - [fsUnderline]; + 'I': c.Font.Style := c.Font.Style + [fsItalic]; + 'i': c.Font.Style := c.Font.Style - [fsItalic]; + end; + inc(i, 2); + end; + else + C.TextOut(x, y, s[i]); + x := x + c.TextWidth(s[i]); + inc(i); + end; + except + end; + c.Font.Assign(f); + f.Free; + c.Brush.Assign(b); + b.Free; +end; + +{ TSynCompletion } + +type + TRecordUsedToStoreEachEditorVars = record + kp: TKeyPressEvent; + kd: TKeyEvent; + NoNextKey: boolean; + end; + PRecordUsedToStoreEachEditorVars = ^TRecordUsedToStoreEachEditorVars; + +procedure TSynCompletion.backspace(Senter: TObject); +var + F: TSynBaseCompletionForm; +begin + F := Senter as TSynBaseCompletionForm; + if F.CurrentEditor <> nil then begin + (F.CurrentEditor as TCustomSynEdit).CommandProcessor(ecDeleteLastChar, #0, + nil); + end; +end; + +procedure TSynCompletion.Cancel(Senter: TObject); +var + F: TSynBaseCompletionForm; +begin + F := Senter as TSynBaseCompletionForm; + if F.CurrentEditor <> nil then begin + if (F.CurrentEditor as TCustomSynEdit).Owner is TWinControl then + TWinControl((F.CurrentEditor as TCustomSynEdit).Owner).SetFocus; + (F.CurrentEditor as TCustomSynEdit).SetFocus; + end; +end; + +procedure TSynCompletion.Validate(Senter: TObject; Shift: TShiftState); +var + F: TSynBaseCompletionForm; + Value: string; + Pos: TPoint; +begin + F := Senter as TSynBaseCompletionForm; + if F.CurrentEditor <> nil then + with F.CurrentEditor as TCustomSynEdit do begin + BlockBegin := Point(CaretX - length(CurrentString), CaretY); + BlockEnd := Point(CaretX, CaretY); + if Assigned(FOnCodeCompletion) then begin + Value := ItemList[position]; + FOnCodeCompletion(Value, Shift); + SelText := Value; + end else + SelText := ItemList[position]; + with Editor do begin + Pos.x := CaretX; + Pos.y := CaretY; + Perform(LM_MBUTTONDOWN, 0, 0); + Application.ProcessMessages; + CaretX := Pos.x; + CaretY := Pos.y; + end; + SetFocus; + end; +end; + +procedure TSynCompletion.KeyPress(Sender: TObject; var Key: Char); +var + F: TSynBaseCompletionForm; +begin + F := Sender as TSynBaseCompletionForm; + if F.CurrentEditor <> nil then begin + with F.CurrentEditor as TCustomSynEdit do + CommandProcessor(ecChar, Key, nil); + end; +end; + +procedure TSynCompletion.SetEditor(const Value: TCustomSynEdit); +begin + AddEditor(Value); +end; + +procedure TSynCompletion.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if (Operation = opRemove) and (fEditors.IndexOf(AComponent) > -1) then + RemoveEditor(AComponent as TCustomSynEdit); +end; + +constructor TSynCompletion.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + Form.OnKeyPress := {$IFDEF FPC}@{$ENDIF}KeyPress; + Form.OnKeyDelete := {$IFDEF FPC}@{$ENDIF}backspace; + Form.OnValidate := {$IFDEF FPC}@{$ENDIF}validate; + Form.OnCancel := {$IFDEF FPC}@{$ENDIF}Cancel; + FEndOfTokenChr := '()[].'; + fEditors := TList.Create; + fEditstuffs := TList.Create; + fShortCut := Menus.ShortCut(Ord(' '), [ssCtrl]); +end; + +procedure TSynCompletion.SetShortCut(Value: TShortCut); +begin + FShortCut := Value; +end; + +procedure TSynCompletion.EditorKeyDown(Sender: TObject; + var Key: Word; Shift: TShiftState); +var + p: TPoint; + i: integer; + ShortCutKey: Word; + ShortCutShift: TShiftState; +begin + Writeln('[TSynCompletion] EditorKeyDown'); + + ShortCutToKey(FShortCut, ShortCutKey, ShortCutShift); + +//inserted by shane + ShortCutKey := word(' '); + ShortCutShift := [ssCtrl]; +//shane + + i := fEditors.indexOf(Sender); + if i <> -1 then + with sender as TCustomSynEdit do begin + if not ReadOnly and (Shift = ShortCutShift) and (Key = ShortCutKey) then begin + p := ClientToScreen(Point(CaretXPix, CaretYPix + LineHeight)); + Form.CurrentEditor := Sender as TCustomSynEdit; + Execute(GetPreviousToken(Sender as TCustomSynEdit), p.x, p.y); + Key := 0; + TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).NoNextKey := true; + end; + if assigned(TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).kd) then + TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).kd(sender, key, shift); + end; +end; + +function TSynCompletion.GetPreviousToken(FEditor: TCustomSynEdit): string; +var + s: string; + i: integer; +begin + if FEditor <> nil then begin + s := FEditor.LineText; + i := FEditor.CaretX - 1; + if i > length(s) then + result := '' + else begin + while (i > 0) and (s[i] > ' ') and (pos(s[i], FEndOfTokenChr) = 0) do + dec(i); + result := copy(s, i + 1, FEditor.CaretX - i - 1); + end; + end + else + result := ''; +end; + +procedure TSynCompletion.EditorKeyPress(Sender: TObject; var Key: char); +var + i: integer; +begin + i := fEditors.IndexOf(Sender); + if i <> -1 then begin + if TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).NoNextKey then begin + key := #0; + TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).NoNextKey := false; + end; + if assigned(TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).kp) then + TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).kp(sender, key); + end; +end; + +destructor TSynCompletion.destroy; +begin + // necessary to get Notification called before fEditors is freed + Form.Free; + Form := nil; + while fEditors.Count <> 0 do + RemoveEditor(TCustomSynEdit(fEditors.last)); + fEditors.Free; + fEditstuffs.free; + inherited; +end; + +function TSynCompletion.GetFEditor: TCustomSynEdit; +begin + if EditorsCount > 0 then + result := Editors[0] + else + result := nil; +end; + +procedure TSynCompletion.AddEditor(aEditor: TCustomSynEdit); +var + p: PRecordUsedToStoreEachEditorVars; +begin + if fEditors.IndexOf(Editor) = -1 then begin + fEditors.Add(aEditor); + new(p); + p^.kp := aEditor.OnKeyPress; + p^.kd := aEditor.OnKeyDown; + p^.NoNextKey := false; + fEditstuffs.add(p); + aEditor.FreeNotification(self); + if not (csDesigning in ComponentState) then begin + aEditor.OnKeyDown := {$IFDEF FPC}@{$ENDIF}EditorKeyDown; + aEditor.OnKeyPress := {$IFDEF FPC}@{$ENDIF}EditorKeyPress; + end; + end; +end; + +function TSynCompletion.EditorsCount: integer; +begin + result := fEditors.count; +end; + +function TSynCompletion.GetEditor(i: integer): TCustomSynEdit; +begin + if (i < 0) or (i >= EditorsCount) then + result := nil + else + result := TCustomSynEdit(fEditors[i]); +end; + +function TSynCompletion.RemoveEditor(aEditor: TCustomSynEdit): boolean; +var + i: integer; + P : PRecordUsedToStoreEachEditorVars; +begin + i := fEditors.Remove(aEditor); + result := i <> -1; + if result then + begin + p := fEditStuffs[i]; //shane + dispose(p); //shane +// dispose(fEditstuffs[i]); //commented out by shane + fEditstuffs.delete(i); + end; +end; + +{ TSynAutoComplete } + +procedure TSynAutoComplete.AddEditor(aEditor: TCustomSynEdit); +var + p: PRecordUsedToStoreEachEditorVars; +begin + if fEditors.IndexOf(aEditor) = -1 then begin + fEditors.Add(aEditor); + new(p); + p^.kp := aEditor.OnKeyPress; + p^.kd := aEditor.OnKeyDown; + p^.NoNextKey := false; + fEditstuffs.add(p); + aEditor.FreeNotification(self); + if not (csDesigning in ComponentState) then begin + aEditor.OnKeyDown := {$IFDEF FPC}@{$ENDIF}EditorKeyDown; + aEditor.OnKeyPress := {$IFDEF FPC}@{$ENDIF}EditorKeyPress; + end; + end; +end; + +constructor TSynAutoComplete.Create(AOwner: TComponent); +begin + inherited; + fEditors := TList.Create; + fEditstuffs := TList.Create; + FEndOfTokenChr := '()[].'; + fAutoCompleteList := TStringList.Create; + fShortCut := Menus.ShortCut(Ord(' '), [ssShift]); +end; + +procedure TSynAutoComplete.SetShortCut(Value: TShortCut); +begin + FShortCut := Value; +end; + +destructor TSynAutoComplete.destroy; +begin + while feditors.count <> 0 do +{$IFDEF FPC} + RemoveEditor(TCustomSynEdit(feditors.last)); +{$ELSE} + RemoveEditor(feditors.last); +{$ENDIF} + fEditors.free; + fEditstuffs.free; + fAutoCompleteList.free; + inherited; +end; + +procedure TSynAutoComplete.EditorKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); +var + i: integer; + ShortCutKey: Word; + ShortCutShift: TShiftState; +begin + ShortCutToKey(FShortCut, ShortCutKey, ShortCutShift); +//inserted by shane + ShortCutKey := word(' '); + ShortCutShift := [ssCtrl]; +//shane + + i := fEditors.IndexOf(Sender); + if i <> -1 then begin + if (Shift = ShortCutShift) and (Key = ShortCutKey) and + not (Sender as TCustomSynEdit).ReadOnly + then begin + Execute(GetPreviousToken(Sender as TCustomSynEdit), Sender as TCustomSynEdit); + Key := 0; + TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).NoNextKey := true; + end; + if assigned(TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).kd) then + TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).kd(sender, key, Shift); + end; +end; + +procedure TSynAutoComplete.EditorKeyPress(Sender: TObject; var Key: char); +var + i: integer; +begin + i := fEditors.IndexOf(Sender); + if i <> -1 then begin + if TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).NoNextKey then begin + key := #0; + TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).NoNextKey := false; + end; + if assigned(TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).kp) then + TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).kp(sender, key); + end; +end; + +function TSynAutoComplete.EditorsCount: integer; +begin + result := fEditors.count; +end; + +procedure TSynAutoComplete.Execute(token: string; aEditor: TCustomSynEdit); +var + Temp: string; + i, j, prevspace: integer; + StartOfBlock: tpoint; +begin + i := AutoCompleteList.IndexOf(token); + if i <> -1 then begin + TRecordUsedToStoreEachEditorVars(fEditstuffs[fEditors.IndexOf(aEditor)]^).NoNextKey := true; + for j := 1 to length(token) do + aEditor.CommandProcessor(ecDeleteLastChar, ' ', nil); + inc(i); + StartOfBlock := Point(-1, -1); + PrevSpace := 0; + while (i < AutoCompleteList.Count) and + (length(AutoCompleteList[i]) > 0) and + (AutoCompleteList[i][1] = '=') do begin + for j := 0 to PrevSpace - 1 do + aEditor.CommandProcessor(ecDeleteLastChar, ' ', nil); + Temp := AutoCompleteList[i]; + PrevSpace := 0; + while (length(temp) >= PrevSpace + 2) and (temp[PrevSpace + 2] <= ' ') do + inc(PrevSpace); + for j := 2 to length(Temp) do begin + aEditor.CommandProcessor(ecChar, Temp[j], nil); + if Temp[j] = '|' then + StartOfBlock := aEditor.CaretXY + end; + inc(i); + if (i < AutoCompleteList.Count) and + (length(AutoCompleteList[i]) > 0) and + (AutoCompleteList[i][1] = '=') then + aEditor.CommandProcessor(ecLineBreak, ' ', nil); + end; + if (StartOfBlock.x <> -1) and (StartOfBlock.y <> -1) then begin + aEditor.CaretXY := StartOfBlock; + aEditor.CommandProcessor(ecDeleteLastChar, ' ', nil); + end; + end; +end; + +function TSynAutoComplete.GetEdit: TCustomSynEdit; +begin + if EditorsCount > 0 then + result := Editors[0] + else + result := nil; +end; + +function TSynAutoComplete.GetEditor(i: integer): TCustomSynEdit; +begin + if (i < 0) or (i >= EditorsCount) then + result := nil + else + result := TCustomSynEdit(fEditors[i]); +end; + +function TSynAutoComplete.GetPreviousToken(aEditor: TCustomSynEdit): string; +var + s: string; + i: integer; +begin + if aEditor <> nil then begin + s := aEditor.LineText; + i := aEditor.CaretX - 1; + if i > length(s) then + result := '' + else begin + while (i > 0) and (s[i] > ' ') and (pos(s[i], FEndOfTokenChr) = 0) do + dec(i); + result := copy(s, i + 1, aEditor.CaretX - i - 1); + end; + end + else + result := ''; +end; + +procedure TSynAutoComplete.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if (Operation = opRemove) and (fEditors.indexOf(AComponent) <> -1) then + RemoveEditor(AComponent as TCustomSynEdit); +end; + +function TSynAutoComplete.RemoveEditor(aEditor: TCustomSynEdit): boolean; +var + i: integer; + P : PRecordUsedToStoreEachEditorVars; + +begin + i := fEditors.Remove(aEditor); + result := i <> -1; + if result then begin + p := fEditStuffs[i]; //shane + dispose(p); //shane +// dispose(fEditstuffs[i]); //commented out by shane + fEditstuffs.delete(i); + end; +end; + +procedure TSynAutoComplete.SetAutoCompleteList(List: TStrings); +begin + fAutoCompleteList.Assign(List); +end; + +procedure TSynAutoComplete.SetEdit(const Value: TCustomSynEdit); +begin + AddEditor(Value); +end; + +function TSynAutoComplete.GetTokenList: string; +var + List: TStringList; + i: integer; +begin + Result := ''; + if AutoCompleteList.Count < 1 then Exit; + List := TStringList.Create; + i := 0; + while (i < AutoCompleteList.Count) do begin + if (length(AutoCompleteList[i]) > 0) and (AutoCompleteList[i][1] <> '=') then + List.Add(Trim(AutoCompleteList[i])); + inc(i); + end; + Result := List.Text; + List.Free; +end; + +function TSynAutoComplete.GetTokenValue(Token: string): string; +var + i: integer; + List: TStringList; +begin + Result := ''; + i := AutoCompleteList.IndexOf(Token); + if i <> -1 then begin + List := TStringList.Create; + Inc(i); + while (i < AutoCompleteList.Count) and + (length(AutoCompleteList[i]) > 0) and + (AutoCompleteList[i][1] = '=') do begin + if Length(AutoCompleteList[i]) = 1 then + List.Add('') + else + List.Add(Copy(AutoCompleteList[i], 2, Length(AutoCompleteList[i]))); + inc(i); + end; + Result := List.Text; + List.Free; + end; +end; + +end. + diff --git a/components/synedit/syneditautocomplete.pp b/components/synedit/syneditautocomplete.pp index ff7e456834..bb6c4d841b 100644 --- a/components/synedit/syneditautocomplete.pp +++ b/components/synedit/syneditautocomplete.pp @@ -251,16 +251,19 @@ begin try Temp.Text := fCompletionValues[i]; // indent lines - if (IndentLen > 0) and (Temp.Count > 1) then begin + if (IndentLen > 0) and (Temp.Count > 1) then + begin s := StringOfChar(' ', IndentLen); for i := 1 to Temp.Count - 1 do Temp[i] := s + Temp[i]; end; // find first '|' and use it as caret position - for i := 0 to Temp.Count - 1 do begin + for i := 0 to Temp.Count - 1 do + begin s := Temp[i]; j := Pos('|', s); - if j > 0 then begin + if j > 0 then + begin Delete(s, j, 1); Temp[i] := s; // if j > 1 then diff --git a/ide/editoroptions.pp b/ide/editoroptions.pp index c774323749..682d8f7e79 100644 --- a/ide/editoroptions.pp +++ b/ide/editoroptions.pp @@ -416,7 +416,6 @@ begin ConfFileName:=SecConfFileName; end; end; -writeln('EditorOptionsFile=',ConfFilename); XMLConfig:=TXMLConfig.Create(ConfFileName); // set defaults @@ -463,7 +462,6 @@ procedure TEditorOptions.Load; var SynEditOpt:TSynEditorOption; SynEditOptName:ansistring; begin -writeln('AAAAAAAAAAAAAAAAAAAAAAAAAAAAA'); // general options for SynEditOpt:=Low(TSynEditorOption) to High(TSynEditorOption) do begin case SynEditOpt of @@ -496,7 +494,6 @@ writeln('AAAAAAAAAAAAAAAAAAAAAAAAAAAAA'); fUndoAfterSave:= XMLConfig.GetValue('EditorOptions/General/Editor/UndoAfterSave',true); -writeln('UndoAfterSave',fUndoAfterSave); fDoubleClickLine:= XMLConfig.GetValue('EditorOptions/General/Editor/DoubleClickLine',false); fFindTextAtCursor:= @@ -1134,7 +1131,6 @@ begin with FontDialog do begin if Execute then begin EditorFontComboBox.Text:=FontName; -writeln('[TEditorOptionsForm.EditorFontButtonClick] fontname=''',FontName,''''); for a:=Low(PreviewEdits) to High(PreviewEdits) do begin if PreviewEdits[a]<>nil then FontDialogNameToFont(FontName,PreviewEdits[a].Font); @@ -1256,8 +1252,6 @@ begin end; if Old<>CurHighlightElement then ShowCurAttribute; - if CurHighlightElement<>nil then - writeln('CurHigh: '+CurHighlightElement.Name); end; procedure TEditorOptionsForm.InvalidatePreviews; @@ -2714,7 +2708,6 @@ begin EditorOpts.Save; try - writeln('SAVING ',EditorOpts.CodeTemplateFileName); SynAutoComplete.AutoCompleteList.SaveToFile( EditorOpts.CodeTemplateFileName); except @@ -2730,6 +2723,7 @@ end; procedure TEditorOptionsForm.CancelButtonClick(Sender:TObject); begin + EditorOpts.Load; ModalResult:=mrCancel; end; diff --git a/ide/find_dlg.pp b/ide/find_dlg.pp index 35ddd23a71..5c2690b556 100644 --- a/ide/find_dlg.pp +++ b/ide/find_dlg.pp @@ -45,10 +45,13 @@ type cbRegularExpressions : TCheckBox; rgForwardBack : TRadioGroup; + rgScope : TRadioGroup; + rgOrigin : TRadioGroup; { event handlers } procedure btnOKClicked(Sender : TObject); procedure btnCancelClicked(Sender : TObject); procedure btnHelpClicked(Sender : TObject); + Procedure FindDialogOnActivate(Sender : TObject); private FFindText : String; FOnFind : TNotifyEvent; @@ -101,7 +104,7 @@ begin begin parent := Self; Left := 10; - Top := 35; + Top := 30; Width :=(Self.Width div 2) - 10; Height := (Self.Height div 2) -35; Caption := 'Options'; @@ -117,7 +120,7 @@ begin begin parent := gbGroupBox; left := 5; - top := 5; + top := 3; Caption := 'Case Sensitive'; Name := 'cbCaseSensitive'; visible := True; @@ -127,7 +130,7 @@ begin begin parent := gbGroupBox; left := 5; - top := 25; + top := 20; Caption := 'Whole Words'; Name := 'cbWholeWords'; visible := True; @@ -137,7 +140,7 @@ begin begin parent := gbGroupBox; left := 5; - top := 50; + top := 37; Caption := 'Regular Expressions'; Name := 'cbRegularExpressions'; visible := True; @@ -148,7 +151,7 @@ begin begin parent := self; left := (Self.Width div 2) +5; - top := 35; + top := 30; Height := (Self.Height div 2) -35; width := (Self.Width div 2) -10; Caption := 'Direction'; @@ -159,6 +162,38 @@ begin ItemIndex := 0; end; + rgScope := TRadioGroup.Create(self); + with rgScope do + begin + parent := self; + left := 10; + top := (Self.Height div 2)+5; + Height := (Self.Height div 2)-35; + width := (Self.Width div 2) -10; + Caption := 'Scope'; + Items.Add('Global'); + Items.Add('Selected Text'); + Name := 'rgScope'; + visible := True; + ItemIndex := 0; + end; + + rgOrigin := TRadioGroup.Create(self); + with rgOrigin do + begin + parent := self; + left := (Self.Width div 2) +5; + top := (Self.Height div 2) + 5; + Height := (Self.Height div 2) -35; + width := (Self.Width div 2) -10; + Caption := 'Origin'; + Items.Add('From Cursor'); + Items.Add('Entire Scope'); + Name := 'rgOrigin'; + visible := True; + ItemIndex := 1; + end; + btnOK := TButton.create(self); with btnOK do begin @@ -200,6 +235,7 @@ begin visible := True; OnCLick := @BTnHelpClicked; end; + OnActivate := @FindDialogOnActivate; end; procedure TFindDialog.btnOKClicked(Sender : TObject); @@ -217,5 +253,9 @@ procedure TFindDialog.btnHelpClicked(Sender : TObject); Begin end; +Procedure TFindDialog.FindDialogOnActivate(Sender : TObject); +Begin + edtTextToFind.SetFocus; +End; end. diff --git a/ide/main.pp b/ide/main.pp index 56e95525ee..7b4b7a8ec3 100644 --- a/ide/main.pp +++ b/ide/main.pp @@ -37,8 +37,7 @@ uses CompReg; const - STANDARDBTNCOUNT = 50; - + Version_String = '0.7'; type @@ -258,7 +257,7 @@ var begin inherited Create(AOwner); - Caption := 'Lazarus Editor v 0.5'; + Caption := 'Lazarus Editor v '+Version_String; Left := 0; Top := 0; @@ -693,7 +692,7 @@ begin SpeedButton5.OnClick := @SourceNotebook.SaveClicked; SpeedButton6.OnClick := @SourceNotebook.SaveAllClicked; - + EditorOPts.Load; end; @@ -1621,7 +1620,8 @@ end; procedure TMainIDE.mnuEnvironmentOptionsClicked(Sender : TObject); Begin - EditorOptionsForm.ShowModal; + if EditorOptionsForm.ShowModal = mrOK then + SourceNotebook.ReloadEditorOptions; End; @@ -1643,8 +1643,8 @@ end. { ============================================================================= $Log$ - Revision 1.53 2001/01/31 18:57:29 lazarus - Added the ability to use the FIND feature in the editor. + Revision 1.54 2001/02/01 16:45:19 lazarus + Started the code completion. Shane Revision 1.52 2001/01/31 13:03:33 lazarus diff --git a/ide/uniteditor.pp b/ide/uniteditor.pp index d449d5bd9b..7e6a0e49a7 100644 --- a/ide/uniteditor.pp +++ b/ide/uniteditor.pp @@ -31,10 +31,10 @@ unit UnitEditor; interface uses - classes, Controls, forms,buttons,comctrls,sysutils,Dialogs,FormEditor,Find_Dlg, + classes, Controls, forms,buttons,comctrls,sysutils,Dialogs,FormEditor,Find_Dlg,EditorOPtions, {$ifdef NEW_EDITOR_SYNEDIT} - SynEdit, SynEditHighlighter, SynHighlighterPas, SynEditAutoComplete, - SynEditKeyCmds, + SynEdit, SynEditHighlighter, SynHighlighterPas,SynEditAutoComplete, + SynEditKeyCmds,SynCompletion, {$else} mwcustomedit,mwPasSyn, {$endif} @@ -146,6 +146,8 @@ type Function StartFind : Boolean; Function FindAgain(StartX,StartLine : Integer) : Boolean; + Function RefreshEditorSettings : Boolean; + property Editor : TmwCustomEdit read FEditor; property Visible : Boolean read FVisible write FVisible default False; FindText : String; @@ -241,6 +243,7 @@ type Procedure ToggleBookmark(Value : Integer); Procedure GotoBookmark(Value: Integer); + Procedure ReloadEditorOptions; property OnCloseFile : TNotifyFileEvent read FOnCloseFile write FOnCloseFile; property OnOpenFile : TNotifyFileEvent read FOnOPenFile write FOnOPenFile; @@ -274,6 +277,7 @@ const var Editor_Num : Integer; aHighlighter: TSynPasSyn; + aCompletion : TSynCompletion; { TSourceEditor } @@ -605,6 +609,8 @@ end; Function TSourceEditor.StartFind : Boolean; Begin Result := False; + //setup the find dialog + if not Assigned(FindDialog1) then FindDialog1 := TFindDialog.Create(nil); @@ -614,7 +620,9 @@ Begin FindText := uppercase(FindDialog1.edtTextToFind.Text); Result := FindAgain(1,0); - end; + end + else + Exit; if not Result then Application.MessageBox('Search String not found.','Not Found',mb_OK); @@ -802,23 +810,43 @@ Begin end; +Function TSourceEditor.RefreshEditorSettings : Boolean; +Begin + Result := False; + + if EditorOPts.UseSyntaxHighlight then + Begin + EditorOPts.GetHighlighterSettings(aHighlighter); + FEditor.Highlighter:=aHighlighter; + end + else + FEditor.Highlighter:=nil; + + + + with FSynAutoComplete do begin + if FileExists(EditorOPts.CodeTemplateFilename) then + AutoCompleteList.LoadFromFile(EditorOPts.CodeTemplateFilename) + else + if FileExists('lazarus.dci') then + AutoCompleteList.LoadFromFile('lazarus.dci'); + + end; + + EditorOpts.GetSynEditSettings(FEditor); +end; + + Procedure TSourceEditor.CreateEditor(AOwner : TComponent; AParent: TWinControl); Begin -if assigned(FEditor) then + if assigned(FEditor) then Begin FSource.Assign(FEditor.Lines); FEditor.Free; end; -{SynEdit} FSynAutoComplete:=TSynAutoComplete.Create(FAOwner); - with FSynAutoComplete do begin - if FileExists(SetDirSeparators(GetPrimaryConfigPath+'/lazarus.dci')) then - AutoCompleteList.LoadFromFile(SetDirSeparators(GetPrimaryConfigPath+'/lazarus.dci')) - else - AutoCompleteList.LoadFromFile('lazarus.dci'); - end; FEditor:=TSynEdit.Create(FAOwner); with FEditor do @@ -828,7 +856,6 @@ if assigned(FEditor) then Parent := AParent; SetBounds(0,25,TWinControl(FAOwner).ClientWidth - 10,TWinControl(FAOwner).ClientHeight -10); Align := alClient; - Highlighter:=aHighlighter; Gutter.Color:=clBlue; AddKey(ecAutoCompletion, word('J'), [ssCtrl], 0, []); AddKey(ecFind, word('F'), [ssCtrl], 0, []); @@ -847,10 +874,11 @@ if assigned(FEditor) then Show; end; FSynAutoComplete.AddEditor(FEditor); -{SynEdit} + RefreshEditorSettings; + aCompletion.Editor := FEditor; -FEditor.Lines.Assign(FSource); -FEditor.Setfocus + FEditor.Lines.Assign(FSource); + FEditor.Setfocus end; Procedure TSourceEditor.AddControlCode(_Control : TComponent); @@ -1249,6 +1277,16 @@ begin SymbolAttri.ForeGround:=clBlack; end; + + aCompletion := TSynCompletion.Create(AOwner); + with aCompletion do + Begin + + + + end; + + StatusBar := TStatusBar.Create(self); with Statusbar do begin @@ -1479,8 +1517,8 @@ Begin end; End; -//TempEditor now is the editor on the active page -//Compare it to the editor help by the SourceEditors + // TempEditor now is the editor on the active page + // Compare it to the editor help by the SourceEditors I := 0; while TSourceEditor(FSourceEditorList[I]).Editor <> TempEditor do inc(i); @@ -1800,6 +1838,15 @@ begin end; //case end; +Procedure TSourceNotebook.ReloadEditorOptions; +var + I : integer; +Begin + //this reloads the colrs for the highlighter and other settings. + for I := 0 to FSourceEditorList.Count-1 do + TSOurceEditor(FSourceEditorList.Items[i]).RefreshEditorSettings; +end; + initialization Editor_Num := 0; diff --git a/lcl/controls.pp b/lcl/controls.pp index aa25e3db95..43e85f03ea 100644 --- a/lcl/controls.pp +++ b/lcl/controls.pp @@ -423,6 +423,7 @@ TCMDialogKey = TLMKEY; FControlState: TControlState; Procedure AdjustSize; dynamic; { events need to be protected otherwise they can't be overridden ??} + Procedure Changed; procedure WMLButtonDown(Var Message: TLMLButtonDown); message LM_LBUTTONDOWN; procedure WMRButtonDown(Var Message: TLMRButtonDown); message LM_RBUTTONDOWN; procedure WMMButtonDown(Var Message: TLMMButtonDown); message LM_MBUTTONDOWN; @@ -1124,6 +1125,10 @@ end. { ============================================================================= $Log$ + Revision 1.11 2001/02/01 16:45:19 lazarus + Started the code completion. + Shane + Revision 1.10 2001/01/23 23:33:54 lazarus MWE: - Removed old LM_InvalidateRect diff --git a/lcl/forms.pp b/lcl/forms.pp index abac5876fb..6481e87eff 100644 --- a/lcl/forms.pp +++ b/lcl/forms.pp @@ -47,6 +47,10 @@ type TWindowState = (wsNormal, wsMinimized, wsMaximized); TCloseAction = (caNone, caHide, caFree, caMinimize); + TScrollBarKind = (sbHorizontal, sbVertical); + TScrollBarInc = 1..32768; + TScrollBarStyle = (ssRegular, ssFlat, ssHotTrack); + TControlScrollBar = class(TPersistent) end; @@ -78,6 +82,7 @@ type FModalResult : TModalResult; FOnActivate: TNotifyEvent; FOnCreate: TNotifyEvent; + FOnDeactivate : TNotifyEvent; FOnDestroy: TNotifyEvent; FOnHide: TNotifyEvent; FOnShow: TNotifyEvent; @@ -111,6 +116,7 @@ type function CloseQuery : boolean; virtual; procedure CreateParams(var Params: TCreateParams); override; procedure CreateWnd; override; + Procedure DeActivate; dynamic; procedure DoClose(var Action: TCloseAction); dynamic; procedure DoHide; dynamic; procedure DoShow; dynamic; @@ -129,6 +135,7 @@ type {events} property OnActivate: TNotifyEvent read FOnActivate write FOnActivate; property OnCreate: TNotifyEvent read FOnCreate write FOnCreate; + property OnDeactivate: TNotifyEvent read FOnDeactivate write FOnDeactivate; property OnDestroy: TNotifyEvent read FOnDestroy write FOnDestroy; property OnHide: TNotifyEvent read FOnHide write FOnHide; property OnShow: TNotifyEvent read FOnShow write FOnShow; @@ -181,6 +188,7 @@ type // property WindowState; property OnActivate; property OnCreate; + property OnDeactivate; property OnDestroy; property OnShow; property OnHide; diff --git a/lcl/include/control.inc b/lcl/include/control.inc index 0fae2ab6d2..ad06d28682 100644 --- a/lcl/include/control.inc +++ b/lcl/include/control.inc @@ -74,6 +74,16 @@ begin SetZOrder(True); end; +{------------------------------------------------------------------------------} +{ TControl.Change +} +{------------------------------------------------------------------------------} +Procedure TControl.Changed; +Begin + Perform(CM_CHANGED,0,Longint(self)); +End; + + {------------------------------------------------------------------------------} { TControl.ChangeScale } @@ -1273,6 +1283,10 @@ end; { ============================================================================= $Log$ + Revision 1.10 2001/02/01 16:45:19 lazarus + Started the code completion. + Shane + Revision 1.9 2001/01/09 18:23:20 lazarus Worked on moving controls. It's just not working with the X and Y coord's I'm getting. Shane diff --git a/lcl/include/customform.inc b/lcl/include/customform.inc index dc9b4e3354..751264181a 100644 --- a/lcl/include/customform.inc +++ b/lcl/include/customform.inc @@ -71,6 +71,19 @@ begin inherited Destroy; end; +{------------------------------------------------------------------------------ + Method: TCustomForm.Deactivate + Params: None + Returns: Nothing + + + ------------------------------------------------------------------------------} +Procedure TCustomForm.Deactivate; +Begin + if Assigned(FOnDeactivate) then + FOnDeactivate(Self); +end; + {------------------------------------------------------------------------------ Method: TCustomForm.Notification @@ -825,6 +838,10 @@ end; { ============================================================================= $Log$ + Revision 1.10 2001/02/01 16:45:20 lazarus + Started the code completion. + Shane + Revision 1.9 2001/01/12 18:46:50 lazarus Named the speedbuttons in MAINIDE and took out some writelns. Shane diff --git a/lcl/include/scrollbar.inc b/lcl/include/scrollbar.inc index f0bd09f659..bd79e1d2fb 100644 --- a/lcl/include/scrollbar.inc +++ b/lcl/include/scrollbar.inc @@ -2,9 +2,191 @@ { function TScrollBar.Create } {------------------------------------------------------------------------------} + +{ TScrollBar } + constructor TScrollBar.Create(AOwner: TComponent); begin - inherited Create(AOwner); -// FCompStlye := csVScrollBar; - fOwner := TControl(AOwner); + inherited Create(AOwner); + fCompStyle := csScrollBar; + Width := 121; + Height := GetSystemMetrics(SM_CYHSCROLL); + TabStop := True; + ControlStyle := [csFramed, csDoubleClicks, csOpaque]; + FKind := sbHorizontal; + FPosition := 0; + FMin := 0; + FMax := 100; + FSmallChange := 1; + FLargeChange := 1; +end; + +procedure TScrollBar.CreateParams(var Params: TCreateParams); +const + Kinds: array[TScrollBarKind] of DWORD = (SBS_HORZ, SBS_VERT); +begin + inherited CreateParams(Params); + CreateSubClass(Params, 'SCROLLBAR'); + Params.Style := Params.Style or Kinds[FKind]; + if FKind = sbVertical then + Params.Style := Params.Style or SBS_LEFTALIGN; + FRTLFactor := 1 +end; + +procedure TScrollBar.CreateWnd; +var + ScrollInfo: TScrollInfo; +begin + inherited CreateWnd; + SetScrollRange(Handle, SB_CTL, FMin, FMax, False); + ScrollInfo.cbSize := SizeOf(ScrollInfo); + ScrollInfo.nPage := FPageSize; + ScrollInfo.fMask := SIF_PAGE; + SetScrollInfo(Handle, SB_CTL, ScrollInfo, False); + if NotRightToLeft then + SetScrollPos(Handle, SB_CTL, FPosition, True) + else + SetScrollPos(Handle, SB_CTL, FMax - FPosition, True); +end; + +function TScrollBar.NotRightToLeft: Boolean; +begin + Result := True; +end; + +procedure TScrollBar.SetKind(Value: TScrollBarKind); +begin + if FKind <> Value then + begin + FKind := Value; + if not (csLoading in ComponentState) then SetBounds(Left, Top, Height, Width); + RecreateWnd; + end; +end; + +procedure TScrollBar.SetParams(APosition, AMin, AMax: Integer); +begin + if AMax < AMin then + raise EInvalidOperation.Create(SScrollBarRange); + if APosition < AMin then APosition := AMin; + if APosition > AMax then APosition := AMax; + if (FMin <> AMin) or (FMax <> AMax) then + begin + FMin := AMin; + FMax := AMax; + if HandleAllocated then + SetScrollRange(Handle, SB_CTL, AMin, AMax, FPosition = APosition); + end; + if FPosition <> APosition then + begin + FPosition := APosition; + if HandleAllocated then + if NotRightToLeft then + SetScrollPos(Handle, SB_CTL, FPosition, True) + else + SetScrollPos(Handle, SB_CTL, FMax - FPosition, True); + Change; + end; +end; + +procedure TScrollBar.SetPosition(Value: Integer); +begin + SetParams(Value, FMin, FMax); +end; + +procedure TScrollBar.SetPageSize(Value: Integer); +var + ScrollInfo: TScrollInfo; +begin + if (FPageSize = Value) or (FPageSize > FMax) then exit; + FPageSize := Value; + ScrollInfo.cbSize := SizeOf(ScrollInfo); + ScrollInfo.nPage := Value; + ScrollInfo.fMask := SIF_PAGE; + if HandleAllocated then + SetScrollInfo(Handle, SB_CTL, ScrollInfo, True); +end; + +procedure TScrollBar.SetMin(Value: Integer); +begin + SetParams(FPosition, Value, FMax); +end; + +procedure TScrollBar.SetMax(Value: Integer); +begin + SetParams(FPosition, FMin, Value); +end; + +procedure TScrollBar.Change; +begin + inherited Changed; + if Assigned(FOnChange) then FOnChange(Self); +end; + +procedure TScrollBar.Scroll(ScrollCode: TScrollCode; var ScrollPos: Integer); +begin + if Assigned(FOnScroll) then FOnScroll(Self, ScrollCode, ScrollPos); +end; + +procedure TScrollBar.DoScroll(var Message: TLMScroll); +var + ScrollPos: Integer; + NewPos: Longint; + ScrollInfo: TScrollInfo; +begin + with Message do + begin + NewPos := FPosition; + case TScrollCode(ScrollCode) of + scLineUp: + Dec(NewPos, FSmallChange * FRTLFactor); + scLineDown: + Inc(NewPos, FSmallChange * FRTLFactor); + scPageUp: + Dec(NewPos, FLargeChange * FRTLFactor); + scPageDown: + Inc(NewPos, FLargeChange * FRTLFactor); + scPosition, scTrack: + with ScrollInfo do + begin + cbSize := SizeOf(ScrollInfo); + fMask := SIF_ALL; + GetScrollInfo(Handle, SB_CTL, ScrollInfo); + NewPos := nTrackPos; + { We need to reverse the positioning because SetPosition below + calls SetParams that reverses the position. This acts as a + double negative. } + if not NotRightToLeft then NewPos := FMax - NewPos; + end; + scTop: + NewPos := FMin; + scBottom: + NewPos := FMax; + end; + if NewPos < FMin then NewPos := FMin; + if NewPos > FMax then NewPos := FMax; + ScrollPos := NewPos; + Scroll(TScrollCode(ScrollCode), ScrollPos); + SetPosition(ScrollPos); + end; +end; + +procedure TScrollBar.CNHScroll(var Message: TLMHScroll); +begin + DoScroll(Message); +end; + +procedure TScrollBar.CNVScroll(var Message: TLMVScroll); +begin + DoScroll(Message); +end; + +procedure TScrollBar.CNCtlColorScrollBar(var Message: TLMessage); +begin +//CallWIndowProc is not yet created so no code is here +end; + +procedure TScrollBar.WMEraseBkgnd(var Message: TLMEraseBkgnd); +begin + DefaultHandler(Message); end; diff --git a/lcl/lcllinux.pp b/lcl/lcllinux.pp index 12b5844dee..ab910aa1dc 100644 --- a/lcl/lcllinux.pp +++ b/lcl/lcllinux.pp @@ -454,6 +454,16 @@ Region_Error = Error; SB_RIGHT = 7; SB_ENDSCROLL = 8; + SBS_HORZ = 0; + SBS_VERT = 1; + SBS_TOPALIGN = 2; + SBS_LEFTALIGN = 2; + SBS_BOTTOMALIGN = 4; + SBS_RIGHTALIGN = 4; + SBS_SIZEBOXTOPLEFTALIGN = 2; + SBS_SIZEBOXBOTTOMRIGHTALIGN = 4; + SBS_SIZEBOX = 8; + SBS_SIZEGRIP = $10; SIF_Range = 1; SIF_PAGE = 2; @@ -1361,6 +1371,10 @@ end. { $Log$ + Revision 1.5 2001/02/01 16:45:19 lazarus + Started the code completion. + Shane + Revision 1.4 2000/09/10 23:08:30 lazarus MWE: + Added CreateCompatibeleBitamp function diff --git a/lcl/stdctrls.pp b/lcl/stdctrls.pp index cf297ca75e..911f051fa6 100644 --- a/lcl/stdctrls.pp +++ b/lcl/stdctrls.pp @@ -37,13 +37,81 @@ uses vclglobals, classes, sysutils, Graphics, LMessages, Controls, forms; type TEditCharCase = (ecNormal, ecUppercase, ecLowerCase); TScrollStyle = (ssNone, ssHorizontal, ssVertical, ssBoth); - TScrollBar = class(TWinControl) - private - fOwner: TControl; - public - constructor Create(AOwner: TComponent); override; - end; + TScrollCode = (scLineUp, scLineDown, scPageUp, scPageDown, scPosition, + scTrack, scTop, scBottom, scEndScroll); + + TScrollEvent = procedure(Sender: TObject; ScrollCode: TScrollCode; + var ScrollPos: Integer) of object; + + + TScrollBar = class(TWinControl) + private + FKind: TScrollBarKind; + FPosition: Integer; + FMin: Integer; + FMax: Integer; + FPageSize: Integer; + FRTLFactor: Integer; + FSmallChange: TScrollBarInc; + FLargeChange: TScrollBarInc; + FOnChange: TNotifyEvent; + FOnScroll: TScrollEvent; + procedure DoScroll(var Message: TLMScroll); + function NotRightToLeft: Boolean; + procedure SetKind(Value: TScrollBarKind); + procedure SetMax(Value: Integer); + procedure SetMin(Value: Integer); + procedure SetPosition(Value: Integer); + procedure SetPageSize(Value: Integer); + procedure CNHScroll(var Message: TLMHScroll); message CN_HSCROLL; + procedure CNVScroll(var Message: TLMVScroll); message CN_VSCROLL; + procedure CNCtlColorScrollBar(var Message: TLMessage); message CN_CTLCOLORSCROLLBAR; + procedure WMEraseBkgnd(var Message: TLMEraseBkgnd); message LM_ERASEBKGND; + protected + procedure CreateParams(var Params: TCreateParams); override; + procedure CreateWnd; override; + procedure Change; dynamic; + procedure Scroll(ScrollCode: TScrollCode; var ScrollPos: Integer); dynamic; + public + constructor Create(AOwner: TComponent); override; + procedure SetParams(APosition, AMin, AMax: Integer); + published + property Align; + property Anchors; + property Ctl3D; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property Kind: TScrollBarKind read FKind write SetKind default sbHorizontal; + property LargeChange: TScrollBarInc read FLargeChange write FLargeChange default 1; + property Max: Integer read FMax write SetMax default 100; + property Min: Integer read FMin write SetMin default 0; + property PageSize: Integer read FPageSize write SetPageSize; + property ParentCtl3D; + property ParentShowHint; + property PopupMenu; + property Position: Integer read FPosition write SetPosition default 0; + property ShowHint; + property SmallChange: TScrollBarInc read FSmallChange write FSmallChange default 1; + property TabOrder; + property TabStop default True; + property Visible; + property OnChange: TNotifyEvent read FOnChange write FOnChange; + property OnDragDrop; + property OnDragOver; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnScroll: TScrollEvent read FOnScroll write FOnScroll; + property OnStartDrag; + end; + + TCustomGroupBox = class (TWinControl) {class(TCustomControl) } public @@ -432,6 +500,8 @@ type implementation {*******} +uses LCLLinux; + type TSelection = record @@ -472,6 +542,10 @@ var aColors : Array[1..10] of TColor; ColorNum : Integer; +const + + SScrollBarRange = 'ScrollBar property out of range'; + {$I customgroupbox.inc} {$I customcombobox.inc} {$I customlistbox.inc} @@ -495,6 +569,10 @@ end. { ============================================================================= $Log$ + Revision 1.12 2001/02/01 16:45:19 lazarus + Started the code completion. + Shane + Revision 1.11 2001/01/28 21:06:07 lazarus Changes for TComboBox events KeyPress Focus. Shane diff --git a/lcl/vclglobals.pp b/lcl/vclglobals.pp index dd11c436d4..03b10e8920 100644 --- a/lcl/vclglobals.pp +++ b/lcl/vclglobals.pp @@ -45,7 +45,7 @@ csEdit = 6; csForm= 7; csLabel = 8; csgtkTable = 9; -csHScrollBar = 10; +csScrollBar = 10; csListView = 11; csMainForm = 12; csMemo = 13; @@ -60,7 +60,7 @@ csSpinedit = 21; csStatusBar = 22; csTable = 23; csToggleBox = 24; -csVScrollBar = 25; +//csVScrollBar = 25; csFrame = 26; csButtonBox = 27; csCanvas = 28;