diff --git a/docs/xml/lcl/comctrls.xml b/docs/xml/lcl/comctrls.xml
index 0cb801b122..fdee571324 100644
--- a/docs/xml/lcl/comctrls.xml
+++ b/docs/xml/lcl/comctrls.xml
@@ -18600,6 +18600,10 @@ Call ParentNode.CustomSort(nil) to sort only the child nodes of a single node.
Called for owner-data mode.
Called for owner-data mode.
+ Indicator of the sorting order. Serves only the visual purpose, doesn't affect the actual sorting order
+ If AutoSort is used on TListView, this property controls, if TListView should also automatically set SortIndicator for the selected sorting columnSortIndicator</link>
+
+
diff --git a/lcl/comctrls.pp b/lcl/comctrls.pp
index ce9b4fdc19..b40d492696 100644
--- a/lcl/comctrls.pp
+++ b/lcl/comctrls.pp
@@ -1187,6 +1187,8 @@ type
TWidth = 0..MaxInt;
+ TSortIndicator = (siNone, siAscending, siDescending);
+
TListColumn = class(TCollectionItem)
private
FAlignment: TAlignment;
@@ -1198,6 +1200,7 @@ type
FWidth: TWidth;
FImageIndex: TImageIndex;
FTag: PtrInt;
+ FSortIndicator: TSortIndicator;
function GetWidth: TWidth;
procedure WSCreateColumn;
procedure WSDestroyColumn;
@@ -1211,6 +1214,7 @@ type
procedure SetCaption(const AValue: TTranslateString);
procedure SetAlignment(const AValue: TAlignment);
procedure SetImageIndex(const AValue: TImageIndex);
+ procedure SetSortIndicator(AValue: TSortIndicator);
protected
procedure SetIndex(AValue: Integer); override;
function GetDisplayName: string; override;
@@ -1230,6 +1234,7 @@ type
property Tag: PtrInt read FTag write FTag default 0;
property Visible: Boolean read FVisible write SetVisible default true;
property Width: TWidth read GetWidth write SetWidth default 50;
+ property SortIndicator: TSortIndicator read FSortIndicator write SetSortIndicator default siNone;
end;
@@ -1372,6 +1377,7 @@ type
FEditor: TCustomListViewEditor;
FAllocBy: Integer;
FAutoSort: Boolean;
+ FAutoSortIndicator: Boolean;
FAutoWidthLastColumn: Boolean;
FCanvas: TCanvas;
FDefaultItemHeight: integer;
@@ -1536,6 +1542,7 @@ type
protected
property AllocBy: Integer read FAllocBy write SetAllocBy default 0;
property AutoSort: Boolean read FAutoSort write FAutoSort default True;
+ property AutoSortIndicator: Boolean read FAutoSortIndicator write FAutoSortIndicator default False;
property AutoWidthLastColumn: Boolean read FAutoWidthLastColumn write SetAutoWidthLastColumn default False;
property ColumnClick: Boolean index Ord(lvpColumnClick) read GetProperty write SetProperty default True;
property Columns: TListColumns read FColumns write SetColumns;
@@ -1654,6 +1661,7 @@ type
property AllocBy;
property Anchors;
property AutoSort;
+ property AutoSortIndicator;
property AutoWidthLastColumn: Boolean read FAutoWidthLastColumn write SetAutoWidthLastColumn default False; // resize last column to fit width of TListView
property BorderSpacing;
property BorderStyle;
diff --git a/lcl/include/customlistview.inc b/lcl/include/customlistview.inc
index bee29bf33f..2bb3a76295 100644
--- a/lcl/include/customlistview.inc
+++ b/lcl/include/customlistview.inc
@@ -209,6 +209,10 @@ end;
{ TCustomListView ColClick }
{------------------------------------------------------------------------------}
procedure TCustomListView.ColClick(AColumn: TListColumn);
+const
+ DirToIndicator : array [TSortDirection] of TSortIndicator = (siAscending, siDescending);
+var
+ i: Integer;
begin
if IsEditing then
begin
@@ -226,8 +230,14 @@ begin
if SortType <> stNone then
begin
if AColumn.Index <> SortColumn then begin
+ if FAutoSortIndicator then
+ for i:=0 to Columns.Count-1 do
+ if (i <> AColumn.Index) and (Columns[i].SortIndicator <> siNone) then
+ Columns[i].SortIndicator := siNone;
+
SortColumn := AColumn.Index;
SortDirection := sdAscending;
+ if FAutoSortIndicator then AColumn.SortIndicator := siAscending;
end
else
begin
@@ -236,6 +246,7 @@ begin
SortDirection := sdDescending
else
SortDirection := sdAscending;
+ if FAutoSortIndicator then AColumn.SortIndicator := DirToIndicator[SortDirection];
end;
end;
end;
diff --git a/lcl/include/listcolumn.inc b/lcl/include/listcolumn.inc
index 01c914e6f0..9bad88bade 100644
--- a/lcl/include/listcolumn.inc
+++ b/lcl/include/listcolumn.inc
@@ -95,6 +95,8 @@ begin
end;
WSC.ColumnSetImage(LV, Index, Self, FImageIndex);
WSC.ColumnSetVisible(LV, Index, Self, FVisible);
+ if FSortIndicator<>siNone then
+ WSC.ColumnSetSortIndicator(LV, Index, Self, FSortIndicator);
end;
procedure TListColumn.WSDestroyColumn;
@@ -139,6 +141,19 @@ begin
Result := FWidth;
end;
+procedure TListColumn.SetSortIndicator(AValue: TSortIndicator);
+var
+ LV: TCustomListView;
+begin
+ if FSortIndicator = AValue then Exit;
+ FSortIndicator := AValue;
+ Changed(False);
+ if not WSUpdateAllowed then Exit;
+
+ LV := TListColumns(Collection).FOwner;
+ TWSCustomListViewClass(LV.WidgetSetClass).ColumnSetSortIndicator(LV, Index, Self, FSortIndicator);
+end;
+
procedure TListColumn.SetAlignment(const AValue: TAlignment);
var
LV: TCustomListView;
diff --git a/lcl/interfaces/cocoa/cocoawscomctrls.pas b/lcl/interfaces/cocoa/cocoawscomctrls.pas
index 10de8f48b2..67d94da558 100644
--- a/lcl/interfaces/cocoa/cocoawscomctrls.pas
+++ b/lcl/interfaces/cocoa/cocoawscomctrls.pas
@@ -158,6 +158,7 @@ type
class procedure ColumnSetMinWidth(const ALV: TCustomListView; const AIndex: Integer; const {%H-}AColumn: TListColumn; const AMinWidth: integer); override;
class procedure ColumnSetWidth(const ALV: TCustomListView; const AIndex: Integer; const {%H-}AColumn: TListColumn; const AWidth: Integer); override;
class procedure ColumnSetVisible(const ALV: TCustomListView; const AIndex: Integer; const {%H-}AColumn: TListColumn; const AVisible: Boolean); override;
+ class procedure ColumnSetSortIndicator(const ALV: TCustomListView; const AIndex: Integer; const AColumn: TListColumn; const ASortIndicator: TSortIndicator); override;
// Item
class procedure ItemDelete(const ALV: TCustomListView; const AIndex: Integer); override;
@@ -1232,6 +1233,29 @@ begin
{$endif}
end;
+class procedure TCocoaWSCustomListView.ColumnSetSortIndicator(
+ const ALV: TCustomListView; const AIndex: Integer;
+ const AColumn: TListColumn; const ASortIndicator: TSortIndicator);
+var
+ lTableLV: TCocoaTableListView;
+ lNSColumn: NSTableColumn;
+begin
+ if not CheckColumnParams(lTableLV, lNSColumn, ALV, AIndex) then Exit;
+
+ case ASortIndicator of
+ siNone:
+ lTableLV.setIndicatorImage_inTableColumn(nil, lNSColumn);
+ siAscending:
+ lTableLV.setIndicatorImage_inTableColumn(
+ NSImage.imageNamed(NSSTR('NSAscendingSortIndicator')),
+ lNSColumn);
+ siDescending:
+ lTableLV.setIndicatorImage_inTableColumn(
+ NSImage.imageNamed(NSSTR('NSDescendingSortIndicator')),
+ lNSColumn);
+ end;
+end;
+
class procedure TCocoaWSCustomListView.ItemDelete(const ALV: TCustomListView;
const AIndex: Integer);
var
diff --git a/lcl/interfaces/gtk2/gtk2wscomctrls.pp b/lcl/interfaces/gtk2/gtk2wscomctrls.pp
index e48d88f4f4..1c48969128 100644
--- a/lcl/interfaces/gtk2/gtk2wscomctrls.pp
+++ b/lcl/interfaces/gtk2/gtk2wscomctrls.pp
@@ -153,6 +153,9 @@ type
class procedure ColumnSetMinWidth(const ALV: TCustomListView; const AIndex: Integer; const {%H-}AColumn: TListColumn; const AMinWidth: integer); override;
class procedure ColumnSetWidth(const ALV: TCustomListView; const AIndex: Integer; const {%H-}AColumn: TListColumn; const AWidth: Integer); override;
class procedure ColumnSetVisible(const ALV: TCustomListView; const AIndex: Integer; const {%H-}AColumn: TListColumn; const AVisible: Boolean); override;
+ class procedure ColumnSetSortIndicator(const ALV: TCustomListView; const AIndex: Integer;
+ const AColumn: TListColumn; const ASortIndicator: TSortIndicator);
+ override;
// items
class procedure ItemDelete(const ALV: TCustomListView; const AIndex: Integer); override;
diff --git a/lcl/interfaces/gtk2/gtk2wscustomlistview.inc b/lcl/interfaces/gtk2/gtk2wscustomlistview.inc
index c30cadc920..4cd9bfa637 100644
--- a/lcl/interfaces/gtk2/gtk2wscustomlistview.inc
+++ b/lcl/interfaces/gtk2/gtk2wscustomlistview.inc
@@ -1083,6 +1083,36 @@ begin
end;
end;
+class procedure TGtk2WSCustomListView.ColumnSetSortIndicator(
+ const ALV: TCustomListView; const AIndex: Integer;
+ const AColumn: TListColumn; const ASortIndicator: TSortIndicator);
+const
+ GtkOrder : array [ TSortIndicator] of TGtkSortType = (0, GTK_SORT_ASCENDING, GTK_SORT_DESCENDING);
+var
+ Widgets: PTVWidgets;
+ GtkColumn: PGtkTreeViewColumn;
+begin
+ if not WSCheckHandleAllocated(ALV, 'ColumnSetCaption')
+ then Exit;
+
+ GetCommonTreeViewWidgets({%H-}PGtkWidget(ALV.Handle), Widgets);
+
+ if not GTK_IS_TREE_VIEW(Widgets^.MainView) then
+ Exit;
+
+ GtkColumn := gtk_tree_view_get_column(PGtkTreeView(Widgets^.MainView), AIndex);
+ if GtkColumn <> nil then
+ begin
+ if ASortIndicator = siNone then
+ gtk_tree_view_column_set_sort_indicator(GtkColumn, false)
+ else
+ begin
+ gtk_tree_view_column_set_sort_indicator(GtkColumn, true);
+ gtk_tree_view_column_set_sort_order(GtkColumn, GtkOrder[ASortIndicator]);
+ end;
+ end;
+end;
+
class procedure TGtk2WSCustomListView.ItemDelete(const ALV: TCustomListView;
const AIndex: Integer);
var
diff --git a/lcl/interfaces/qt5/qtwscomctrls.pp b/lcl/interfaces/qt5/qtwscomctrls.pp
index c8d63728d5..2d8b71601f 100644
--- a/lcl/interfaces/qt5/qtwscomctrls.pp
+++ b/lcl/interfaces/qt5/qtwscomctrls.pp
@@ -128,6 +128,9 @@ type
class procedure ColumnSetMinWidth(const ALV: TCustomListView; const AIndex: Integer; const AColumn: TListColumn; const AMinWidth: integer); override;
class procedure ColumnMove(const ALV: TCustomListView; const AOldIndex, ANewIndex: Integer; const AColumn: TListColumn); override;
+ class procedure ColumnSetSortIndicator(const ALV: TCustomListView; const AIndex: Integer;
+ const AColumn: TListColumn; const ASortIndicator: TSortIndicator);
+ override;
{items}
class procedure ItemInsert(const ALV: TCustomListView; const AIndex: Integer; const AItem: TListItem); override;
@@ -865,6 +868,33 @@ begin
QtTreeWidget.Header.moveSection(AOldIndex, ANewIndex);
end;
+class procedure TQtWSCustomListView.ColumnSetSortIndicator(
+ const ALV: TCustomListView; const AIndex: Integer;
+ const AColumn: TListColumn; const ASortIndicator: TSortIndicator);
+const
+ QtSortOrder : array [TSortIndicator] of QtSortOrder = (QtAscendingOrder, QtAscendingOrder, QtDescendingOrder);
+var
+ QtTreeWidget: TQtTreeWidget;
+begin
+ if not WSCheckHandleAllocated(ALV, 'ColumnSetCaption') then
+ Exit;
+
+ if IsIconView(ALV) then
+ exit;
+
+ QtTreeWidget := TQtTreeWidget(ALV.Handle);
+ if Assigned(QtTreeWidget) then
+ begin
+ if ASortIndicator = siNone then
+ QtTreeWidget.Header.SetSortIndicatorVisible(false)
+ else
+ begin
+ QtTreeWidget.Header.SetSortIndicatorVisible(true);
+ QtTreeWidget.Header.SetSortIndicator(AIndex, QtSortOrder[ASortIndicator]);
+ end;
+ end;
+end;
+
{------------------------------------------------------------------------------
Method: TQtWSCustomListView.ColumnSetAlignment
Params: None
diff --git a/lcl/interfaces/win32/win32wscomctrls.pp b/lcl/interfaces/win32/win32wscomctrls.pp
index 9741a9034d..358ac77d58 100644
--- a/lcl/interfaces/win32/win32wscomctrls.pp
+++ b/lcl/interfaces/win32/win32wscomctrls.pp
@@ -137,6 +137,7 @@ type
class procedure ColumnSetMinWidth(const ALV: TCustomListView; const AIndex: Integer; const AColumn: TListColumn; const AMinWidth: integer); override;
class procedure ColumnSetWidth(const ALV: TCustomListView; const AIndex: Integer; const AColumn: TListColumn; const AWidth: Integer); override;
class procedure ColumnSetVisible(const ALV: TCustomListView; const AIndex: Integer; const AColumn: TListColumn; const AVisible: Boolean); override;
+ class procedure ColumnSetSortIndicator(const ALV: TCustomListView; const AIndex: Integer; const AColumn: TListColumn; const AAndicator: TSortIndicator); override;
// items
class procedure ItemDelete(const ALV: TCustomListView; const AIndex: Integer); override;
diff --git a/lcl/interfaces/win32/win32wscustomlistview.inc b/lcl/interfaces/win32/win32wscustomlistview.inc
index 4f086da451..06c8d5f3a2 100644
--- a/lcl/interfaces/win32/win32wscustomlistview.inc
+++ b/lcl/interfaces/win32/win32wscustomlistview.inc
@@ -484,6 +484,28 @@ begin
else ListView_SetColumnWidth(ALV.Handle, AIndex, 0);
end;
+class procedure TWin32WSCustomListView.ColumnSetSortIndicator(
+ const ALV: TCustomListView; const AIndex: Integer;
+ const AColumn: TListColumn; const AAndicator: TSortIndicator);
+var
+ Hdr: HWND;
+ Itm: THDITEM;
+begin
+ if not WSCheckHandleAllocated(ALV, 'ColumnSetSortIndicator')
+ then Exit;
+
+ Hdr := ListView_GetHeader(ALV.Handle);
+ FillChar(itm, sizeof(itm),0);
+ itm.mask := HDI_FORMAT;
+ Header_GetItem(Hdr, AIndex, Itm);
+ case AAndicator of
+ siNone: itm.fmt := itm.fmt and (not (HDF_SORTDOWN or HDF_SORTUP));
+ siAscending: itm.fmt := (itm.fmt or HDF_SORTUP) and (not HDF_SORTDOWN);
+ siDescending: itm.fmt := (itm.fmt or HDF_SORTDOWN) and (not HDF_SORTUP);
+ end;
+ Header_SetItem(Hdr, AIndex, Itm);
+end;
+
////////////////////////////////////////////////////////////////////////////////
// Item code
////////////////////////////////////////////////////////////////////////////////
diff --git a/lcl/widgetset/wscomctrls.pp b/lcl/widgetset/wscomctrls.pp
index c95341fcd3..2972e58849 100644
--- a/lcl/widgetset/wscomctrls.pp
+++ b/lcl/widgetset/wscomctrls.pp
@@ -120,6 +120,7 @@ type
class procedure ColumnSetMinWidth(const ALV: TCustomListView; const AIndex: Integer; const AColumn: TListColumn; const AMinWidth: integer); virtual;
class procedure ColumnSetWidth(const ALV: TCustomListView; const AIndex: Integer; const AColumn: TListColumn; const AWidth: Integer); virtual;
class procedure ColumnSetVisible(const ALV: TCustomListView; const AIndex: Integer; const AColumn: TListColumn; const AVisible: Boolean); virtual;
+ class procedure ColumnSetSortIndicator(const ALV: TCustomListView; const AIndex: Integer; const AColumn: TListColumn; const ASortIndicator: TSortIndicator); virtual;
// Item
class procedure ItemDelete(const ALV: TCustomListView; const AIndex: Integer); virtual;
@@ -539,6 +540,13 @@ class procedure TWSCustomListView.ColumnSetVisible(const ALV: TCustomListView;
begin
end;
+class procedure TWSCustomListView.ColumnSetSortIndicator(
+ const ALV: TCustomListView; const AIndex: Integer;
+ const AColumn: TListColumn; const ASortIndicator: TSortIndicator);
+begin
+
+end;
+
class procedure TWSCustomListView.ItemDelete(const ALV: TCustomListView;
const AIndex: Integer);
begin