mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-08 15:32:40 +02:00
840 lines
25 KiB
PHP
840 lines
25 KiB
PHP
{%MainUnit ../stdctrls.pp}
|
|
{
|
|
*****************************************************************************
|
|
This file is part of the Lazarus Component Library (LCL)
|
|
|
|
See the file COPYING.modifiedLGPL.txt, included in this distribution,
|
|
for details about the license.
|
|
*****************************************************************************
|
|
}
|
|
{ if not HandleAllocated then
|
|
FItems contains a TExtendedStringList
|
|
else
|
|
FItems contains an interface specific TStrings descendent
|
|
}
|
|
|
|
type
|
|
TCustomListBoxItemRecord = record
|
|
TheObject: TObject;
|
|
Selected: Boolean;
|
|
end;
|
|
PCustomListBoxItemRecord = ^TCustomListBoxItemRecord;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomListBox.AssignCacheToItemData
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.AssignCacheToItemData(const AIndex: Integer;
|
|
const AData: Pointer);
|
|
begin
|
|
if PCustomListBoxItemRecord(AData)^.Selected or (not MultiSelect and (FItemIndex = AIndex)) then
|
|
begin
|
|
LockSelectionChange;
|
|
SendItemSelected(AIndex, True);
|
|
UnlockSelectionChange;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomListBox.BeforeDragStart;
|
|
begin
|
|
if HandleAllocated then
|
|
TWSCustomListBoxClass(WidgetSetClass).DragStart(Self);
|
|
end;
|
|
|
|
procedure TCustomListBox.BeginAutoDrag;
|
|
begin
|
|
BeginDrag(False);
|
|
end;
|
|
|
|
function TCustomListBox.CalculateStandardItemHeight: Integer;
|
|
var
|
|
B: TBitmap;
|
|
begin
|
|
// Paul: This will happen only once if Style = lbStandard then CheckListBox is
|
|
// OwnerDrawFixed in real (under windows). Handle is not allocated and we
|
|
// can not use Canvas since it will cause recursion but we need correct font height
|
|
B := TBitmap.Create;
|
|
try
|
|
B.Canvas.Font := Font;
|
|
Result := B.Canvas.TextHeight('Fj');
|
|
finally
|
|
B.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomListBox.CreateParams(var Params: TCreateParams);
|
|
const
|
|
MultiSelectStyle: array[Boolean] of DWord = (LBS_MULTIPLESEL, LBS_EXTENDEDSEL);
|
|
begin
|
|
inherited CreateParams(Params);
|
|
if Sorted then
|
|
Params.Style := Params.Style or LBS_SORT;
|
|
if MultiSelect then
|
|
Params.Style := Params.Style or MultiSelectStyle[ExtendedSelect];
|
|
if Columns > 1 then
|
|
Params.Style := Params.Style or LBS_MULTICOLUMN;
|
|
|
|
case Style of
|
|
lbOwnerDrawFixed: Params.Style := Params.Style or LBS_OWNERDRAWFIXED;
|
|
lbOwnerDrawVariable: Params.Style := Params.Style or LBS_OWNERDRAWVARIABLE;
|
|
end;
|
|
Params.Style := Params.Style or
|
|
(WS_HSCROLL or WS_VSCROLL or LBS_NOINTEGRALHEIGHT or LBS_HASSTRINGS or LBS_NOTIFY);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomListBox.AssignItemDataToCache
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.AssignItemDataToCache(const AIndex: Integer;
|
|
const AData: Pointer);
|
|
begin
|
|
PCustomListBoxItemRecord(AData)^.Selected := Selected[AIndex];
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomListBox.InitializeWnd
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.InitializeWnd;
|
|
var
|
|
NewStrings: TStrings;
|
|
OldItems: TExtendedStringList;
|
|
i: integer;
|
|
begin
|
|
LockSelectionChange;
|
|
inherited InitializeWnd;
|
|
// fetch the interface item list
|
|
NewStrings := TWSCustomListBoxClass(WidgetSetClass).GetStrings(Self);
|
|
// copy the items (text+objects)
|
|
OldItems := FItems as TExtendedStringList;
|
|
|
|
OldItems.Sorted := False;// make sure the items are not reordered (needed for ItemIndex and attributes)
|
|
NewStrings.Assign(FItems);
|
|
|
|
// new item list is the interface item list
|
|
FItems := NewStrings;
|
|
FCacheValid := False;
|
|
|
|
// don't reset item index without a need - on windows this may cause an undesired selection of
|
|
// item for multiselect listbox
|
|
if FItemIndex <> TWSCustomListBoxClass(WidgetSetClass).GetItemIndex(Self) then
|
|
SendItemIndex;
|
|
|
|
// copy items attributes
|
|
for i := 0 to OldItems.Count - 1 do
|
|
AssignCacheToItemData(i, OldItems.Records[i]);
|
|
// free old items
|
|
OldItems.Free;
|
|
TWSCustomListBoxClass(WidgetSetClass).SetSorted(Self, FItems, FSorted);
|
|
TWSCustomListBoxClass(WidgetSetClass).SetScrollWidth(Self, FScrollWidth);
|
|
UnlockSelectionChange;
|
|
end;
|
|
|
|
procedure TCustomListbox.DestroyWnd;
|
|
begin
|
|
inherited;
|
|
if FCanvas <> nil then
|
|
TControlCanvas(FCanvas).FreeHandle;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomListBox.FinalizeWnd
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.FinalizeWnd;
|
|
var
|
|
NewStrings: TExtendedStringList;
|
|
i: integer;
|
|
begin
|
|
LockSelectionChange;
|
|
|
|
// save ItemIndex on destroy handle
|
|
if ([csDestroying,csLoading]*ComponentState=[]) then
|
|
GetItemIndex;
|
|
// create internal item list
|
|
if Assigned(FItems) then
|
|
begin
|
|
NewStrings := TExtendedStringList.Create(GetCachedDataSize);
|
|
|
|
// copy items (text+objects) from the interface items list
|
|
NewStrings.Assign(Items);
|
|
// copy items attributes
|
|
for i:=0 to Items.Count-1 do
|
|
AssignItemDataToCache(i, NewStrings.Records[i]);
|
|
|
|
// free the interface items list
|
|
TWSCustomListBoxClass(WidgetSetClass).FreeStrings(FItems);
|
|
// new item list is the internal item list
|
|
NewStrings.Sorted:=FSorted;
|
|
FItems:= NewStrings;
|
|
FCacheValid := True;
|
|
end;
|
|
inherited FinalizeWnd;
|
|
UnlockSelectionChange;
|
|
end;
|
|
|
|
class function TCustomListBox.GetControlClassDefaultSize: TSize;
|
|
begin
|
|
Result.CX := 100;
|
|
Result.CY := 80;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomListBox.UpdateSelectionMode
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.UpdateSelectionMode;
|
|
begin
|
|
if not HandleAllocated then exit;
|
|
LockSelectionChange;
|
|
TWSCustomListBoxClass(WidgetSetClass).SetSelectionMode(Self,
|
|
ExtendedSelect, MultiSelect);
|
|
UnlockSelectionChange;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function TCustomListBox.GetTopIndex: Integer;
|
|
------------------------------------------------------------------------------}
|
|
function TCustomListBox.GetTopIndex: Integer;
|
|
begin
|
|
if HandleAllocated then
|
|
FTopIndex := TWSCustomListBoxClass(WidgetSetClass).GetTopIndex(Self);
|
|
Result := FTopIndex;
|
|
end;
|
|
|
|
procedure TCustomListBox.RaiseIndexOutOfBounds(AIndex: integer);
|
|
begin
|
|
raise Exception.CreateFmt(rsIndexOutOfBounds, [ClassName, AIndex, FItems.Count-1]);
|
|
end;
|
|
|
|
procedure TCustomListBox.SetColumns(const AValue: Integer);
|
|
begin
|
|
if (FColumns = AValue) or (AValue < 0) then
|
|
Exit;
|
|
FColumns := AValue;
|
|
if HandleAllocated then
|
|
TWSCustomListBoxClass(WidgetSetClass).SetColumnCount(Self, FColumns);
|
|
end;
|
|
|
|
procedure TCustomListBox.SetScrollWidth(const AValue: Integer);
|
|
begin
|
|
FScrollWidth := AValue;
|
|
if HandleAllocated then
|
|
TWSCustomListBoxClass(WidgetSetClass).SetScrollWidth(Self, FScrollWidth);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function TCustomListBox.GetCount: Integer;
|
|
------------------------------------------------------------------------------}
|
|
function TCustomListBox.GetCount: Integer;
|
|
begin
|
|
Result := Items.Count;
|
|
end;
|
|
|
|
function TCustomListBox.GetScrollWidth: Integer;
|
|
begin
|
|
if HandleAllocated then
|
|
Result := TWSCustomListBoxClass(WidgetSetClass).GetScrollWidth(Self)
|
|
else
|
|
Result := FScrollWidth;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomListBox.SetTopIndex(const AValue: Integer);
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.SetTopIndex(const AValue: Integer);
|
|
begin
|
|
// don't check if changed. If the item is only partly visible, the message
|
|
// will make it complete visible.
|
|
FTopIndex := AValue;
|
|
if HandleAllocated and ([csLoading,csDestroying]*ComponentState=[]) then
|
|
TWSCustomListBoxClass(WidgetSetClass).SetTopIndex(Self, AValue);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomListBox.UpdateSorted;
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.UpdateSorted;
|
|
begin
|
|
if HandleAllocated then
|
|
begin
|
|
LockSelectionChange;
|
|
TWSCustomListBoxClass(WidgetSetClass).SetSorted(Self, FItems, FSorted);
|
|
UnlockSelectionChange;
|
|
end
|
|
else
|
|
TExtendedStringList(FItems).Sorted := FSorted;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomListBox.LMDrawListItem(var TheMessage: TLMDrawListItem);
|
|
|
|
Handler for custom drawing items.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.LMDrawListItem(var TheMessage: TLMDrawListItem);
|
|
begin
|
|
with TheMessage.DrawListItemStruct^ do
|
|
begin
|
|
FCanvas.Handle := DC;
|
|
if Assigned(Font) then
|
|
begin
|
|
FCanvas.Font := Font;
|
|
FCanvas.Font.PixelsPerInch := Font.PixelsPerInch;
|
|
end;
|
|
if Assigned(Brush) then
|
|
FCanvas.Brush := Brush;
|
|
if (ItemID <> UINT(-1)) and (odSelected in ItemState) then
|
|
begin
|
|
FCanvas.Brush.Color := clHighlight;
|
|
FCanvas.Font.Color := clHighlightText
|
|
end else
|
|
begin
|
|
FCanvas.Brush.Color := GetColorResolvingParent;
|
|
FCanvas.Font.Color := clWindowText;
|
|
end;
|
|
DrawItem(ItemID, Area, ItemState);
|
|
if (odFocused in ItemState) and (lboDrawFocusRect in FOptions) then
|
|
DrawFocusRect(DC, Area);
|
|
FCanvas.Handle := 0;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomListBox.LMMeasureItem(var TheMessage: TLMMeasureItem);
|
|
var
|
|
AHeight: Integer;
|
|
begin
|
|
with TheMessage.MeasureItemStruct^ do
|
|
begin
|
|
if Self.ItemHeight <> 0 then
|
|
AHeight := Self.ItemHeight
|
|
else begin
|
|
Canvas.Font := Font;
|
|
AHeight := Canvas.TextHeight('Hg');
|
|
end;
|
|
MeasureItem(Integer(ItemId), AHeight);
|
|
if AHeight > 0 then
|
|
ItemHeight := AHeight;
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomListBox.LMSelChange(var TheMessage);
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.LMSelChange(var TheMessage);
|
|
begin
|
|
if [csLoading,csDestroying,csDesigning]*ComponentState<>[] then exit;
|
|
DoSelectionChange(FLockSelectionChange = 0);
|
|
end;
|
|
|
|
procedure TCustomListBox.WMLButtonUp(var Message: TLMLButtonUp);
|
|
begin
|
|
// prevent Click to be called twice when using selchange as click
|
|
if ClickOnSelChange and FClickTriggeredBySelectionChange then
|
|
Exclude(FControlState, csClicked);
|
|
inherited WMLButtonUp(Message);
|
|
// reset flag
|
|
FClickTriggeredBySelectionChange := False;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomListBox.SendItemSelected(Index: integer; IsSelected: boolean);
|
|
|
|
Tell the interface whether an item is selected.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.SendItemSelected(Index: integer; IsSelected: boolean);
|
|
begin
|
|
if HandleAllocated then
|
|
TWSCustomListBoxClass(WidgetSetClass).SelectItem(Self, Index, IsSelected);
|
|
end;
|
|
|
|
class procedure TCustomListBox.WSRegisterClass;
|
|
begin
|
|
inherited WSRegisterClass;
|
|
RegisterCustomListBox;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------}
|
|
{ procedure TCustomListBox.SetExtendedSelect }
|
|
{------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.SetExtendedSelect(Val: boolean);
|
|
begin
|
|
if Val <> FExtendedSelect then
|
|
begin
|
|
FExtendedSelect:= Val;
|
|
UpdateSelectionMode;
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------}
|
|
{ procedure TCustomListBox.SetMultiSelect }
|
|
{------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.SetMultiSelect(Val: boolean);
|
|
begin
|
|
if Val <> FMultiSelect then
|
|
begin
|
|
FMultiSelect := Val;
|
|
UpdateSelectionMode;
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------}
|
|
{ procedure TCustomListBox.SetSelected }
|
|
{------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.SetSelected(Index: integer; Val: boolean);
|
|
begin
|
|
CheckIndex(Index);
|
|
|
|
if not MultiSelect then
|
|
begin
|
|
if Val then
|
|
ItemIndex := Index
|
|
else
|
|
if Index = ItemIndex then
|
|
ItemIndex := -1;
|
|
end else
|
|
begin
|
|
if HandleAllocated then
|
|
SendItemSelected(Index, Val)
|
|
else
|
|
PCustomListBoxItemRecord(GetCachedData(Index))^.Selected := Val;
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------}
|
|
{ function TCustomListBox.GetSelected }
|
|
{------------------------------------------------------------------------------}
|
|
function TCustomListBox.GetSelected(Index: integer): boolean;
|
|
begin
|
|
CheckIndex(Index);
|
|
if HandleAllocated then
|
|
Result := TWSCustomListBoxClass(WidgetSetClass).GetSelected(Self, Index)
|
|
else
|
|
Result := PCustomListBoxItemRecord(GetCachedData(Index))^.Selected;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------}
|
|
{ function TCustomListBox.GetSelCount }
|
|
{------------------------------------------------------------------------------}
|
|
function TCustomListBox.GetSelCount: integer;
|
|
begin
|
|
if HandleAllocated then
|
|
Result := TWSCustomListBoxClass(WidgetSetClass).GetSelCount(Self)
|
|
else
|
|
Result := 0;
|
|
end;
|
|
|
|
function TCustomListBox.GetItemHeight: Integer;
|
|
begin
|
|
if HandleAllocated and (Style = lbStandard) then
|
|
begin
|
|
with ItemRect(TopIndex) do
|
|
Result := Bottom - Top;
|
|
end
|
|
else
|
|
Result := FItemHeight;
|
|
end;
|
|
|
|
procedure TCustomListBox.SetItemHeight(Value: Integer);
|
|
begin
|
|
if (FItemHeight <> Value) and (Value >= 0) then
|
|
begin
|
|
FItemHeight := Value;
|
|
if (not HandleAllocated) or (csLoading in ComponentState) then exit;
|
|
// TODO: remove RecreateWnd
|
|
RecreateWnd(Self);
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------}
|
|
{ procedure TCustomListBox.SetSorted }
|
|
{------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.SetSorted(Val: boolean);
|
|
begin
|
|
if Val <> FSorted then
|
|
begin
|
|
FSorted:= Val;
|
|
UpdateSorted;
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomListBox.SetStyle
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.SetStyle(Val: TListBoxStyle);
|
|
begin
|
|
if Val <> FStyle then
|
|
begin
|
|
FStyle:= Val;
|
|
if HandleAllocated then
|
|
TWSCustomListBoxClass(WidgetSetClass).SetStyle(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomListBox.DrawItem(Index: Integer; ARect: TRect;
|
|
State: TOwnerDrawState);
|
|
begin
|
|
if Assigned(FOnDrawItem) then
|
|
FOnDrawItem(Self, Index, ARect, State)
|
|
else
|
|
begin
|
|
if not(odBackgroundPainted in State) then
|
|
FCanvas.FillRect(ARect);
|
|
if (Index>=0) and (Index < Items.Count) then
|
|
InternalDrawItem(Self, FCanvas, ARect, Items[Index]);
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomListBox.DoAutoAdjustLayout(
|
|
const AMode: TLayoutAdjustmentPolicy; const AXProportion, AYProportion: Double
|
|
);
|
|
begin
|
|
inherited;
|
|
|
|
if AMode in [lapAutoAdjustWithoutHorizontalScrolling, lapAutoAdjustForDPI] then
|
|
begin
|
|
if FItemHeight > 0 then
|
|
ItemHeight := Round(ItemHeight * AYProportion);
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomListBox.DoSelectionChange(User: Boolean);
|
|
begin
|
|
if Assigned(OnSelectionChange) then
|
|
OnSelectionChange(Self, User);
|
|
if User and ClickOnSelChange then
|
|
begin
|
|
Click;
|
|
// set flag, that we triggered a Click, so that a possible MouseClick will
|
|
// not trigger it again
|
|
FClickTriggeredBySelectionChange := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomListBox.SendItemIndex;
|
|
begin
|
|
TWSCustomListBoxClass(WidgetSetClass).SetItemIndex(Self, FItemIndex);
|
|
end;
|
|
|
|
procedure TCustomListBox.WMGetDlgCode(var Message: TLMNoParams);
|
|
begin
|
|
inherited;
|
|
Message.Result := Message.Result or DLGC_WANTARROWS;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function TCustomListBox.GetCachedData
|
|
------------------------------------------------------------------------------}
|
|
function TCustomListBox.GetCachedData(const AIndex: Integer): Pointer;
|
|
begin
|
|
if not FCacheValid then
|
|
raise EInvalidOperation.Create('Reading form invalid cache');
|
|
Result := TExtendedStringList(FItems).Records[AIndex];
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function TCustomListBox.GetCachedDataSize
|
|
|
|
Returns the amount of data needed when the widged isn't realized in the
|
|
interface
|
|
------------------------------------------------------------------------------}
|
|
function TCustomListBox.GetCachedDataSize: Integer;
|
|
begin
|
|
Result := SizeOf(TCustomListBoxItemRecord);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function TCustomListBox.SetItems
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.SetItems(Value: TStrings);
|
|
begin
|
|
if (Value <> FItems) then
|
|
begin
|
|
LockSelectionChange;
|
|
FItems.Assign(Value);
|
|
UnlockSelectionChange;
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function TCustomListBox.Create
|
|
------------------------------------------------------------------------------}
|
|
constructor TCustomListBox.Create(TheOwner: TComponent);
|
|
begin
|
|
inherited Create(TheOwner);
|
|
fCompStyle := csListBox;
|
|
BorderStyle:= bsSingle;
|
|
FItems := TExtendedStringList.Create(GetCachedDataSize);
|
|
FCacheValid := True;
|
|
FClickOnSelChange:= True;
|
|
FItemIndex:=-1;
|
|
FExtendedSelect := true;
|
|
//FScrollWidth := 0;
|
|
FOptions := DefOptions;
|
|
FCanvas := TControlCanvas.Create;
|
|
TControlCanvas(FCanvas).Control := Self;
|
|
ParentColor := false;
|
|
TabStop := true;
|
|
with GetControlClassDefaultSize do
|
|
SetInitialBounds(0, 0, CX, CY);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function TCustomListBox.Destroy
|
|
------------------------------------------------------------------------------}
|
|
destructor TCustomListBox.Destroy;
|
|
begin
|
|
FreeAndNil(FCanvas);
|
|
FreeAndNil(FItems);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TCustomListBox.AddItem(const Item: String; AnObject: TObject);
|
|
begin
|
|
Items.AddObject(Item, AnObject);
|
|
end;
|
|
|
|
function TCustomListBox.GetItemIndex: integer;
|
|
begin
|
|
if HandleAllocated then
|
|
begin
|
|
Result := TWSCustomListBoxClass(WidgetSetClass).GetItemIndex(Self);
|
|
if (Result < 0) or (Result >= Count) then
|
|
Result := -1;
|
|
FItemIndex := Result;
|
|
end
|
|
else
|
|
Result := FItemIndex;
|
|
end;
|
|
|
|
procedure TCustomListBox.SetItemIndex(AIndex: integer);
|
|
begin
|
|
if AIndex=GetItemIndex then
|
|
exit;
|
|
if (AIndex >= FItems.Count) then
|
|
RaiseIndexOutOfBounds(AIndex);
|
|
if AIndex < 0 then AIndex := -1;
|
|
FItemIndex := AIndex;
|
|
if HandleAllocated and ([csLoading,csDestroying]*ComponentState=[]) then
|
|
SendItemIndex;
|
|
DoSelectionChange(false);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomListBox.CheckIndex
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.CheckIndex(const AIndex: Integer);
|
|
begin
|
|
if (AIndex < 0) or (AIndex >= Items.Count) then
|
|
RaiseIndexOutOfBounds(AIndex);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomListBox.Clear
|
|
|
|
Delete all items.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.Clear;
|
|
begin
|
|
FItems.Clear;
|
|
FItemIndex := -1;
|
|
end;
|
|
|
|
procedure TCustomListBox.ClearSelection;
|
|
var
|
|
i: integer;
|
|
begin
|
|
if MultiSelect then
|
|
for i := 0 to Items.Count - 1 do
|
|
Selected[i] := False
|
|
else
|
|
ItemIndex := -1; // no need to traverse all items - look at SetSelected
|
|
end;
|
|
|
|
procedure TCustomListBox.LockSelectionChange;
|
|
begin
|
|
inc(FLockSelectionChange);
|
|
end;
|
|
|
|
procedure TCustomListBox.UnlockSelectionChange;
|
|
begin
|
|
dec(FLockSelectionChange);
|
|
end;
|
|
|
|
procedure TCustomListBox.Click;
|
|
begin
|
|
inherited Click;
|
|
Changed;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
procedure TCustomListBox.MeasureItem(Index: Integer; var TheHeight: Integer);
|
|
|
|
------------------------------------------------------------------------------}
|
|
procedure TCustomListBox.MeasureItem(Index: Integer; var TheHeight: Integer);
|
|
begin
|
|
if Assigned(OnMeasureItem) then
|
|
OnMeasureItem(Self, Index, TheHeight);
|
|
end;
|
|
|
|
procedure TCustomListBox.SelectAll;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if MultiSelect then
|
|
begin
|
|
for i := 0 to Items.Count - 1 do
|
|
Selected[i] := true;
|
|
DoSelectionChange(false);
|
|
end else
|
|
begin
|
|
i := ItemIndex;
|
|
if (i>=0) and (i<Count) then
|
|
Selected[i] := true;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomListBox.DeleteSelected;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if MultiSelect then
|
|
begin
|
|
i := Items.Count;
|
|
while i > 0 do
|
|
begin
|
|
dec(i);
|
|
if Selected[i] then
|
|
FItems.Delete(i);
|
|
end;
|
|
end else
|
|
if ItemIndex>=0 then
|
|
Items.Delete(ItemIndex);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function TCustomListBox.GetIndexAtXY(X, Y: integer): integer;
|
|
|
|
Returns item index at x, y coordinate (including scrolling)
|
|
------------------------------------------------------------------------------}
|
|
function TCustomListBox.GetIndexAtXY(X, Y: integer): integer;
|
|
begin
|
|
Result := -1;
|
|
if (not HandleAllocated) then Exit;
|
|
Result := TWSCustomListBoxClass(WidgetSetClass).GetIndexAtXY(Self, X, Y);
|
|
end;
|
|
|
|
function TCustomListBox.GetIndexAtY(Y: integer): integer;
|
|
begin
|
|
Result := GetIndexAtXY(1, Y);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function TCustomListBox.GetSelectedText: string;
|
|
|
|
Returns Text of all selected items, separated by LineEnding
|
|
------------------------------------------------------------------------------}
|
|
function TCustomListBox.GetSelectedText: string;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
Result := '';
|
|
if ItemIndex < 0 then
|
|
Exit;
|
|
for i := 0 to Items.Count - 1 do
|
|
if Selected[i] then
|
|
if Result = '' then
|
|
Result := Items[i]
|
|
else
|
|
Result := Result + LineEnding + Items[i]
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function TCustomListBox.ItemAtPos(const Pos: TPoint; Existing: Boolean
|
|
): Integer;
|
|
|
|
Returns item index at y coordinate (including scrolling)
|
|
------------------------------------------------------------------------------}
|
|
function TCustomListBox.ItemAtPos(const Pos: TPoint; Existing: Boolean
|
|
): Integer;
|
|
begin
|
|
Result := GetIndexAtXY(Pos.X, Pos.Y);
|
|
if Existing then
|
|
begin
|
|
if Result >= Items.Count then
|
|
Result := -1;
|
|
end else
|
|
begin
|
|
if (Result < 0) and (Result > Items.Count) and PtInRect(ClientRect, Pos) then
|
|
Result := Items.Count;
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function TCustomListBox.ItemRect(Index: Integer): TRect;
|
|
|
|
Returns coordinates of an item (including scrolling)
|
|
Special: If Index=Count the rectangle is guessed (like VCL).
|
|
------------------------------------------------------------------------------}
|
|
function TCustomListBox.ItemRect(Index: Integer): TRect;
|
|
begin
|
|
FillChar(Result, SizeOf(Result), 0);
|
|
if not HandleAllocated then
|
|
Exit;
|
|
if (Index >= 0) and (Index < Items.Count) then
|
|
TWSCustomListBoxClass(WidgetSetClass).GetItemRect(Self, Index, Result)
|
|
else
|
|
if (Index=Items.Count) and (Index>0) then
|
|
begin
|
|
TWSCustomListBoxClass(WidgetSetClass).GetItemRect(Self, Index - 1, Result);
|
|
OffsetRect(Result, 0, Result.Bottom - Result.Top);
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function TCustomListBox.ItemVisible(Index: Integer): boolean;
|
|
|
|
Returns true if Item is partially visible.
|
|
------------------------------------------------------------------------------}
|
|
function TCustomListBox.ItemVisible(Index: Integer): boolean;
|
|
var
|
|
ARect: TRect;
|
|
begin
|
|
Result := False;
|
|
if (Index < 0) or (Index >= Items.Count) then Exit;
|
|
if not TWSCustomListBoxClass(WidgetSetClass).GetItemRect(Self, Index, ARect) then
|
|
Exit;
|
|
if (ARect.Bottom < 0) or (ARect.Top > ClientHeight) then
|
|
Exit;
|
|
Result := True;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function TCustomListBox.ItemFullyVisible(Index: Integer): boolean;
|
|
|
|
Returns true if Item is fully visible.
|
|
------------------------------------------------------------------------------}
|
|
function TCustomListBox.ItemFullyVisible(Index: Integer): boolean;
|
|
var
|
|
ARect: TRect;
|
|
begin
|
|
Result := False;
|
|
if (Index < 0) or (Index >= Items.Count) then Exit;
|
|
if not TWSCustomListBoxClass(WidgetSetClass).GetItemRect(Self, Index, ARect) then
|
|
Exit;
|
|
if (ARect.Top < 0) or (ARect.Bottom > ClientHeight) then
|
|
Exit;
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TCustomListBox.MakeCurrentVisible;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
i := ItemIndex;
|
|
|
|
if (i < 0) or (i >= Items.Count) then Exit;
|
|
// don't change top index if items is already fully visible
|
|
if ItemFullyVisible(i) then Exit;
|
|
|
|
TopIndex := ItemIndex;
|
|
end;
|
|
|
|
|
|
// back to stdctrls.pp
|