Browse Source

fix file selection and update button

johann 5 years ago
parent
commit
7276a04d51
2 changed files with 110 additions and 52 deletions
  1. 11 4
      lazpaint/dialog/ubrowseimages.pas
  2. 99 48
      lazpaint/umyslv.pas

+ 11 - 4
lazpaint/dialog/ubrowseimages.pas

@@ -70,6 +70,7 @@ type
     function GetCurrentDirectory: string;
     procedure SetCurrentDirectory(AValue: string);
     function AdaptExtension: boolean;
+    procedure ShellListView1SelectionChanged(Sender: TObject);
   private
     FLazPaintInstance: TLazPaintCustomInstance;
     FDefaultExtension: string;
@@ -169,7 +170,7 @@ uses BGRAThumbnail, BGRAPaintNet, BGRAOpenRaster, BGRAReadLzp,
     Types, UResourceStrings,
     UConfig, bgrareadjpeg, FPReadJPEG,
     UFileExtensions, BGRAUTF8, LazFileUtils,
-    UGraph, URaw, UDarkTheme;
+    UGraph, URaw, UDarkTheme, ShellCtrls;
 
 var
   IconCache: TStringList;
@@ -292,8 +293,10 @@ begin
   SetShellMask;
   ShellListView1.OnDblClick := @ShellListView1DblClick;
   ShellListView1.OnSelectItem := @ShellListView1SelectItem;
+  ShellListView1.OnSelectionChanged:=@ShellListView1SelectionChanged;
   ShellListView1.OnSort := @ShellListView1OnSort;
   ShellListView1.OnFormatType := @ShellListView1OnFormatType;
+  ShellListView1.SelectAllAction := [otNonFolders];
 
   BGRAPaintNet.RegisterPaintNetFormat;
   BGRAOpenRaster.RegisterOpenRasterFormat;
@@ -474,20 +477,19 @@ begin
   wasTimer := Timer1.Enabled;
   Timer1.Enabled := false;
 
-  if not InFilenameChange and ShellListView1.ItemSelected[Item] then
+  if not InFilenameChange and Selected then
   begin
     InFilenameChange := true;
     Edit_Filename.Text := ShellListView1.ItemName[Item];
     InFilenameChange := false;
   end;
 
-  if ShellListView1.ItemSelected[Item] and not ShellListView1.ItemIsFolder[Item] then
+  if Selected and not ShellListView1.ItemIsFolder[Item] then
     UpdatePreview(ShellListView1.ItemFullName[Item])
   else
     if FPreviewFilename = ShellListView1.ItemFullName[Item] then
       UpdatePreview('');
 
-  UpdateToolButtonOpen;
   Timer1.Enabled := wasTimer;
 end;
 
@@ -724,6 +726,11 @@ begin
     result := false;
 end;
 
+procedure TFBrowseImages.ShellListView1SelectionChanged(Sender: TObject);
+begin
+  UpdateToolButtonOpen;
+end;
+
 procedure TFBrowseImages.UpdateToolButtonOpen;
 var chosenFilename: string;
 begin

+ 99 - 48
lazpaint/umyslv.pas

@@ -32,6 +32,7 @@ type
   private
     FAllowMultiSelect: boolean;
     FOnDblClick: TNotifyEvent;
+    FOnSelectionChanged: TNotifyEvent;
     FOnSelectItem: TSelectItemEvent;
     FSortColumn: integer;
     FVirtualScreen: TBGRAVirtualScreen;
@@ -105,8 +106,11 @@ type
     procedure Clear;
     function GetItemFullName(AIndex: integer): string;
     function GetItemDisplayRect(AIndex: integer): TRect;
+    function InternalSelectAll: boolean;
+    function InternalDeselectAll(AExcept: integer = -1): boolean;
   public
     DetailIconSize, SmallIconSize, LargeIconSize, FontHeight, MinimumRowHeight: integer;
+    SelectAllAction: TObjectTypes;
     IconPadding: integer;
     BytesCaption: string;
     { Basic methods }
@@ -135,6 +139,7 @@ type
     property ViewStyle: TViewStyle read GetViewStyleFit write SetViewStyleFit;
     property OnDblClick: TNotifyEvent read FOnDblClick write SetOnDblClick;
     property OnSelectItem: TSelectItemEvent read FOnSelectItem write SetOnSelectItem;
+    property OnSelectionChanged: TNotifyEvent read FOnSelectionChanged write FOnSelectionChanged;
     property SortColumn: integer read FSortColumn write SetSortColumn;
     property OnSort: TNotifyEvent read FOnSort write FOnSort;
     property OnFormatType: TFormatTypeEvent read FOnFormatType write FOnFormatType;
@@ -843,8 +848,8 @@ end;
 
 procedure TLCShellListView.MouseDown(Sender: TObject; Button: TMouseButton;
   Shift: TShiftState; X, Y: Integer);
-var i,idx,prevItem:integer;
-  prevItemWasSelected:boolean;
+var i,idx, prevIdx:integer;
+  keepSelection, selChanged:boolean;
 begin
   SetFocus;
   for i := 0 to ColumnCount-1 do
@@ -862,38 +867,60 @@ begin
       exit;
     end;
   idx := GetItemAt(X,Y);
-  prevItem := FSelectedIndex;
-  prevItemWasSelected := (prevItem <> -1) and ItemSelected[prevItem];
-  if not (ssSnap in Shift) or not FAllowMultiSelect then DeselectAll;
-  if (ssShift in Shift) and (prevItem <> -1) and (idx <> -1) and FAllowMultiSelect then
+  keepSelection := (ssSnap in Shift) and FAllowMultiSelect;
+  selChanged := false;
+  if not keepSelection and InternalDeselectAll(FSelectedIndex) then selChanged := true;
+  if (ssShift in Shift) and (FSelectedIndex <> -1) and (idx <> -1) and FAllowMultiSelect then
   begin
-    FSelectedIndex:= prevItem;
-    ItemSelected[FSelectedIndex] := prevItemWasSelected;
-    while idx <> FSelectedIndex do
+    if idx <> FSelectedIndex then
     begin
-      if FSelectedIndex > idx then dec(FSelectedIndex) else inc(FSelectedIndex);
-      ItemSelected[FSelectedIndex] := not ItemSelected[FSelectedIndex];
+      while idx <> FSelectedIndex do
+      begin
+        if FSelectedIndex > idx then dec(FSelectedIndex) else inc(FSelectedIndex);
+        ItemSelected[FSelectedIndex] := not ItemSelected[FSelectedIndex];
+        selChanged := true;
+      end;
+      if not ItemSelected[FSelectedIndex] then FSelectedIndex := -1;
+      if Assigned(FOnSelectItem) then FOnSelectItem(self, FSelectedIndex, ItemSelected[FSelectedIndex]);
     end;
-    InvalidateView;
   end else
-  if idx <> -1 then
   begin
-    ItemSelected[idx] := not ItemSelected[idx];
-    if ItemSelected[idx] then
-      FSelectedIndex := idx
-    else
-      FSelectedIndex:= -1;
-    InvalidateView;
+    if keepSelection then
+    begin
+      if idx <> -1 then
+      begin
+        ItemSelected[idx] := not ItemSelected[idx];
+        if ItemSelected[idx] then FSelectedIndex := idx
+        else if idx = FSelectedIndex then FSelectedIndex := -1;
+        if Assigned(FOnSelectItem) then FOnSelectItem(self, idx, ItemSelected[idx]);
+        selChanged := true;
+      end;
+    end else
+    if idx <> FSelectedIndex then
+    begin
+      if FSelectedIndex <> -1 then
+      begin
+        prevIdx := FSelectedIndex;
+        ItemSelected[prevIdx] := false;
+        FSelectedIndex := -1;
+        if Assigned(FOnSelectItem) then FOnSelectItem(self, prevIdx, false);
+        selChanged := true;
+      end;
+      if idx <> -1 then
+      begin
+        ItemSelected[idx] := true;
+        FSelectedIndex := idx;
+        if Assigned(FOnSelectItem) then FOnSelectItem(self, idx, true);
+        selChanged := true;
+      end;
+    end;
   end;
-  if (FSelectedIndex <> prevItem) then
+  if selChanged then
   begin
-    if prevItemWasSelected and not ((prevItem <> -1) and ItemSelected[prevItem]) then
-      if Assigned(FOnSelectItem) then FOnSelectItem(self,prevItem,False);
+    InvalidateView;
     if (FSelectedIndex <> -1) and ItemSelected[FSelectedIndex] then
-    begin
-      if Assigned(FOnSelectItem) then FOnSelectItem(self,FSelectedIndex,true);
       MakeItemVisible(FSelectedIndex);
-    end;
+    if Assigned(FOnSelectionChanged) then FOnSelectionChanged(self);
   end;
 end;
 
@@ -1150,6 +1177,7 @@ begin
   IconPadding := 8;
   FObjectTypes := [otFolders, otNonFolders];
   FSortColumn:= -1;
+  SelectAllAction := [otFolders, otNonFolders];
 end;
 
 procedure TLCShellListView.VirtualScreenFreed;
@@ -1219,6 +1247,48 @@ begin
     result := FData[AIndex].displayRect;
 end;
 
+function TLCShellListView.InternalSelectAll: boolean;
+var i:integer;
+begin
+  result:= false;
+  for i := 0 to ItemCount-1 do
+    if not FData[i].isSelected and
+      ((FData[i].isFolder and (otFolders in SelectAllAction)) or
+       (not FData[i].isFolder and (otNonFolders in SelectAllAction))) then
+    begin
+      FData[i].isSelected := true;
+      result := true;
+    end;
+  for i := 0 to ItemCount-1 do
+    if FData[i].isSelected and
+      ((FData[i].isFolder and not (otFolders in SelectAllAction)) or
+       (not FData[i].isFolder and not (otNonFolders in SelectAllAction))) then
+    begin
+      FData[i].isSelected := false;
+      result := true;
+    end;
+
+  if result then InvalidateView;
+end;
+
+function TLCShellListView.InternalDeselectAll(AExcept: integer): boolean;
+var i:integer;
+begin
+  result:= false;
+  for i := 0 to ItemCount-1 do
+    if (i <> AExcept) and FData[i].isSelected then
+    begin
+      FData[i].isSelected := false;
+      if FSelectedIndex = i then
+      begin
+        FSelectedIndex := -1;
+        if Assigned(FOnSelectItem) then FOnSelectItem(self, i, False);
+      end;
+      result := true;
+    end;
+  if result then InvalidateView;
+end;
+
 procedure TLCShellListView.Sort;
 var lst: TList;
   i: integer;
@@ -1286,34 +1356,15 @@ begin
 end;
 
 procedure TLCShellListView.DeselectAll;
-var i:integer;
-  discard: boolean;
 begin
-  discard:= false;
-  for i := 0 to ItemCount-1 do
-    if FData[i].isSelected then
-    begin
-      FData[i].isSelected := false;
-      discard := true;
-    end;
-  FSelectedIndex := -1;
-  if discard then InvalidateView;
+  if InternalDeselectAll then
+    if Assigned(FOnSelectionChanged) then FOnSelectionChanged(self);
 end;
 
 procedure TLCShellListView.SelectAll;
-var i:integer;
-  discard: boolean;
 begin
-  discard:= false;
-  for i := 0 to ItemCount-1 do
-    if not FData[i].isSelected then
-    begin
-      FData[i].isSelected := true;
-      if not discard then
-        FSelectedIndex := i;
-      discard := true;
-    end;
-  if discard then InvalidateView;
+  if InternalSelectAll then
+    if Assigned(FOnSelectionChanged) then FOnSelectionChanged(self);
 end;
 
 end.