{"id":1321,"date":"2014-04-22T22:18:42","date_gmt":"2014-04-22T21:18:42","guid":{"rendered":"http:\/\/tulip-ui.azurewebsites.net\/?page_id=1321"},"modified":"2014-04-22T23:16:07","modified_gmt":"2014-04-22T22:16:07","slug":"tulip-ui-listboxes-pas","status":"publish","type":"page","link":"https:\/\/tulip-ui.azurewebsites.net\/?page_id=1321","title":{"rendered":"Tulip.UI.ListBoxes.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.ListBoxes.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.ListBoxes.pas                               Modified: 23-Mar-2013  }\r\n{  --------------------------------------------------------------------------  }\r\n{                                                                              }\r\n{                  Base Implementations for ListBox Controls                   }\r\n{                                                                              }\r\n{                                Version 1.03                                  }\r\n{                                                                              }\r\n{******************************************************************************}\r\n\r\nunit Tulip.UI.ListBoxes;\r\n\r\ninterface\r\n\r\nuses\r\n  Winapi.Windows, System.SysUtils, System.Types, System.Classes, System.Math,\r\n  \/\/ Aspryre units\r\n  AsphyreTypes, AbstractCanvas, AsphyreFonts, AsphyreImages, AsphyreUtils,\r\n  Vectors2,\r\n  \/\/ Tulip UI Units\r\n  Tulip.UI.Classes, Tulip.UI.Types, Tulip.UI.Utils, Tulip.UI.Controls,\r\n  Tulip.UI.Forms, Tulip.UI.Helpers;\r\n\r\ntype\r\n{$REGION 'TCustomAListBox'}\r\n  TCustomAListBox = class(TWControl)\r\n  private\r\n    FAntialiased: Boolean;\r\n    FBorder: TBorder;\r\n    FColor: TFillColor;\r\n    FDownButton: TBtBox;\r\n    FFocusRect: TFocusRect;\r\n    FFont: TEditFont;\r\n    FImage: TImage;\r\n    FIndex: Integer;\r\n    FLineHeight: Integer;\r\n    FMargin: Word;\r\n    FScrollButton: TBtBox;\r\n    FStrings: TAStringList;\r\n    FTransparent: Boolean;\r\n    FUpButton: TBtBox;\r\n\r\n    FVirtualPos: Integer;\r\n\r\n    function GetVirtualHeight: Integer;\r\n    function GetVirtualWidth: Integer;\r\n\r\n    procedure SetAntialiased(Value: Boolean);\r\n    procedure SetBorder(Value: TBorder);\r\n    procedure SetColor(Value: TFillColor);\r\n    procedure SetDownButton(Value: TBtBox);\r\n    procedure SetFocusRect(Value: TFocusRect);\r\n    procedure SetFont(Value: TEditFont);\r\n    procedure SetImage(Value: TImage);\r\n    procedure SetIndex(Value: Integer);\r\n    procedure SetLineHeight(Value: Integer);\r\n    procedure SetMargin(Value: Word);\r\n    procedure SetScrollButton(Value: TBtBox);\r\n    procedure SetStrings(Value: TAStringList);\r\n    procedure SetTransparent(Value: Boolean);\r\n    procedure SetUpButton(Value: TBtBox);\r\n  protected\r\n    procedure AssignTo(Dest: TPersistent); override;\r\n    procedure Paint; override;\r\n    procedure PaintScrollBar;\r\n\r\n    procedure SetHeight(Value: Integer); override;\r\n    procedure SetWidth(Value: Integer); override;\r\n  public\r\n    constructor Create(AOwner: TComponent); override;\r\n    destructor Destroy; override;\r\n\r\n    procedure KeyDown(var Key: Word; Shift: TShiftState); override;\r\n\r\n    procedure MouseLeave; override;\r\n\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    procedure MouseUp(Button: TMouseButton; Shift: TShiftState;\r\n      X, Y: Integer); override;\r\n\r\n    function MouseWheelDown(Shift: TShiftState; MousePos: TPoint)\r\n      : Boolean; override;\r\n    function MouseWheelUp(Shift: TShiftState; MousePos: TPoint)\r\n      : Boolean; override;\r\n\r\n    property Antialiased: Boolean read FAntialiased write SetAntialiased;\r\n    property Border: TBorder read FBorder write SetBorder;\r\n    property Color: TFillColor read FColor write SetColor;\r\n    property DownButton: TBtBox read FDownButton write SetDownButton;\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 ItemIndex: Integer read FIndex write SetIndex;\r\n    property LineHeight: Integer read FLineHeight write SetLineHeight;\r\n    property Lines: TAStringList read FStrings write SetStrings;\r\n    property Margin: Word read FMargin write SetMargin;\r\n    property ScrollButton: TBtBox read FScrollButton write SetScrollButton;\r\n    property Transparent: Boolean read FTransparent write SetTransparent;\r\n    property UpButton: TBtBox read FUpButton write SetUpButton;\r\n  end;\r\n{$ENDREGION}\r\n\r\nimplementation\r\n\r\n{$REGION 'TCustomAListBox'}\r\n{ TCustomAListBox }\r\n\r\nprocedure TCustomAListBox.AssignTo(Dest: TPersistent);\r\nbegin\r\n  ControlState := ControlState + [csReadingState];\r\n\r\n  inherited AssignTo(Dest);\r\n\r\n  if Dest is TCustomAListBox then\r\n    with TCustomAListBox(Dest) do\r\n    begin\r\n      Antialiased := Self.Antialiased;\r\n      Border := Self.Border;\r\n      Color := Self.Color;\r\n      DownButton := Self.DownButton;\r\n      FocusRect := Self.FocusRect;\r\n      Font := Self.Font;\r\n      Image := Self.Image;\r\n      ItemIndex := Self.ItemIndex;\r\n      LineHeight := Self.LineHeight;\r\n      Lines := Self.Lines;\r\n      Margin := Self.Margin;\r\n      ScrollButton := Self.ScrollButton;\r\n      Transparent := Self.Transparent;\r\n      UpButton := Self.UpButton;\r\n    end;\r\n\r\n  ControlState := ControlState - [csReadingState];\r\nend;\r\n\r\nconstructor TCustomAListBox.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    while AOwner.FindComponent('ListBox' + IntToStr(Num)) <> nil do\r\n      Inc(Num);\r\n    Name := 'ListBox' + IntToStr(Num);\r\n  end;\r\n\r\n  \/\/ Set Fields\r\n  FAntialiased := 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  FDownButton := TBtBox.Create;\r\n  FDownButton.Height := 16;\r\n  FDownButton.Width := 16;\r\n  FFocusRect := fDark;\r\n  FFont := TEditFont.Create;\r\n  FImage := TImage.Create;\r\n  FIndex := -1;\r\n  LineHeight := 16;\r\n  FMargin := 1;\r\n  FScrollButton := TBtBox.Create;\r\n  FScrollButton.Height := 16;\r\n  FScrollButton.Width := 16;\r\n  FStrings := TAStringList.Create;\r\n  FTransparent := False;\r\n  FUpButton := TBtBox.Create;\r\n  FUpButton.Height := 16;\r\n  FUpButton.Width := 16;\r\n  FVirtualPos := 0;\r\n\r\n  \/\/ Set Properties\r\n  Self.Left := 0;\r\n  Self.Top := 0;\r\n  Self.Height := 120;\r\n  Self.Width := 120;\r\n  Self.TabStop := True;\r\n\r\n  ControlState := ControlState - [csCreating];\r\nend;\r\n\r\ndestructor TCustomAListBox.Destroy;\r\nbegin\r\n  FBorder.Free;\r\n  FColor.Free;\r\n  FDownButton.Free;\r\n  FFont.Free;\r\n  FImage.Free;\r\n  FScrollButton.Free;\r\n  FStrings.Free;\r\n  FUpButton.Free;\r\n\r\n  inherited;\r\nend;\r\n\r\nfunction TCustomAListBox.GetVirtualHeight: Integer;\r\nbegin\r\n  Result := FLineHeight * FStrings.Count;\r\nend;\r\n\r\nfunction TCustomAListBox.GetVirtualWidth: Integer;\r\nbegin\r\n  Result := Self.Width - (FBorder.Size * 2) - (FMargin * 2) -\r\n    Max(Max(FUpButton.Width, FDownButton.Width), FScrollButton.Width);\r\nend;\r\n\r\nprocedure TCustomAListBox.KeyDown(var Key: Word; Shift: TShiftState);\r\nvar\r\n  H: Integer;\r\n  dLines: Integer;\r\nbegin\r\n  H := Self.Height - FMargin * 2 - FBorder.Size * 2;\r\n  dLines := H div FLineHeight;\r\n\r\n  if Key = VK_UP then\r\n  begin\r\n    if (FStrings.Count > 0) and (FIndex > 0) then\r\n    begin\r\n      Self.ItemIndex := FIndex - 1;\r\n\r\n      if (Abs(FVirtualPos) > FIndex * FLineHeight) then\r\n      begin\r\n        FVirtualPos := -(FIndex * FLineHeight);\r\n      end;\r\n    end;\r\n  end;\r\n\r\n  \/\/ Page_Up pressed\r\n  if Key = VK_PRIOR then\r\n  begin\r\n    if (FStrings.Count > 0) and (FIndex > 0) then\r\n    begin\r\n      Self.ItemIndex := FIndex - dLines;\r\n\r\n      if (Abs(FVirtualPos) > FIndex * FLineHeight) then\r\n      begin\r\n        FVirtualPos := -(FIndex * FLineHeight);\r\n      end;\r\n    end;\r\n  end;\r\n\r\n  if Key = VK_HOME then\r\n  begin\r\n    if (FStrings.Count > 0) and (FIndex > 0) then\r\n    begin\r\n      Self.ItemIndex := 0;\r\n\r\n      if (Abs(FVirtualPos) > FIndex * FLineHeight) then\r\n      begin\r\n        FVirtualPos := -(FIndex * FLineHeight);\r\n      end;\r\n    end;\r\n  end;\r\n\r\n  if Key = VK_DOWN then\r\n  begin\r\n    if (FStrings.Count > 0) and (FIndex < FStrings.Count - 1) then\r\n    begin\r\n      Self.ItemIndex := FIndex + 1;\r\n\r\n      if ((FIndex + 1) * FLineHeight) > (dLines * FLineHeight - FVirtualPos)\r\n      then\r\n      begin\r\n        FVirtualPos := -(((FIndex + 1) * FLineHeight) - (dLines * FLineHeight));\r\n      end;\r\n    end;\r\n  end;\r\n\r\n  \/\/ Page_Down pressed\r\n  if Key = VK_NEXT then\r\n  begin\r\n    if (FStrings.Count > 0) and (FIndex < FStrings.Count - 1) then\r\n    begin\r\n      Self.ItemIndex := FIndex + dLines;\r\n\r\n      if ((FIndex + 1) * FLineHeight) > (dLines * FLineHeight - FVirtualPos)\r\n      then\r\n      begin\r\n        FVirtualPos := -(((FIndex + 1) * FLineHeight) - (dLines * FLineHeight));\r\n      end;\r\n    end;\r\n  end;\r\n\r\n  if Key = VK_END then\r\n  begin\r\n    if (FStrings.Count > 0) and (FIndex < FStrings.Count - 1) then\r\n    begin\r\n      Self.ItemIndex := FStrings.Count - 1;\r\n\r\n      if ((FIndex + 1) * FLineHeight) > (dLines * FLineHeight - FVirtualPos)\r\n      then\r\n      begin\r\n        FVirtualPos := -(((FIndex + 1) * FLineHeight) - (dLines * FLineHeight));\r\n      end;\r\n    end;\r\n  end;\r\n\r\n  inherited KeyDown(Key, Shift);\r\nend;\r\n\r\nprocedure TCustomAListBox.MouseDown(Button: TMouseButton; Shift: TShiftState;\r\n  X, Y: Integer);\r\nvar\r\n  L, T, H, W: Integer;\r\n  upBtL, upBtT, upBtH, upBtW: Integer;\r\n  dnBtL, dnBtT, dnBtH, dnBtW: Integer;\r\n  srBtL, srBtT, srBtH, srBtW: Integer;\r\n  dLines, VPos: Integer;\r\nbegin\r\n  \/\/ check if user clicked on client list area\r\n  L := Self.ClientLeft + FMargin + FBorder.Size;\r\n  T := Self.ClientTop + FMargin + FBorder.Size;\r\n  W := Self.ClientLeft + FMargin + FBorder.Size + GetVirtualWidth;\r\n  H := Self.ClientTop + Self.Height - FMargin - FBorder.Size;\r\n\r\n  if PtInRect(Rect(L, T, W, H), Point(X, Y)) then\r\n  begin\r\n    VPos := (Y - T) - FVirtualPos;\r\n    Self.ItemIndex := VPos div FLineHeight;\r\n  end;\r\n\r\n  \/\/ Check if user clicked on scroll area\r\n  L := Self.ClientLeft + FMargin + FBorder.Size + GetVirtualWidth;\r\n  \/\/ W := Self.ClientLeft + Self.Width - FMargin - FBorder.Size;\r\n\r\n  \/\/ Test UpButton\r\n  upBtL := L;\r\n  upBtT := T;\r\n  upBtW := L + FUpButton.Width;\r\n  upBtH := T + FUpButton.Height;\r\n\r\n  if PtInRect(Rect(upBtL, upBtT, upBtW, upBtH), Point(X, Y)) then\r\n  begin\r\n    FUpButton.ControlState := FUpButton.ControlState + [csClicked];\r\n  end;\r\n\r\n  \/\/ Test Down Button\r\n  dnBtL := L;\r\n  dnBtT := H - FDownButton.Height;\r\n  dnBtW := L + FDownButton.Width;\r\n  dnBtH := H;\r\n\r\n  if PtInRect(Rect(dnBtL, dnBtT, dnBtW, dnBtH), Point(X, Y)) then\r\n  begin\r\n    FDownButton.ControlState := FDownButton.ControlState + [csClicked];\r\n  end;\r\n\r\n  \/\/ Test Scroll Button\r\n  dLines := (H - T) div FLineHeight;\r\n\r\n  T := T + FUpButton.Height;\r\n  H := H - FDownButton.Height;\r\n\r\n  srBtL := L;\r\n  srBtT := T + Round(Abs(FVirtualPos) \/\r\n    (GetVirtualHeight - (FLineHeight * dLines)) *\r\n    (H - T - FScrollButton.Height));\r\n  srBtW := L + FScrollButton.Width;\r\n  srBtH := srBtT + FScrollButton.Height;\r\n\r\n  if PtInRect(Rect(srBtL, srBtT, srBtW, srBtH), Point(X, Y)) then\r\n  begin\r\n    FScrollButton.ControlState := FScrollButton.ControlState + [csClicked];\r\n  end;\r\n\r\n  inherited MouseDown(Button, Shift, X, Y);\r\nend;\r\n\r\nprocedure TCustomAListBox.MouseLeave;\r\nbegin\r\n  FUpButton.ControlState := FUpButton.ControlState - [csMouseHover];\r\n  FDownButton.ControlState := FDownButton.ControlState - [csMouseHover];\r\n  FScrollButton.ControlState := FScrollButton.ControlState - [csMouseHover];\r\n\r\n  inherited MouseLeave;\r\nend;\r\n\r\nprocedure TCustomAListBox.MouseMove(Shift: TShiftState; X, Y: Integer);\r\nvar\r\n  L, T, H: Integer;\r\n  upBtL, upBtT, upBtH, upBtW: Integer;\r\n  dnBtL, dnBtT, dnBtH, dnBtW: Integer;\r\n  srBtL, srBtT, srBtH, srBtW: Integer;\r\n  dLines, VPos: Integer;\r\nbegin\r\n  L := Self.ClientLeft + FMargin + FBorder.Size + GetVirtualWidth;\r\n  T := Self.ClientTop + FMargin + FBorder.Size;\r\n  \/\/ W := Self.ClientLeft + Self.Width - FMargin - FBorder.Size;\r\n  H := Self.ClientTop + Self.Height - FMargin - FBorder.Size;\r\n\r\n  \/\/ Test UpButton\r\n  upBtL := L;\r\n  upBtT := T;\r\n  upBtW := L + FUpButton.Width;\r\n  upBtH := T + FUpButton.Height;\r\n\r\n  if PtInRect(Rect(upBtL, upBtT, upBtW, upBtH), Point(X, Y)) then\r\n  begin\r\n    FUpButton.ControlState := FUpButton.ControlState + [csMouseHover];\r\n  end\r\n  else\r\n    FUpButton.ControlState := FUpButton.ControlState - [csMouseHover];\r\n\r\n  \/\/ Test Down Button\r\n  dnBtL := L;\r\n  dnBtT := H - FDownButton.Height;\r\n  dnBtW := L + FDownButton.Width;\r\n  dnBtH := H;\r\n\r\n  if PtInRect(Rect(dnBtL, dnBtT, dnBtW, dnBtH), Point(X, Y)) then\r\n  begin\r\n    FDownButton.ControlState := FDownButton.ControlState + [csMouseHover];\r\n  end\r\n  else\r\n    FDownButton.ControlState := FDownButton.ControlState - [csMouseHover];\r\n\r\n  \/\/ Test Scroll Button\r\n  dLines := (H - T) div FLineHeight;\r\n\r\n  T := T + FUpButton.Height;\r\n  H := H - FDownButton.Height;\r\n\r\n  if csClicked in FScrollButton.ControlState then\r\n  begin\r\n    if GetVirtualHeight - (FLineHeight * dLines) > 0 then\r\n    begin\r\n      VPos := Round((Y - (T + FScrollButton.Height div 2)) \/\r\n        (H - T - FScrollButton.Height) *\r\n        (GetVirtualHeight - (FLineHeight * dLines)));\r\n\r\n      FVirtualPos := -VPos;\r\n\r\n      if FVirtualPos > 0 then\r\n        FVirtualPos := 0;\r\n\r\n      if (GetVirtualHeight - (FLineHeight * dLines)) < Abs(FVirtualPos) then\r\n        FVirtualPos := -(GetVirtualHeight - (FLineHeight * dLines));\r\n    end;\r\n  end;\r\n\r\n  srBtL := L;\r\n  srBtT := T + Round(Abs(FVirtualPos) \/\r\n    (GetVirtualHeight - (FLineHeight * dLines)) *\r\n    (H - T - FScrollButton.Height));\r\n  srBtW := L + FScrollButton.Width;\r\n  srBtH := srBtT + FScrollButton.Height;\r\n\r\n  if PtInRect(Rect(srBtL, srBtT, srBtW, srBtH), Point(X, Y)) then\r\n  begin\r\n    FScrollButton.ControlState := FScrollButton.ControlState + [csMouseHover];\r\n  end\r\n  else\r\n    FScrollButton.ControlState := FScrollButton.ControlState - [csMouseHover];\r\n\r\n  inherited MouseMove(Shift, X, Y);\r\nend;\r\n\r\nprocedure TCustomAListBox.MouseUp(Button: TMouseButton; Shift: TShiftState;\r\n  X, Y: Integer);\r\nvar\r\n  H: Integer;\r\n  dLines: Integer;\r\nbegin\r\n  H := Self.Height - FMargin * 2 - FBorder.Size * 2;\r\n  dLines := H div FLineHeight;\r\n\r\n  \/\/ Button Up released\r\n  if csClicked in FUpButton.ControlState then\r\n  begin\r\n    if (FVirtualPos < 0) then\r\n    begin\r\n      FVirtualPos := FVirtualPos + FLineHeight;\r\n\r\n      if FVirtualPos > 0 then\r\n        FVirtualPos := 0;\r\n    end;\r\n\r\n    FUpButton.ControlState := FUpButton.ControlState - [csClicked];\r\n  end;\r\n\r\n  \/\/ Button Down Released\r\n  if csClicked in FDownButton.ControlState then\r\n  begin\r\n    if (GetVirtualHeight - (FLineHeight * dLines) + FVirtualPos > 0) then\r\n    begin\r\n      FVirtualPos := FVirtualPos - FLineHeight;\r\n\r\n      if (GetVirtualHeight - (FLineHeight * dLines)) < Abs(FVirtualPos) then\r\n        FVirtualPos := -(GetVirtualHeight - (FLineHeight * dLines));\r\n    end;\r\n\r\n    FDownButton.ControlState := FDownButton.ControlState - [csClicked];\r\n  end;\r\n\r\n  \/\/ Scroll Button released always\r\n  FScrollButton.ControlState := FScrollButton.ControlState - [csClicked];\r\n\r\n  inherited MouseUp(Button, Shift, X, Y);\r\nend;\r\n\r\nfunction TCustomAListBox.MouseWheelDown(Shift: TShiftState;\r\n  MousePos: TPoint): Boolean;\r\nvar\r\n  H: Integer;\r\nbegin\r\n  H := Self.Height - FMargin * 2 - FBorder.Size * 2;\r\n\r\n  if (FVirtualPos + GetVirtualHeight >= H) then\r\n  begin\r\n    FVirtualPos := FVirtualPos - FLineHeight;\r\n  end;\r\n\r\n  Result := True;\r\nend;\r\n\r\nfunction TCustomAListBox.MouseWheelUp(Shift: TShiftState;\r\n  MousePos: TPoint): Boolean;\r\nbegin\r\n  if (FVirtualPos < 0) then\r\n  begin\r\n    FVirtualPos := FVirtualPos + FLineHeight;\r\n\r\n    if FVirtualPos > 0 then\r\n      FVirtualPos := 0;\r\n  end;\r\n\r\n  Result := True;\r\nend;\r\n\r\nprocedure TCustomAListBox.Paint;\r\nvar\r\n  I, X, Y: Integer;\r\n  ARect: TRect;\r\n  AImage: TAsphyreImage;\r\n  AFont: TAsphyreFont;\r\n  bTop, bBottom: TConstraintSize;\r\n  L, T, H, W: Integer;\r\nbegin\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  \/\/ Get size Canvas\r\n  ARect := ControlManager.Canvas.ClipRect;\r\n\r\n  \/\/ Draw Background\r\n  if not FTransparent then\r\n  begin\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  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 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($30000000), beNormal);\r\n  end;\r\n\r\n  PaintScrollBar;\r\n\r\n  \/\/ Set Rect Canvas\r\n  L := X + FBorder.Size + FMargin;\r\n  T := Y + FBorder.Size + FMargin;\r\n  W := L + GetVirtualWidth;\r\n  H := T + Self.Height - FBorder.Size * 2 - FMargin * 2;\r\n\r\n  ControlManager.Canvas.ClipRect := ShortRect(Rect(L, T, W, H), ARect);\r\n\r\n  \/\/ test\r\n  \/\/ ControlManager.Canvas.FillRect(Rect(L, T,W, H), $FFFFFFFF, beNormal);\r\n\r\n  if GetVirtualHeight <= (Self.Height - (FBorder.Size * 2) - (FMargin * 2)) then\r\n    FVirtualPos := 0;\r\n\r\n  T := T + FVirtualPos;\r\n\r\n  \/\/ Draw Text\r\n  \/\/ Draw DisplayText\r\n  AFont := ControlManager.Fonts.Font[FFont.Name];\r\n  if (AFont <> nil) and (FStrings.Count > 0) then\r\n  begin\r\n    for I := 0 to FStrings.Count - 1 do\r\n    begin\r\n      \/\/ Draw selected rect\r\n      if I = FIndex then\r\n      begin\r\n        ControlManager.Canvas.FillRect(Rect(L, T + (LineHeight * I), W,\r\n          T + (LineHeight * (I + 1))), cColor4(FFont.SelectionColor), beNormal);\r\n        AFont.TextOut(Point2(L, T + (LineHeight * I)), FStrings.Items[I],\r\n          cColor2($B0FFFFFF), 1.0);\r\n      end\r\n      else\r\n      begin\r\n        AFont.TextOut(Point2(L, T + (LineHeight * I)), FStrings.Items[I],\r\n          cColor2(FFont.Color), 1.0);\r\n      end;\r\n    end;\r\n  end;\r\n\r\n  \/\/ Set Rect Canvas\r\n  ControlManager.Canvas.ClipRect := ARect;\r\nend;\r\n\r\nprocedure TCustomAListBox.PaintScrollBar;\r\nvar\r\n  X, Y: Integer;\r\n  AImage: TAsphyreImage;\r\n  bTop, bBottom: TConstraintSize;\r\n  L, T, H, W: Integer;\r\n\r\n  upBtColor: TFillColor;\r\n  upBtImage: TImage;\r\n  upBtBorderColor: TAColor;\r\n  upBtL, upBtT, upBtH, upBtW: Integer;\r\n\r\n  dnBtColor: TFillColor;\r\n  dnBtImage: TImage;\r\n  dnBtBorderColor: TAColor;\r\n  dnBtL, dnBtT, dnBtH, dnBtW: Integer;\r\n\r\n  srBtColor: TFillColor;\r\n  srBtImage: TImage;\r\n  srBtBorderColor: TAColor;\r\n  srBtL, srBtT, srBtH, srBtW: Integer;\r\n\r\n  dLines: Integer;\r\nbegin\r\n  \/\/ Set initial values\r\n  X := ClientLeft;\r\n  Y := ClientTop;\r\n\r\n  L := X + FMargin + FBorder.Size + GetVirtualWidth;\r\n  T := Y + FMargin + FBorder.Size;\r\n  W := X + Width - FMargin - FBorder.Size;\r\n  H := Y + Height - FMargin - FBorder.Size;\r\n\r\n  \/\/ Draw background shadow\r\n  AImage := ControlManager.Images.Image[FImage.Image];\r\n  if AImage = nil then\r\n  begin\r\n    ControlManager.Canvas.FillRect(Rect(L, T, W, H), cColor4($20000000),\r\n      beNormal);\r\n  end;\r\n\r\n  \/\/ Draw UpButton\r\n  if csClicked in FUpButton.ControlState then\r\n  begin\r\n    upBtColor := FUpButton.ColorPressed;\r\n    upBtImage := FUpButton.ImagePressed;\r\n    upBtBorderColor := FUpButton.Border.ColorPressed;\r\n  end\r\n  else if csMouseHover in FUpButton.ControlState then\r\n  begin\r\n    upBtColor := FUpButton.ColorHover;\r\n    upBtImage := FUpButton.ImageHover;\r\n    upBtBorderColor := FUpButton.Border.ColorHover;\r\n  end\r\n  else\r\n  begin\r\n    upBtColor := FUpButton.Color;\r\n    upBtImage := FUpButton.Image;\r\n    upBtBorderColor := FUpButton.Border.Color;\r\n  end;\r\n\r\n  upBtL := L;\r\n  upBtT := T;\r\n  upBtW := L + FUpButton.Width;\r\n  upBtH := T + FUpButton.Height;\r\n\r\n  AImage := ControlManager.Images.Image[upBtImage.Image];\r\n  if AImage <> nil then\r\n  begin\r\n    ControlManager.Canvas.UseImagePx(AImage, pRect4(upBtImage.Rect));\r\n    ControlManager.Canvas.TexMap(pRect4(Rect(upBtL, upBtT, upBtW, upBtH)),\r\n      cAlpha4(upBtColor), beNormal);\r\n  end\r\n  else\r\n  begin\r\n    ControlManager.Canvas.FillRect(Rect(upBtL, upBtT, upBtW, upBtH),\r\n      cColor4(upBtColor), beNormal);\r\n\r\n    ControlManager.Canvas.FillTri(Point2(upBtL + (FUpButton.Width \/ 2),\r\n      upBtT + (FUpButton.Border.Size + (FUpButton.Height \/ 8)) - 1),\r\n      Point2(upBtL + (FUpButton.Border.Size + (FUpButton.Width \/ 8)),\r\n      upBtH - (FUpButton.Border.Size + (FUpButton.Height \/ 8)) - 1),\r\n      Point2(upBtW - (FUpButton.Border.Size + (FUpButton.Width \/ 8)),\r\n      upBtH - (FUpButton.Border.Size + (FUpButton.Height \/ 8)) - 1), $20000000,\r\n      $20000000, $20000000, beNormal);\r\n  end;\r\n\r\n  \/\/ Draw UpButton Border\r\n  if FUpButton.Border.Size > 0 then\r\n  begin\r\n    bTop := 0;\r\n    bBottom := 0;\r\n\r\n    if eTop in FUpButton.Border.Edges then\r\n    begin\r\n      ControlManager.Canvas.FillRect(Rect(upBtL, upBtT, upBtW,\r\n        upBtT + FUpButton.Border.Size), upBtBorderColor, beNormal);\r\n      bTop := FUpButton.Border.Size;\r\n    end;\r\n\r\n    if eBottom in FUpButton.Border.Edges then\r\n    begin\r\n      ControlManager.Canvas.FillRect(Rect(upBtL, upBtH - FUpButton.Border.Size,\r\n        upBtW, upBtH), upBtBorderColor, beNormal);\r\n      bBottom := FUpButton.Border.Size;\r\n    end;\r\n\r\n    if eLeft in FUpButton.Border.Edges then\r\n      ControlManager.Canvas.FillRect(Rect(upBtL, upBtT + bTop,\r\n        upBtL + FUpButton.Border.Size, upBtH - bBottom), upBtBorderColor,\r\n        beNormal);\r\n\r\n    if eRight in FUpButton.Border.Edges then\r\n      ControlManager.Canvas.FillRect(Rect(upBtW - FUpButton.Border.Size,\r\n        upBtT + bTop, upBtW, upBtH - bBottom), upBtBorderColor, beNormal);\r\n  end;\r\n\r\n  \/\/ Draw DownButton\r\n  if csClicked in FDownButton.ControlState then\r\n  begin\r\n    dnBtColor := FDownButton.ColorPressed;\r\n    dnBtImage := FDownButton.ImagePressed;\r\n    dnBtBorderColor := FDownButton.Border.ColorPressed;\r\n  end\r\n  else if csMouseHover in FDownButton.ControlState then\r\n  begin\r\n    dnBtColor := FDownButton.ColorHover;\r\n    dnBtImage := FDownButton.ImageHover;\r\n    dnBtBorderColor := FDownButton.Border.ColorHover;\r\n  end\r\n  else\r\n  begin\r\n    dnBtColor := FDownButton.Color;\r\n    dnBtImage := FDownButton.Image;\r\n    dnBtBorderColor := FDownButton.Border.Color;\r\n  end;\r\n\r\n  dnBtL := L;\r\n  dnBtT := H - FDownButton.Height;\r\n  dnBtW := L + FDownButton.Width;\r\n  dnBtH := H;\r\n\r\n  AImage := ControlManager.Images.Image[dnBtImage.Image];\r\n  if AImage <> nil then\r\n  begin\r\n    ControlManager.Canvas.UseImagePx(AImage, pRect4(dnBtImage.Rect));\r\n    ControlManager.Canvas.TexMap(pRect4(Rect(dnBtL, dnBtT, dnBtW, dnBtH)),\r\n      cAlpha4(dnBtColor), beNormal);\r\n  end\r\n  else\r\n  begin\r\n    ControlManager.Canvas.FillRect(Rect(dnBtL, dnBtT, dnBtW, dnBtH),\r\n      cColor4(dnBtColor), beNormal);\r\n    ControlManager.Canvas.FillTri\r\n      (Point2(dnBtL + (FDownButton.Border.Size + (FDownButton.Width \/ 8)),\r\n      dnBtT + (FDownButton.Border.Size + (FDownButton.Height \/ 8)) + 1),\r\n      Point2(dnBtW - (FDownButton.Border.Size + (FDownButton.Width \/ 8)),\r\n      dnBtT + (FDownButton.Border.Size + (FDownButton.Height \/ 8)) + 1),\r\n      Point2(dnBtL + (FDownButton.Width \/ 2),\r\n      dnBtH - (FDownButton.Border.Size + (FDownButton.Height \/ 8)) + 1),\r\n      $20000000, $20000000, $20000000, beNormal);\r\n  end;\r\n\r\n  \/\/ Draw DownButton Border\r\n  if FDownButton.Border.Size > 0 then\r\n  begin\r\n    bTop := 0;\r\n    bBottom := 0;\r\n\r\n    if eTop in FDownButton.Border.Edges then\r\n    begin\r\n      ControlManager.Canvas.FillRect(Rect(dnBtL, dnBtT, dnBtW,\r\n        dnBtT + FDownButton.Border.Size), dnBtBorderColor, beNormal);\r\n      bTop := FDownButton.Border.Size;\r\n    end;\r\n\r\n    if eBottom in FDownButton.Border.Edges then\r\n    begin\r\n      ControlManager.Canvas.FillRect\r\n        (Rect(dnBtL, dnBtH - FDownButton.Border.Size, dnBtW, dnBtH),\r\n        dnBtBorderColor, beNormal);\r\n      bBottom := FDownButton.Border.Size;\r\n    end;\r\n\r\n    if eLeft in FDownButton.Border.Edges then\r\n      ControlManager.Canvas.FillRect(Rect(dnBtL, dnBtT + bTop,\r\n        dnBtL + FDownButton.Border.Size, dnBtH - bBottom), dnBtBorderColor,\r\n        beNormal);\r\n\r\n    if eRight in FDownButton.Border.Edges then\r\n      ControlManager.Canvas.FillRect(Rect(dnBtW - FDownButton.Border.Size,\r\n        dnBtT + bTop, dnBtW, dnBtH - bBottom), dnBtBorderColor, beNormal);\r\n  end;\r\n\r\n  \/\/ Draw ScrollButton\r\n  if csClicked in FScrollButton.ControlState then\r\n  begin\r\n    srBtColor := FScrollButton.ColorPressed;\r\n    srBtImage := FScrollButton.ImagePressed;\r\n    srBtBorderColor := FScrollButton.Border.ColorPressed;\r\n  end\r\n  else if csMouseHover in FScrollButton.ControlState then\r\n  begin\r\n    srBtColor := FScrollButton.ColorHover;\r\n    srBtImage := FScrollButton.ImageHover;\r\n    srBtBorderColor := FScrollButton.Border.ColorHover;\r\n  end\r\n  else\r\n  begin\r\n    srBtColor := FScrollButton.Color;\r\n    srBtImage := FScrollButton.Image;\r\n    srBtBorderColor := FScrollButton.Border.Color;\r\n  end;\r\n\r\n  dLines := (H - T) div FLineHeight;\r\n\r\n  T := T + FUpButton.Height;\r\n  H := H - FDownButton.Height;\r\n\r\n  srBtL := L;\r\n  srBtT := T + Round(Abs(FVirtualPos) \/\r\n    (GetVirtualHeight - (FLineHeight * dLines)) *\r\n    (H - T - FScrollButton.Height));\r\n  srBtW := L + FScrollButton.Width;\r\n  srBtH := srBtT + FScrollButton.Height;\r\n\r\n  AImage := ControlManager.Images.Image[srBtImage.Image];\r\n  if AImage <> nil then\r\n  begin\r\n    ControlManager.Canvas.UseImagePx(AImage, pRect4(srBtImage.Rect));\r\n    ControlManager.Canvas.TexMap(pRect4(Rect(srBtL, srBtT, srBtW, srBtH)),\r\n      cAlpha4(srBtColor), beNormal);\r\n  end\r\n  else\r\n  begin\r\n    ControlManager.Canvas.FillRect(Rect(srBtL, srBtT, srBtW, srBtH),\r\n      cColor4(srBtColor), beNormal);\r\n  end;\r\n\r\n  \/\/ Draw ScrollButton Border\r\n  if FScrollButton.Border.Size > 0 then\r\n  begin\r\n    bTop := 0;\r\n    bBottom := 0;\r\n\r\n    if eTop in FScrollButton.Border.Edges then\r\n    begin\r\n      ControlManager.Canvas.FillRect(Rect(srBtL, srBtT, srBtW,\r\n        srBtT + FScrollButton.Border.Size), srBtBorderColor, beNormal);\r\n      bTop := FScrollButton.Border.Size;\r\n    end;\r\n\r\n    if eBottom in FScrollButton.Border.Edges then\r\n    begin\r\n      ControlManager.Canvas.FillRect\r\n        (Rect(srBtL, srBtH - FScrollButton.Border.Size, srBtW, srBtH),\r\n        srBtBorderColor, beNormal);\r\n      bBottom := FScrollButton.Border.Size;\r\n    end;\r\n\r\n    if eLeft in FScrollButton.Border.Edges then\r\n      ControlManager.Canvas.FillRect(Rect(srBtL, srBtT + bTop,\r\n        srBtL + FScrollButton.Border.Size, srBtH - bBottom), srBtBorderColor,\r\n        beNormal);\r\n\r\n    if eRight in FScrollButton.Border.Edges then\r\n      ControlManager.Canvas.FillRect(Rect(srBtW - FScrollButton.Border.Size,\r\n        srBtT + bTop, srBtW, srBtH - bBottom), srBtBorderColor, beNormal);\r\n  end;\r\n\r\nend;\r\n\r\nprocedure TCustomAListBox.SetAntialiased(Value: Boolean);\r\nbegin\r\n  FAntialiased := Value;\r\nend;\r\n\r\nprocedure TCustomAListBox.SetBorder(Value: TBorder);\r\nbegin\r\n  if Value <> nil then\r\n    FBorder.Assign(Value);\r\nend;\r\n\r\nprocedure TCustomAListBox.SetColor(Value: TFillColor);\r\nbegin\r\n  if Value <> nil then\r\n    FColor.Assign(Value);\r\nend;\r\n\r\nprocedure TCustomAListBox.SetDownButton(Value: TBtBox);\r\nbegin\r\n  if Value <> nil then\r\n    FDownButton.Assign(Value);\r\nend;\r\n\r\nprocedure TCustomAListBox.SetFocusRect(Value: TFocusRect);\r\nbegin\r\n  FFocusRect := Value;\r\nend;\r\n\r\nprocedure TCustomAListBox.SetFont(Value: TEditFont);\r\nbegin\r\n  if Value <> nil then\r\n    FFont.Assign(Value);\r\nend;\r\n\r\nprocedure TCustomAListBox.SetHeight(Value: Integer);\r\nvar\r\n  MinH: Integer;\r\nbegin\r\n  MinH := FUpButton.Height + FDownButton.Height + FScrollButton.Height + FMargin\r\n    * 2 + FBorder.Size * 2;\r\n\r\n  if (Value < MinH) then\r\n    Value := MinH;\r\n\r\n  inherited SetHeight(Value);\r\nend;\r\n\r\nprocedure TCustomAListBox.SetImage(Value: TImage);\r\nbegin\r\n  if Value <> nil then\r\n    FImage.Assign(Value);\r\nend;\r\n\r\nprocedure TCustomAListBox.SetIndex(Value: Integer);\r\nbegin\r\n  FIndex := Value;\r\n\r\n  if FIndex >= FStrings.Count then\r\n    FIndex := FStrings.Count - 1;\r\nend;\r\n\r\nprocedure TCustomAListBox.SetLineHeight(Value: Integer);\r\nbegin\r\n  FLineHeight := Value;\r\n\r\n  if FLineHeight < 0 then\r\n    FLineHeight := 1;\r\nend;\r\n\r\nprocedure TCustomAListBox.SetMargin(Value: Word);\r\nbegin\r\n  FMargin := Value;\r\n\r\n  SetHeight(Self.Height);\r\n  SetWidth(Self.Width);\r\nend;\r\n\r\nprocedure TCustomAListBox.SetScrollButton(Value: TBtBox);\r\nbegin\r\n  if Value <> nil then\r\n    FScrollButton.Assign(Value);\r\nend;\r\n\r\nprocedure TCustomAListBox.SetStrings(Value: TAStringList);\r\nbegin\r\n  if Value <> nil then\r\n    FStrings.Assign(Value);\r\nend;\r\n\r\nprocedure TCustomAListBox.SetTransparent(Value: Boolean);\r\nbegin\r\n  FTransparent := Value;\r\nend;\r\n\r\nprocedure TCustomAListBox.SetUpButton(Value: TBtBox);\r\nbegin\r\n  if Value <> nil then\r\n    FUpButton.Assign(Value);\r\nend;\r\n\r\nprocedure TCustomAListBox.SetWidth(Value: Integer);\r\nvar\r\n  MinW: Integer;\r\nbegin\r\n  MinW := (FBorder.Size * 2) + (FMargin * 2) +\r\n    Max(Max(FUpButton.Width, FDownButton.Width), FScrollButton.Width);\r\n\r\n  if Value < MinW then\r\n    Value := MinW;\r\n\r\n  inherited SetWidth(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=1321\">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\/1321"}],"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=1321"}],"version-history":[{"count":2,"href":"https:\/\/tulip-ui.azurewebsites.net\/index.php?rest_route=\/wp\/v2\/pages\/1321\/revisions"}],"predecessor-version":[{"id":1761,"href":"https:\/\/tulip-ui.azurewebsites.net\/index.php?rest_route=\/wp\/v2\/pages\/1321\/revisions\/1761"}],"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=1321"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}