diff --git a/docs/xml/lcl/comctrls.xml b/docs/xml/lcl/comctrls.xml index 6ff875948d..10db87181b 100644 --- a/docs/xml/lcl/comctrls.xml +++ b/docs/xml/lcl/comctrls.xml @@ -18727,6 +18727,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 af6ac6f6ac..3078eef122 100644 --- a/lcl/comctrls.pp +++ b/lcl/comctrls.pp @@ -1188,6 +1188,8 @@ type TWidth = 0..MaxInt; + TSortIndicator = (siNone, siAscending, siDescending); + TListColumn = class(TCollectionItem) private FAlignment: TAlignment; @@ -1199,6 +1201,7 @@ type FWidth: TWidth; FImageIndex: TImageIndex; FTag: PtrInt; + FSortIndicator: TSortIndicator; function GetWidth: TWidth; procedure WSCreateColumn; procedure WSDestroyColumn; @@ -1212,6 +1215,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; @@ -1231,6 +1235,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; @@ -1373,6 +1378,7 @@ type FEditor: TCustomListViewEditor; FAllocBy: Integer; FAutoSort: Boolean; + FAutoSortIndicator: Boolean; FAutoWidthLastColumn: Boolean; FCanvas: TCanvas; FDefaultItemHeight: integer; @@ -1537,6 +1543,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; @@ -1655,6 +1662,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 8753dfe949..f50af0cda2 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 780fde4b38..66484a6e02 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; @@ -1237,6 +1238,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 5201b413c9..129ecae468 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 6313e9f64b..b43db16885 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/gtk3/gtk3widgets.pas b/lcl/interfaces/gtk3/gtk3widgets.pas index b4b40e6870..90930e1415 100644 --- a/lcl/interfaces/gtk3/gtk3widgets.pas +++ b/lcl/interfaces/gtk3/gtk3widgets.pas @@ -564,6 +564,7 @@ type procedure SetColumnMinWidth(AIndex: Integer; AColumn: TListColumn; AMinWidth: Integer); procedure SetColumnWidth(AIndex: Integer; AColumn: TListColumn; AWidth: Integer); procedure SetColumnVisible(AIndex: Integer; AColumn: TListColumn; AVisible: Boolean); + procedure ColumnSetSortIndicator(const AIndex: Integer; const AColumn: TListColumn; const ASortIndicator: TSortIndicator); procedure ItemDelete(AIndex: Integer); procedure ItemInsert(AIndex: Integer; AItem: TListItem); @@ -5635,6 +5636,27 @@ begin end; end; +procedure TGtk3ListView.ColumnSetSortIndicator(const AIndex: Integer; + const AColumn: TListColumn; const ASortIndicator: TSortIndicator); +const + GtkOrder : array [ TSortIndicator] of TGtkSortType = (0, {GTK_SORT_ASCENDING}0, {GTK_SORT_DESCENDING}1); +var + AGtkColumn: PGtkTreeViewColumn; +begin + AGtkColumn := PGtkTreeView(getContainerWidget)^.get_column(AIndex); + + if AGtkColumn <> nil then + begin + if ASortIndicator = siNone then + AGtkColumn^.set_sort_indicator(false) + else + begin + AGtkColumn^.set_sort_indicator(true); + AgtkColumn^.set_sort_order(GtkOrder[ASortIndicator]); + end; + end; +end; + procedure TGtk3ListView.ItemDelete(AIndex: Integer); var AModel: PGtkTreeModel; diff --git a/lcl/interfaces/gtk3/gtk3wscomctrls.pp b/lcl/interfaces/gtk3/gtk3wscomctrls.pp index 1b3a26e678..b005849f69 100644 --- a/lcl/interfaces/gtk3/gtk3wscomctrls.pp +++ b/lcl/interfaces/gtk3/gtk3wscomctrls.pp @@ -121,6 +121,8 @@ 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; @@ -595,6 +597,19 @@ begin TGtk3ListView(ALV.Handle).SetColumnVisible(AIndex, AColumn, AVisible); end; +class procedure TGtk3WSCustomListView.ColumnSetSortIndicator( + const ALV: TCustomListView; const AIndex: Integer; + const AColumn: TListColumn; const ASortIndicator: TSortIndicator); +begin + if not WSCheckHandleAllocated(ALV, 'ColumnSetSortIndicator') then + Exit; + + TGtk3ListView(ALV.Handle).ColumnSetSortIndicator(AIndex,AColumn,ASortIndicator); +end; + + + + type TListItemHack = class(TListItem) end; 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 92287257da..57b915df12 100644 --- a/lcl/interfaces/win32/win32wscustomlistview.inc +++ b/lcl/interfaces/win32/win32wscustomlistview.inc @@ -475,6 +475,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 30e62548c7..b14fa00e52 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; @@ -538,6 +539,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