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