{"id":1281,"date":"2014-04-22T22:15:53","date_gmt":"2014-04-22T21:15:53","guid":{"rendered":"http:\/\/tulip-ui.azurewebsites.net\/?page_id=1281"},"modified":"2014-04-22T23:13:21","modified_gmt":"2014-04-22T22:13:21","slug":"tulip-ui-editboxes-pas","status":"publish","type":"page","link":"https:\/\/tulip-ui.azurewebsites.net\/?page_id=1281","title":{"rendered":"Tulip.UI.EditBoxes.pas"},"content":{"rendered":"<div style=\"background-color: #FFFFFF; width: 680px\">\n<p style=\"text-align: right;\"><a title=\"Source Files\" href=\"http:\/\/tulip-ui.azurewebsites.net\/?page_id=1091\">Source Files<\/a><\/p>\n<p><code><\/p>\n<pre>\r\n{******************************************************************************}\r\n{                                                                              }\r\n{                        Tulip - User Interface Library                        }\r\n{                                                                              }\r\n{         Copyright(c) 2012 - 2013 Marcos Gomes. All rights Reserved.          }\r\n{                                                                              }\r\n{  --------------------------------------------------------------------------  }\r\n{                                                                              }\r\n{  This product is based on Asphyre Sphinx (c) 2000 - 2012  Yuriy Kotsarenko.  }\r\n{       All rights reserved. Official web site: http:\/\/www.afterwarp.net       }\r\n{                                                                              }\r\n{******************************************************************************}\r\n{                                                                              }\r\n{  Important Notice:                                                           }\r\n{                                                                              }\r\n{  If you modify\/use this code or one of its parts either in original or       }\r\n{  modified form, you must comply with Mozilla Public License Version 2.0,     }\r\n{  including section 3, \"Responsibilities\". Failure to do so will result in    }\r\n{  the license breach, which will be resolved in the court. Remember that      }\r\n{  violating author's rights either accidentally or intentionally is           }\r\n{  considered a serious crime in many countries. Thank you!                    }\r\n{                                                                              }\r\n{  !! Please *read* Mozilla Public License 2.0 document located at:            }\r\n{  http:\/\/www.mozilla.org\/MPL\/                                                 }\r\n{                                                                              }\r\n{  --------------------------------------------------------------------------  }\r\n{                                                                              }\r\n{  The contents of this file are subject to the Mozilla Public License         }\r\n{  Version 2.0 (the \"License\"); you may not use this file except in            }\r\n{  compliance with the License. You may obtain a copy of the License at        }\r\n{  http:\/\/www.mozilla.org\/MPL\/                                                 }\r\n{                                                                              }\r\n{  Software distributed under the License is distributed on an \"AS IS\"         }\r\n{  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the     }\r\n{  License for the specific language governing rights and limitations          }\r\n{  under the License.                                                          }\r\n{                                                                              }\r\n{  The Original Code is Tulip.UI.EditBoxes.pas.                                }\r\n{                                                                              }\r\n{  The Initial Developer of the Original Code is Marcos Gomes.                 }\r\n{  Portions created by Marcos Gomes are Copyright (C) 2012, Marcos Gomes.      }\r\n{  All Rights Reserved.                                                        }\r\n{                                                                              }\r\n{******************************************************************************}\r\n{                                                                              }\r\n{  Tulip.UI.EditBoxes.pas                               Modified: 23-Mar-2013  }\r\n{  --------------------------------------------------------------------------  }\r\n{                                                                              }\r\n{                   Base Implementations for EditBox Controls                  }\r\n{                                                                              }\r\n{                                Version 1.03                                  }\r\n{                                                                              }\r\n{******************************************************************************}\r\n\r\nunit Tulip.UI.EditBoxes;\r\n\r\ninterface\r\n\r\nuses\r\n  Winapi.Windows, System.SysUtils, System.Classes, System.Math,\r\n  \/\/ Asphyre Units\r\n  AbstractCanvas, AsphyreFonts, AsphyreImages, AsphyreTypes, AsphyreUtils,\r\n  Vectors2,\r\n  \/\/ Tulip UI Units\r\n  Tulip.UI.Types, Tulip.UI.Classes, Tulip.UI.Controls, Tulip.UI.Helpers,\r\n  Tulip.UI.Utils;\r\n\r\ntype\r\n{$REGION 'TCustomAEditBox'}\r\n  TCustomAEditBox = class(TWControl)\r\n  private\r\n    FAntialiased: Boolean;\r\n    FAutoSelect: Boolean;\r\n    FBorder: TBorder;\r\n    FColor: TFillColor;\r\n    FFocusRect: TFocusRect;\r\n    FFont: TEditFont;\r\n    FImage: TImage;\r\n    FMargin: Word;\r\n    FMaxLength: Integer;\r\n    FOnChange: TNotifyEvent;\r\n    FReadOnly: Boolean;\r\n    FSelection: TSelection;\r\n    FText: String;\r\n    FVirtualPosition: Integer;\r\n\r\n    function GetTic: Integer;\r\n\r\n    procedure SetAntialiased(Value: Boolean);\r\n    procedure SetAutoSelect(Value: Boolean);\r\n    procedure SetBorder(Value: TBorder);\r\n    procedure SetColor(Value: TFillColor);\r\n    procedure SetFocusRect(Value: TFocusRect);\r\n    procedure SetFont(Value: TEditFont);\r\n    procedure SetImage(Value: TImage);\r\n    procedure SetMargin(Value: Word);\r\n    procedure SetMaxLength(Value: Integer);\r\n    procedure SetReadOnly(Value: Boolean);\r\n\r\n    \/\/ procedure SetSelLength(Value: Integer);\r\n    \/\/ procedure SetSelStart(Value: Integer);\r\n    \/\/ procedure SetSelText(Value: String);\r\n\r\n    procedure SetText(Value: String);\r\n  protected\r\n    procedure AssignTo(Dest: TPersistent); override;\r\n    procedure Change; dynamic;\r\n    procedure Paint; override;\r\n  public\r\n    constructor Create(AOwner: TComponent); override;\r\n    destructor Destroy; override;\r\n\r\n    function GetSelLength: Integer;\r\n    function GetSelStart: Integer;\r\n    function GetSelText: string;\r\n\r\n    procedure Clear;\r\n    procedure ClearSelection;\r\n\r\n    procedure CopyToClipboard;\r\n    procedure CutToClipboard;\r\n    procedure PasteFromClipboard;\r\n    procedure SelectAll;\r\n\r\n    procedure DoEnter; override;\r\n    procedure DoExit; override;\r\n    procedure KeyDown(var Key: Word; Shift: TShiftState); override;\r\n    procedure KeyPress(var Key: Char); override;\r\n    procedure MouseEnter; override;\r\n    procedure MouseLeave; override;\r\n    procedure MouseDown(Button: TMouseButton; Shift: TShiftState;\r\n      X, Y: Integer); override;\r\n    procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;\r\n\r\n    property Antialiased: Boolean read FAntialiased write SetAntialiased;\r\n    property AutoSelect: Boolean read FAutoSelect write SetAutoSelect;\r\n    property Border: TBorder read FBorder write SetBorder;\r\n    property Color: TFillColor read FColor write SetColor;\r\n    property FocusRect: TFocusRect read FFocusRect write SetFocusRect;\r\n    property Font: TEditFont read FFont write SetFont;\r\n    property Image: TImage read FImage write SetImage;\r\n    property Margin: Word read FMargin write SetMargin;\r\n    property MaxLength: Integer read FMaxLength write SetMaxLength;\r\n    property OnChange: TNotifyEvent read FOnChange write FOnChange;\r\n    property ReadOnly: Boolean read FReadOnly write SetReadOnly;\r\n    property Text: String read FText write SetText;\r\n  end;\r\n{$ENDREGION}\r\n\r\nimplementation\r\n\r\nuses\r\n  Tulip.UI;\r\n\r\nvar\r\n  Tic: Byte;\r\n  Counter: Cardinal;\r\n\r\n{$REGION 'TCustomAEditBox'}\r\n  { TCustomAEditBox }\r\n\r\nprocedure TCustomAEditBox.AssignTo(Dest: TPersistent);\r\nbegin\r\n  ControlState := ControlState + [csReadingState];\r\n\r\n  inherited AssignTo(Dest);\r\n\r\n  if Dest is TCustomAEditBox then\r\n    with TCustomAEditBox(Dest) do\r\n    begin\r\n      Antialiased := Self.Antialiased;\r\n      AutoSelect := Self.AutoSelect;\r\n      Border := Self.Border;\r\n      Color := Self.Color;\r\n      FocusRect := Self.FocusRect;\r\n      Font := Self.Font;\r\n      Image := Self.Image;\r\n      MaxLength := Self.MaxLength;\r\n      ReadOnly := Self.ReadOnly;\r\n      Text := Self.Text;\r\n    end;\r\n\r\n  ControlState := ControlState - [csReadingState];\r\nend;\r\n\r\nprocedure TCustomAEditBox.Change;\r\nbegin\r\n  if Assigned(FOnChange) then\r\n    FOnChange(Self);\r\nend;\r\n\r\nprocedure TCustomAEditBox.Clear;\r\nbegin\r\n  Text := '';\r\n  Change;\r\nend;\r\n\r\nprocedure TCustomAEditBox.ClearSelection;\r\nbegin\r\n  FSelection.StartPos := 0;\r\n  FSelection.EndPos := 0;\r\nend;\r\n\r\nprocedure TCustomAEditBox.CopyToClipboard;\r\nbegin\r\n  (ControlManager as TAControlManager).GetClipboard.SetTextBuf\r\n    (PChar(GetSelText));\r\nend;\r\n\r\nconstructor TCustomAEditBox.Create(AOwner: TComponent);\r\nvar\r\n  Num: Integer;\r\nbegin\r\n  ControlState := ControlState + [csCreating];\r\n\r\n  inherited Create(AOwner);\r\n\r\n  if (AOwner <> nil) and (AOwner <> Self) and (AOwner is TWControl) then\r\n  begin\r\n    \/\/ Auto generate name\r\n    Num := 1;\r\n    begin\r\n      while AOwner.FindComponent('EditBox' + IntToStr(Num)) <> nil do\r\n        Inc(Num);\r\n      Name := 'EditBox' + IntToStr(Num);\r\n    end;\r\n  end;\r\n\r\n  FAntialiased := True;\r\n  FAutoSelect := True;\r\n  FBorder := TBorder.Create;\r\n  FBorder.Color := $B0FFFFFF;\r\n  FBorder.Size := 1;\r\n  FColor := TFillColor.Create($FF4090F0, $FF4090F0, $FF6EAAF4, $FF6EAAF4);\r\n  FFocusRect := fDark;\r\n  FFont := TEditFont.Create;\r\n  FImage := TImage.Create;\r\n  FMargin := 2;\r\n  FMaxLength := 0;\r\n  FReadOnly := False;\r\n  FSelection.StartPos := 0;\r\n  FSelection.EndPos := 0;\r\n  FText := '';\r\n\r\n  \/\/ Properties\r\n  Left := 0;\r\n  Top := 0;\r\n  Width := 120;\r\n  Height := 24;\r\n  TabStop := True;\r\n  Visible := True;\r\n\r\n  Tic := 0;\r\n  Counter := GetTickCount;\r\n\r\n  ControlState := ControlState - [csCreating];\r\nend;\r\n\r\nprocedure TCustomAEditBox.CutToClipboard;\r\nvar\r\n  AText: String;\r\n  AMin, AMax, ALength: Integer;\r\nbegin\r\n  \/\/ Set initial values\r\n  AText := Text;\r\n\r\n  AMin := Min(FSelection.StartPos, FSelection.EndPos);\r\n  AMax := Max(FSelection.StartPos, FSelection.EndPos);\r\n\r\n  ALength := AMax - AMin;\r\n\r\n  \/\/ Copy to Clipboard\r\n  CopyToClipboard;\r\n\r\n  Delete(AText, AMin + 1, ALength);\r\n  Text := AText;\r\n  \/\/ Execute OnChange Event\r\n  Change;\r\n\r\n  FSelection.StartPos := AMin;\r\n  FSelection.EndPos := AMin;\r\nend;\r\n\r\ndestructor TCustomAEditBox.Destroy;\r\nbegin\r\n  FBorder.Free;\r\n  FColor.Free;\r\n  FFont.Free;\r\n  FImage.Free;\r\n\r\n  inherited;\r\nend;\r\n\r\nprocedure TCustomAEditBox.DoEnter;\r\nbegin\r\n  Tic := 0;\r\n\r\n  if FAutoSelect then\r\n    SelectAll;\r\n\r\n  inherited;\r\nend;\r\n\r\nprocedure TCustomAEditBox.DoExit;\r\nbegin\r\n  ClearSelection;\r\n  inherited;\r\nend;\r\n\r\nfunction TCustomAEditBox.GetSelLength: Integer;\r\nvar\r\n  AMin, AMax: Integer;\r\nbegin\r\n  AMin := Min(FSelection.StartPos, FSelection.EndPos);\r\n  AMax := Max(FSelection.StartPos, FSelection.EndPos);\r\n\r\n  Result := AMax - AMin;\r\nend;\r\n\r\nfunction TCustomAEditBox.GetSelStart: Integer;\r\nvar\r\n  AMin: Integer;\r\nbegin\r\n  AMin := Min(FSelection.StartPos, FSelection.EndPos);\r\n\r\n  Result := AMin;\r\nend;\r\n\r\nfunction TCustomAEditBox.GetSelText: string;\r\nvar\r\n  AMin, AMax, ALength: Integer;\r\nbegin\r\n  AMin := Min(FSelection.StartPos, FSelection.EndPos);\r\n  AMax := Max(FSelection.StartPos, FSelection.EndPos);\r\n  ALength := AMax - AMin;\r\n\r\n  Result := Copy(Text, AMin + 1, ALength);\r\nend;\r\n\r\nfunction TCustomAEditBox.GetTic: Integer;\r\nbegin\r\n  \/\/ When the system run continuously for 49.7 days, GetTickCount=0\r\n  if GetTickCount < Counter then\r\n    Counter := GetTickCount;\r\n\r\n  if (GetTickCount - Counter) >= 300 then\r\n  begin\r\n    Counter := GetTickCount;\r\n    Tic := Tic + 1;\r\n  end;\r\n\r\n  if Tic = 4 then\r\n    Tic := 0;\r\n\r\n  Result := Tic;\r\nend;\r\n\r\nprocedure TCustomAEditBox.KeyDown(var Key: Word; Shift: TShiftState);\r\nvar\r\n  AText: String;\r\n  AMin, AMax, ALength: Integer;\r\nbegin\r\n  AText := Text;\r\n\r\n  AMin := Min(FSelection.StartPos, FSelection.EndPos);\r\n  AMax := Max(FSelection.StartPos, FSelection.EndPos);\r\n\r\n  ALength := AMax - AMin;\r\n\r\n  \/\/ shift pressed\r\n  if Shift = [ssShift] then\r\n  begin\r\n    \/\/ user press right key\r\n    if Key = vk_Right then\r\n    begin\r\n      if FSelection.EndPos < Length(Text) then\r\n        Inc(FSelection.EndPos);\r\n    end;\r\n\r\n    \/\/ user press left key\r\n    if Key = vk_Left then\r\n    begin\r\n      if FSelection.EndPos > 0 then\r\n        Dec(FSelection.EndPos);\r\n    end;\r\n\r\n    \/\/ user press home key\r\n    if Key = VK_Home then\r\n    begin\r\n      FSelection.EndPos := 0;\r\n    end;\r\n\r\n    \/\/ user press end key\r\n    if Key = VK_End then\r\n    begin\r\n      FSelection.EndPos := Length(Text);\r\n    end;\r\n  end;\r\n\r\n  \/\/ Shift not pressed\r\n  if Shift <> [ssShift] then\r\n  begin\r\n    \/\/ User press left key\r\n    if (Key = vk_Left) then\r\n    begin\r\n      if FSelection.StartPos = FSelection.EndPos then\r\n      begin\r\n        if FSelection.StartPos > 0 then\r\n        begin\r\n          Dec(FSelection.StartPos);\r\n          FSelection.EndPos := FSelection.StartPos;\r\n        end;\r\n      end\r\n      else if FSelection.StartPos > FSelection.EndPos then\r\n      begin\r\n        FSelection.StartPos := FSelection.EndPos;\r\n      end\r\n      else if FSelection.StartPos < FSelection.EndPos then\r\n      begin\r\n        FSelection.EndPos := FSelection.StartPos;\r\n      end;\r\n    end;\r\n\r\n    \/\/ User press right key\r\n    if (Key = vk_Right) then\r\n    begin\r\n      if FSelection.StartPos = FSelection.EndPos then\r\n      begin\r\n        if FSelection.EndPos < Length(Text) then\r\n        begin\r\n          Inc(FSelection.EndPos);\r\n          FSelection.StartPos := FSelection.EndPos;\r\n        end;\r\n      end\r\n      else if FSelection.StartPos > FSelection.EndPos then\r\n      begin\r\n        FSelection.EndPos := FSelection.StartPos;\r\n      end\r\n      else if FSelection.StartPos < FSelection.EndPos then\r\n      begin\r\n        FSelection.StartPos := FSelection.EndPos;\r\n      end;\r\n    end;\r\n\r\n    \/\/ User press Delete or Backspace\r\n    if ((Key = vk_Back) or (Key = vk_Delete)) and not(ReadOnly) then\r\n    begin\r\n      if ALength > 0 then\r\n      begin\r\n        case Key of\r\n          vk_Back:\r\n            Delete(AText, AMin + 1, ALength);\r\n          vk_Delete:\r\n            Delete(AText, AMin + 1, ALength);\r\n        end;\r\n      end\r\n      else\r\n      begin\r\n        case Key of\r\n          vk_Back:\r\n            begin\r\n              Delete(AText, AMin, 1);\r\n              if AMin > 0 then\r\n                Dec(AMin);\r\n            end;\r\n          vk_Delete:\r\n            Delete(AText, AMin + 1, 1);\r\n        end;\r\n      end;\r\n\r\n      Text := AText;\r\n      \/\/ Execute OnChange Event\r\n      Change;\r\n\r\n      FSelection.StartPos := AMin;\r\n      FSelection.EndPos := AMin;\r\n    end;\r\n\r\n    \/\/ user press home key\r\n    if Key = VK_Home then\r\n    begin\r\n      FSelection.StartPos := 0;\r\n      FSelection.EndPos := 0;\r\n    end;\r\n\r\n    \/\/ user press end key\r\n    if Key = VK_End then\r\n    begin\r\n      FSelection.StartPos := Length(Text);\r\n      FSelection.EndPos := Length(Text);\r\n    end;\r\n  end;\r\n\r\n  Tic := 0;\r\n\r\n  inherited KeyDown(Key, Shift);\r\nend;\r\n\r\nprocedure TCustomAEditBox.KeyPress(var Key: Char);\r\nvar\r\n  AText: String;\r\n  AMin, AMax, ALength: Integer;\r\nbegin\r\n  AText := Text;\r\n\r\n  AMin := Min(FSelection.StartPos, FSelection.EndPos);\r\n  AMax := Max(FSelection.StartPos, FSelection.EndPos);\r\n\r\n  ALength := AMax - AMin;\r\n\r\n  \/\/ Insert Key\r\n  if (Key > #31) and not ReadOnly then\r\n  begin\r\n    Delete(AText, AMin + 1, ALength);\r\n\r\n    Inc(AMin);\r\n    Insert(Key, AText, AMin);\r\n\r\n    Text := AText;\r\n    \/\/ Execute OnChange Event\r\n    Change;\r\n\r\n    if AMin > Length(Text) then\r\n      AMin := Length(Text);\r\n\r\n    FSelection.StartPos := AMin;\r\n    FSelection.EndPos := AMin;\r\n  end;\r\n\r\n  \/\/ Copy to Clipboard\r\n  if Key = #3 then\r\n    CopyToClipboard;\r\n\r\n  \/\/ Paste from Clipboard\r\n  if Key = #22 then\r\n    PasteFromClipboard;\r\n\r\n  \/\/ Cut to Clipboard\r\n  if Key = #24 then\r\n    CutToClipboard;\r\n\r\n  inherited KeyPress(Key);\r\nend;\r\n\r\nprocedure TCustomAEditBox.MouseDown(Button: TMouseButton; Shift: TShiftState;\r\n  X, Y: Integer);\r\nvar\r\n  Index, XPos, AVirtualCursor: Integer;\r\n  AChars: TAChars;\r\n  AFont: TAsphyreFont;\r\nbegin\r\n  Self.SetFocus;\r\n\r\n  AFont := ControlManager.Fonts.Font[FFont.Name];\r\n\r\n  if ssDouble in Shift then\r\n  begin\r\n    SelectAll;\r\n  end\r\n  else if AFont <> nil then\r\n  begin\r\n    \/\/ Get chars from text\r\n    Index := 0;\r\n    SetLength(AChars, Length(Text) + 1);\r\n    while Index < Length(Text) do\r\n    begin\r\n      AChars[Index].Char := Text[Index + 1];\r\n      AChars[Index].Width := Round(AFont.TextWidth(Text[Index + 1]) +\r\n        AFont.Kerning);\r\n      Inc(Index);\r\n    end;\r\n\r\n    \/\/ Set position to 0\r\n    FSelection.StartPos := 0;\r\n    FSelection.EndPos := 0;\r\n\r\n    \/\/ Get virtual Bounds\r\n    XPos := ClientLeft + FBorder.Size + FMargin + FVirtualPosition;\r\n\r\n    \/\/ Set virtual Pos\r\n    AVirtualCursor := XPos;\r\n    for Index := 0 to High(AChars) do\r\n    begin\r\n      if (X > AVirtualCursor) and (X <= AVirtualCursor + AChars[Index].Width)\r\n      then\r\n      begin\r\n        if Index < Length(Text) then\r\n        begin\r\n          FSelection.StartPos := Index + 1;\r\n          FSelection.EndPos := Index + 1;\r\n        end;\r\n        Break;\r\n      end;\r\n      AVirtualCursor := AVirtualCursor + AChars[Index].Width;\r\n\r\n      if (Index = High(AChars)) and (X >= AVirtualCursor) then\r\n      begin\r\n        FSelection.StartPos := Index;\r\n        FSelection.EndPos := Index;\r\n      end;\r\n    end;\r\n\r\n  end;\r\n\r\n  inherited MouseDown(Button, Shift, X, Y);\r\nend;\r\n\r\nprocedure TCustomAEditBox.MouseEnter;\r\nbegin\r\n  \/\/ Change the cursor\r\n  if ControlManager.Parent <> nil then\r\n    (ControlManager as TAControlManager).GetParentAsControl.Cursor := crIBeam;\r\n\r\n  inherited MouseEnter;\r\nend;\r\n\r\nprocedure TCustomAEditBox.MouseLeave;\r\nbegin\r\n  \/\/ Change the cursor\r\n  if ControlManager.Parent <> nil then\r\n    (ControlManager as TAControlManager).GetParentAsControl.Cursor := crDefault;\r\n\r\n  inherited MouseLeave;\r\nend;\r\n\r\nprocedure TCustomAEditBox.MouseMove(Shift: TShiftState; X, Y: Integer);\r\nvar\r\n  Index, XPos, AVirtualCursor: Integer;\r\n  AChars: TAChars;\r\n  AFont: TAsphyreFont;\r\nbegin\r\n  AFont := ControlManager.Fonts.Font[FFont.Name];\r\n\r\n  if (AFont <> nil) and (Shift = [ssLeft]) then\r\n  begin\r\n    \/\/ Get chars from text\r\n    Index := 0;\r\n    SetLength(AChars, Length(Text) + 1);\r\n    while Index < Length(Text) do\r\n    begin\r\n      AChars[Index].Char := Text[Index + 1];\r\n      AChars[Index].Width := Round(AFont.TextWidth(Text[Index + 1]) +\r\n        AFont.Kerning);\r\n      Inc(Index);\r\n    end;\r\n\r\n    \/\/ Set position to 0\r\n    FSelection.EndPos := 0;\r\n\r\n    \/\/ Get virtual Bounds\r\n    XPos := ClientLeft + Border.Size + Margin + FVirtualPosition;\r\n\r\n    \/\/ Set virtual Pos\r\n    AVirtualCursor := XPos;\r\n    for Index := 0 to High(AChars) do\r\n    begin\r\n      if (X > AVirtualCursor) and (X <= AVirtualCursor + AChars[Index].Width)\r\n      then\r\n      begin\r\n        if Index < Length(Text) then\r\n        begin\r\n          FSelection.EndPos := Index + 1;\r\n        end;\r\n        Break;\r\n      end;\r\n      AVirtualCursor := AVirtualCursor + AChars[Index].Width;\r\n\r\n      if (Index = High(AChars)) and (X >= AVirtualCursor) then\r\n      begin\r\n        FSelection.EndPos := Index;\r\n      end;\r\n    end;\r\n  end;\r\n\r\n  inherited MouseMove(Shift, X, Y);\r\nend;\r\n\r\nprocedure TCustomAEditBox.Paint;\r\nvar\r\n  Index, X, Y, AWidth, AHeight, AVirtualCursor: Integer;\r\n  AMin, AMax: Integer;\r\n  AChars: TAChars;\r\n  ARect: TRect;\r\n  bTop, bBottom: TConstraintSize;\r\n  AImage: TAsphyreImage;\r\n  AFont: TAsphyreFont;\r\nbegin\r\n  \/\/ Get size Canvas\r\n  ARect := ControlManager.Canvas.ClipRect;\r\n\r\n  \/\/ Set initial values\r\n  X := ClientLeft;\r\n  Y := ClientTop;\r\n\r\n  ControlManager.Canvas.Antialias := FAntialiased;\r\n\r\n  \/\/ Draw Background\r\n  AImage := ControlManager.Images.Image[FImage.Image];\r\n  if AImage <> nil then\r\n  begin\r\n    ControlManager.Canvas.UseImagePx(AImage, pRect4(FImage.Rect));\r\n    ControlManager.Canvas.TexMap(pRect4(Rect(X, Y, X + Width, Y + Height)),\r\n      cAlpha4(FColor), beNormal);\r\n  end\r\n  else\r\n  begin\r\n    ControlManager.Canvas.FillRect(Rect(X, Y, X + Width, Y + Height),\r\n      cColor4(FColor), beNormal);\r\n  end;\r\n\r\n  \/\/ Draw Border\r\n  if Border.Size > 0 then\r\n  begin\r\n    bTop := 0;\r\n    bBottom := 0;\r\n\r\n    if eTop in Border.Edges then\r\n    begin\r\n      ControlManager.Canvas.FillRect(Rect(X, Y, X + Width, Y + Border.Size),\r\n        Border.Color, beNormal);\r\n      bTop := Border.Size;\r\n    end;\r\n\r\n    if eBottom in Border.Edges then\r\n    begin\r\n      ControlManager.Canvas.FillRect(Rect(X, Y + Height - Border.Size,\r\n        X + Width, Y + Height), Border.Color, beNormal);\r\n      bBottom := Border.Size;\r\n    end;\r\n\r\n    if eLeft in Border.Edges then\r\n      ControlManager.Canvas.FillRect(Rect(X, Y + bTop, X + Border.Size,\r\n        Y + Height - bBottom), Border.Color, beNormal);\r\n\r\n    if eRight in Border.Edges then\r\n      ControlManager.Canvas.FillRect(Rect(X + Width - Border.Size, Y + bTop,\r\n        X + Width, Y + Height - bBottom), Border.Color, beNormal);\r\n  end;\r\n\r\n  \/\/ Draw DisplayText\r\n  AFont := ControlManager.Fonts.Font[FFont.Name];\r\n  if (AFont <> nil) then\r\n  begin\r\n    \/\/ Set Bounds\r\n    X := X + Margin + Border.Size;\r\n    Y := Y + Margin + Border.Size;\r\n    AWidth := Width - Margin * 2 - Border.Size * 2;\r\n    AHeight := Height - Margin * 2 - Border.Size * 2;\r\n\r\n    \/\/ Set Rect Canvas\r\n    ControlManager.Canvas.ClipRect :=\r\n      ShortRect(Rect(X - 1, Y, X + AWidth, Y + AHeight), ARect);\r\n\r\n    \/\/ Get chars from text\r\n    Index := 0;\r\n    SetLength(AChars, Length(Text) + 1);\r\n    while Index < Length(Text) do\r\n    begin\r\n      AChars[Index].Char := Text[Index + 1];\r\n      AChars[Index].Width := Round(AFont.TextWidth(Text[Index + 1]) +\r\n        AFont.Kerning);\r\n      Inc(Index);\r\n    end;\r\n\r\n    \/\/ Set virtual Pos\r\n    AVirtualCursor := 0;\r\n    FVirtualPosition := 0;\r\n    for Index := 0 to FSelection.EndPos - 1 do\r\n    begin\r\n      AVirtualCursor := AVirtualCursor + AChars[Index].Width;\r\n    end;\r\n\r\n    if AVirtualCursor > AWidth then\r\n    begin\r\n      FVirtualPosition := AWidth - AVirtualCursor;\r\n      X := X + FVirtualPosition;\r\n    end;\r\n\r\n    AMin := Min(FSelection.StartPos, FSelection.EndPos);\r\n    AMax := Max(FSelection.StartPos, FSelection.EndPos);\r\n\r\n    \/\/ Draw Text char by char\r\n    for Index := 0 to High(AChars) do\r\n    begin\r\n      \/\/ Draw Selection\r\n      if (Index >= AMin) and (Index < AMax) then\r\n      begin\r\n        if Index = AMin then\r\n          ControlManager.Canvas.FillRect(Rect(X - 1, Y, X + AChars[Index].Width,\r\n            Y + AHeight), cColor4(FFont.SelectionColor), beNormal)\r\n        else\r\n          ControlManager.Canvas.FillRect(Rect(X, Y, X + AChars[Index].Width,\r\n            Y + AHeight), cColor4(FFont.SelectionColor), beNormal);\r\n\r\n        if (Index = AMin) and (Index = (AMax - 1)) then\r\n          ControlManager.Canvas.FillRect\r\n            (Rect(X, Y + 1, X + AChars[Index].Width - 1, Y + AHeight - 1),\r\n            cColor4($25FFFFFF), beNormal)\r\n        else if Index = AMin then\r\n          ControlManager.Canvas.FillRect(Rect(X, Y + 1, X + AChars[Index].Width,\r\n            Y + AHeight - 1), cColor4($25FFFFFF), beNormal)\r\n        else if Index = (AMax - 1) then\r\n          ControlManager.Canvas.FillRect\r\n            (Rect(X, Y + 1, X + AChars[Index].Width - 1, Y + AHeight - 1),\r\n            cColor4($25FFFFFF), beNormal)\r\n        else\r\n          ControlManager.Canvas.FillRect(Rect(X, Y + 1, X + AChars[Index].Width,\r\n            Y + AHeight - 1), cColor4($25FFFFFF), beNormal);\r\n\r\n        AFont.TextOut(Point2(X, Y + (AHeight div 2) - (AFont.FontSize.Y div 2) -\r\n          1), AChars[Index].Char, cColor2($B0FFFFFF), 1.0);\r\n      end\r\n      else\r\n      begin\r\n        AFont.TextOut(Point2(X, Y + (AHeight div 2) - (AFont.FontSize.Y div 2) -\r\n          1), AChars[Index].Char, cColor2(FFont.Color), 1.0);\r\n      end;\r\n\r\n      \/\/ Draw Tic\r\n      if (GetTic <= 1) and (ControlManager.ActiveControl = Self) then\r\n      begin\r\n        if (Index = FSelection.StartPos) and (Index = FSelection.EndPos) then\r\n          ControlManager.Canvas.Line(Point2(X, Y),\r\n            Point2(X, Y + AHeight), clBlack1)\r\n        else if Index = FSelection.EndPos then\r\n          ControlManager.Canvas.Line(Point2(X - 1, Y),\r\n            Point2(X - 1, Y + AHeight), clBlack1);\r\n      end;\r\n\r\n      \/\/ Set Next X position\r\n      X := X + AChars[Index].Width;\r\n    end;\r\n\r\n    \/\/ Set Rect Canvas\r\n    ControlManager.Canvas.ClipRect := ARect;\r\n  end;\r\n\r\n  \/\/ Set initial values\r\n  X := ClientLeft;\r\n  Y := ClientTop;\r\n\r\n  \/\/ Draw Focus rect\r\n  if (ControlManager.ActiveControl = Self) and (Self.FocusRect = fLight) then\r\n  begin\r\n    ControlManager.Canvas.FrameRect(Rect(X - 1, Y - 1, X + Width + 1,\r\n      Y + Height + 1), cColor4($40FFFFFF), beNormal);\r\n  end;\r\n  if (ControlManager.ActiveControl = Self) and (Self.FocusRect = fDark) then\r\n  begin\r\n    ControlManager.Canvas.FrameRect(Rect(X - 1, Y - 1, X + Width + 1,\r\n      Y + Height + 1), cColor4($20000000), beNormal);\r\n  end;\r\n\r\nend;\r\n\r\nprocedure TCustomAEditBox.PasteFromClipboard;\r\nvar\r\n  AText, CText: String;\r\n  AMin, AMax, ALength: Integer;\r\nbegin\r\n  AText := Text;\r\n\r\n  AMin := Min(FSelection.StartPos, FSelection.EndPos);\r\n  AMax := Max(FSelection.StartPos, FSelection.EndPos);\r\n\r\n  ALength := AMax - AMin;\r\n\r\n  Delete(AText, AMin + 1, ALength);\r\n  CText := (ControlManager as TAControlManager).GetClipboard.AsText;\r\n\r\n  Inc(AMin);\r\n  Insert(CText, AText, AMin);\r\n\r\n  Text := AText;\r\n  \/\/ Execute OnChange Event\r\n  Change;\r\n\r\n  Inc(AMin, Length(CText));\r\n\r\n  if AMin > Length(Text) then\r\n    AMin := Length(Text);\r\n\r\n  FSelection.StartPos := AMin;\r\n  FSelection.EndPos := AMin;\r\nend;\r\n\r\nprocedure TCustomAEditBox.SelectAll;\r\nbegin\r\n  if Enabled then\r\n  begin\r\n    FSelection.StartPos := 0;\r\n    FSelection.EndPos := Length(Text);\r\n  end;\r\nend;\r\n\r\nprocedure TCustomAEditBox.SetAntialiased(Value: Boolean);\r\nbegin\r\n  FAntialiased := Value;\r\nend;\r\n\r\nprocedure TCustomAEditBox.SetAutoSelect(Value: Boolean);\r\nbegin\r\n  FAutoSelect := Value;\r\nend;\r\n\r\nprocedure TCustomAEditBox.SetBorder(Value: TBorder);\r\nbegin\r\n  if Value <> nil then\r\n    FBorder.Assign(Value);\r\nend;\r\n\r\nprocedure TCustomAEditBox.SetColor(Value: TFillColor);\r\nbegin\r\n  if Value <> nil then\r\n    FColor.Assign(Value);\r\nend;\r\n\r\nprocedure TCustomAEditBox.SetFocusRect(Value: TFocusRect);\r\nbegin\r\n  FFocusRect := Value;\r\nend;\r\n\r\nprocedure TCustomAEditBox.SetFont(Value: TEditFont);\r\nbegin\r\n  if Value <> nil then\r\n    FFont.Assign(Value);\r\nend;\r\n\r\nprocedure TCustomAEditBox.SetImage(Value: TImage);\r\nbegin\r\n  if Value <> nil then\r\n    FImage.Assign(Value);\r\nend;\r\n\r\nprocedure TCustomAEditBox.SetMargin(Value: Word);\r\nbegin\r\n  FMargin := Value;\r\nend;\r\n\r\nprocedure TCustomAEditBox.SetMaxLength(Value: Integer);\r\nbegin\r\n  if FMaxLength <> Value then\r\n  begin\r\n    FMaxLength := Value;\r\n    if (Value < Length(Text)) and (Value > 0) then\r\n    begin\r\n      Text := Copy(Text, 0, Value);\r\n    end;\r\n  end;\r\nend;\r\n\r\nprocedure TCustomAEditBox.SetReadOnly(Value: Boolean);\r\nbegin\r\n  FReadOnly := Value;\r\nend;\r\n\r\n\/\/ procedure TCustomAEditBox.SetSelLength(Value: Integer);\r\n\/\/ begin\r\n\/\/ FSelection.EndPos := FSelection.StartPos + Value;\r\n\/\/\r\n\/\/ if FSelection.EndPos > Length(Text) then\r\n\/\/ FSelection.EndPos := Length(Text);\r\n\/\/\r\n\/\/ if FSelection.EndPos < 0 then\r\n\/\/ FSelection.EndPos := 0;\r\n\/\/ end;\r\n\/\/\r\n\/\/ procedure TCustomAEditBox.SetSelStart(Value: Integer);\r\n\/\/ begin\r\n\/\/ if not((Value < 0) and (Value > Length(Text))) then\r\n\/\/ begin\r\n\/\/ FSelection.StartPos := Value;\r\n\/\/ FSelection.EndPos := Value;\r\n\/\/ end;\r\n\/\/ end;\r\n\/\/\r\n\/\/ procedure TCustomAEditBox.SetSelText(Value: String);\r\n\/\/ var\r\n\/\/ AText: String;\r\n\/\/ AMin, AMax, ALength: Integer;\r\n\/\/ begin\r\n\/\/ AText := Text;\r\n\/\/\r\n\/\/ AMin := Min(FSelection.StartPos, FSelection.EndPos);\r\n\/\/ AMax := Max(FSelection.StartPos, FSelection.EndPos);\r\n\/\/\r\n\/\/ ALength := AMax - AMin;\r\n\/\/\r\n\/\/ \/\/ Insert Key\r\n\/\/ Delete(AText, AMin + 1, ALength);\r\n\/\/\r\n\/\/ Inc(AMin);\r\n\/\/ Insert(Value, AText, AMin);\r\n\/\/\r\n\/\/ Text := AText;\r\n\/\/ Change;\r\n\/\/\r\n\/\/ if AMin > Length(Text) then\r\n\/\/ AMin := Length(Text);\r\n\/\/\r\n\/\/ FSelection.StartPos := AMin;\r\n\/\/ FSelection.EndPos := AMin + Length(Value);\r\n\/\/ end;\r\n\r\nprocedure TCustomAEditBox.SetText(Value: String);\r\nbegin\r\n  if (FMaxLength < Length(Value)) and (FMaxLength > 0) then\r\n  begin\r\n    Value := Copy(Value, 0, FMaxLength);\r\n  end;\r\n\r\n  FText := Value;\r\nend;\r\n{$ENDREGION}\r\n\r\nend.\r\n<\/pre>\n<p><\/code>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Source Files {******************************************************************************} { } { Tulip &#8211; User Interface Library } { } { Copyright(c) 2012 &#8211; 2013 Marcos Gomes. All rights Reserved. } { } { &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; } <a class=\"more-link\" href=\"https:\/\/tulip-ui.azurewebsites.net\/?page_id=1281\">Continue Reading &rarr;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":1091,"menu_order":0,"comment_status":"closed","ping_status":"open","template":"","meta":[],"_links":{"self":[{"href":"https:\/\/tulip-ui.azurewebsites.net\/index.php?rest_route=\/wp\/v2\/pages\/1281"}],"collection":[{"href":"https:\/\/tulip-ui.azurewebsites.net\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/tulip-ui.azurewebsites.net\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/tulip-ui.azurewebsites.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tulip-ui.azurewebsites.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1281"}],"version-history":[{"count":2,"href":"https:\/\/tulip-ui.azurewebsites.net\/index.php?rest_route=\/wp\/v2\/pages\/1281\/revisions"}],"predecessor-version":[{"id":1711,"href":"https:\/\/tulip-ui.azurewebsites.net\/index.php?rest_route=\/wp\/v2\/pages\/1281\/revisions\/1711"}],"up":[{"embeddable":true,"href":"https:\/\/tulip-ui.azurewebsites.net\/index.php?rest_route=\/wp\/v2\/pages\/1091"}],"wp:attachment":[{"href":"https:\/\/tulip-ui.azurewebsites.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1281"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}