瀏覽代碼

When switching tabs, prevent visibly scrolling the panels when focusing the last selected file

Partially rolls back/reimplements Bug 1057 from a128fd8e.

Also fixes not compilable DScpComp and broken /Browse switch caused by the same commit

Source commit: f7c5a4d72cd7f63ebdbf67255492a38cb33af169
Martin Prikryl 4 年之前
父節點
當前提交
ffaff0adc5

+ 33 - 18
source/components/UnixDirView.cpp

@@ -53,7 +53,7 @@ __fastcall TUnixDirView::TUnixDirView(TComponent* Owner)
   FFullLoad = false;
   FDriveView = NULL;
   FInvalidNameChars = L"/";
-  FLoadingDriveViewState = NULL;
+  FAnnouncedDriveViewState = NULL;
   DragDropFilesEx->PreferCopy = true;
 }
 //---------------------------------------------------------------------------
@@ -559,6 +559,12 @@ void __fastcall TUnixDirView::SetTerminal(TTerminal * value)
   DoSetTerminal(value, false);
 }
 //---------------------------------------------------------------------------
+void __fastcall TUnixDirView::ReplaceTerminal(TTerminal * value)
+{
+  DoSetTerminal(value, true);
+}
+#endif
+//---------------------------------------------------------------------------
 class TUnixDirViewState : public TObject
 {
 public:
@@ -577,35 +583,44 @@ TObject * __fastcall TUnixDirView::SaveState()
   return State;
 }
 //---------------------------------------------------------------------------
-void TUnixDirView::LoadTerminal(TTerminal * value, bool Replace, TObject * State)
+void __fastcall TUnixDirView::AnnounceState(TObject * State)
 {
   TObject * CustomDirViewState = NULL;
-  TObject * DriveViewState = NULL;
   if (State != NULL)
   {
     TUnixDirViewState * UnixDirViewState = dynamic_cast<TUnixDirViewState *>(State);
-    if (DebugAlwaysTrue(UnixDirViewState != NULL))
+    if (UnixDirViewState != NULL)
     {
+      FAnnouncedDriveViewState = UnixDirViewState->DriveViewState.get();
       CustomDirViewState = UnixDirViewState->CustomDirViewState.get();
-      DriveViewState = UnixDirViewState->DriveViewState.get();
+    }
+    else
+    {
+      // It might be TCustomDirView state from CreateDirViewStateForFocusedItem.
+      CustomDirViewState = State;
     }
   }
-  TValueRestorer<TObject *> LoadingStateRestorer(FLoadingDriveViewState);
-  FLoadingDriveViewState = DriveViewState;
-
-  DoSetTerminal(value, Replace);
-
-  if (value->Active)
-  {
-    value->RefreshDirectory();
-  }
-
-  if (CustomDirViewState != NULL)
+  TCustomDirView::AnnounceState(CustomDirViewState);
+}
+//---------------------------------------------------------------------------
+void __fastcall TUnixDirView::RestoreState(TObject * State)
+{
+  TObject * CustomDirViewState = NULL;
+  if (State != NULL)
   {
-    RestoreState(CustomDirViewState);
+    TUnixDirViewState * UnixDirViewState = dynamic_cast<TUnixDirViewState *>(State);
+    if (UnixDirViewState != NULL)
+    {
+      CustomDirViewState = UnixDirViewState->CustomDirViewState.get();
+    }
+    else
+    {
+      // See the comment in AnnounceState
+      CustomDirViewState = State;
+    }
   }
+  TCustomDirView::RestoreState(CustomDirViewState);
 }
-#endif
 //---------------------------------------------------------------------------
 void __fastcall TUnixDirView::DoStartReadDirectory(TObject * /*Sender*/)
 {

+ 4 - 2
source/components/UnixDirView.h

@@ -35,7 +35,7 @@ private:
   bool __fastcall GetActive();
   TCustomUnixDriveView * FDriveView;
   TNotifyEvent FOnRead;
-  TObject * FLoadingDriveViewState;
+  TObject * FAnnouncedDriveViewState;
   void __fastcall SetTerminal(TTerminal *value);
   void __fastcall DoSetTerminal(TTerminal *value, bool Replace);
   void __fastcall SetShowInaccesibleDirectories(bool value);
@@ -99,8 +99,10 @@ public:
   virtual bool __fastcall PasteFromClipBoard(UnicodeString TargetPath = L"");
   void __fastcall UpdateFiles();
   void __fastcall DisplayContextMenu(const TPoint &Where);
+  void __fastcall ReplaceTerminal(TTerminal * value);
+  virtual void __fastcall AnnounceState(TObject * State);
+  virtual void __fastcall RestoreState(TObject * State);
   virtual TObject * __fastcall SaveState();
-  void LoadTerminal(TTerminal * value, bool Replace, TObject * State);
 
   __property bool Active = { read = GetActive };
   __property TTerminal *Terminal = { read = FTerminal, write = SetTerminal };

+ 7 - 3
source/components/UnixDriveView.cpp

@@ -893,10 +893,10 @@ void __fastcall TCustomUnixDriveView::DisplayPropertiesMenu(TTreeNode * /*Node*/
 //---------------------------------------------------------------------------
 void TCustomUnixDriveView::LoadNodeState(TTreeNode * Node, const UnicodeString & Path)
 {
-  if ((FDirView != NULL) && (FDirView->FLoadingDriveViewState != NULL))
+  if ((FDirView != NULL) && (FDirView->FAnnouncedDriveViewState != NULL))
   {
-    TStrings * LoadingDriveViewState = DebugNotNull(dynamic_cast<TStrings *>(FDirView->FLoadingDriveViewState));
-    if (LoadingDriveViewState->IndexOf(Path) >= 0)
+    TStrings * AnnouncedDriveViewState = DebugNotNull(dynamic_cast<TStrings *>(FDirView->FAnnouncedDriveViewState));
+    if (AnnouncedDriveViewState->IndexOf(Path) >= 0)
     {
       Node->Expand(false);
     }
@@ -905,6 +905,7 @@ void TCustomUnixDriveView::LoadNodeState(TTreeNode * Node, const UnicodeString &
 //---------------------------------------------------------------------------
 TObject * TCustomUnixDriveView::SaveState()
 {
+  #ifndef DESIGN_ONLY
   std::unique_ptr<TStrings> ExpandedNodes(CreateSortedStringList());
   TTreeNode * Node = Items->GetFirstNode();
   while (Node != NULL)
@@ -917,4 +918,7 @@ TObject * TCustomUnixDriveView::SaveState()
     Node = Node->GetNext();
   }
   return ExpandedNodes.release();
+  #else
+  return NULL;
+  #endif
 }

+ 27 - 1
source/forms/CustomScpExplorer.cpp

@@ -600,8 +600,34 @@ void __fastcall TCustomScpExplorerForm::SessionChanged(bool Replaced)
     if (WinConfiguration->PreservePanelState)
     {
       State = Terminal->RemoteExplorerState;
+      DirView(osRemote)->AnnounceState(State);
+    }
+
+    try
+    {
+      if (Replaced)
+      {
+        RemoteDirView->ReplaceTerminal(Terminal);
+      }
+      else
+      {
+        RemoteDirView->Terminal = Terminal;
+      }
+
+      if (Terminal->Active)
+      {
+        Terminal->RefreshDirectory();
+      }
+
+      if (State != NULL)
+      {
+        DirView(osRemote)->RestoreState(State);
+      }
+    }
+    __finally
+    {
+      DirView(osRemote)->AnnounceState(NULL);
     }
-    RemoteDirView->LoadTerminal(Terminal, Replaced, State);
   }
   else
   {

+ 36 - 22
source/forms/ScpCommander.cpp

@@ -605,34 +605,43 @@ void __fastcall TScpCommanderForm::StartingWithoutSession()
   LocalDefaultDirectory();
 }
 //---------------------------------------------------------------------------
-void TScpCommanderForm::RestoreSessionLocalDirView(TDirView * ALocalDirView, const UnicodeString & LocalDirectory)
+void TScpCommanderForm::RestoreSessionLocalDirView(
+  TDirView * ALocalDirView, const UnicodeString & LocalDirectory, TObject * State)
 {
-  // we will load completely different directory, so particularly
-  // do not attempt to select previously selected directory
-  ALocalDirView->ContinueSession(false);
+  ALocalDirView->AnnounceState(State);
+  try
+  {
+    // we will load completely different directory, so particularly
+    // do not attempt to select previously selected directory
+    ALocalDirView->ContinueSession(false);
 
-  // reset home directory
-  ALocalDirView->HomeDirectory = L"";
+    // reset home directory
+    ALocalDirView->HomeDirectory = L"";
 
-  if (!LocalDirectory.IsEmpty() &&
-      (FFirstTerminal || !WinConfiguration->ScpCommander.PreserveLocalDirectory || ManagedSession->LocalBrowser))
-  {
-    try
-    {
-      ALocalDirView->Path = LocalDirectory;
-    }
-    catch(Exception & E)
+    if (!LocalDirectory.IsEmpty() &&
+        (FFirstTerminal || !WinConfiguration->ScpCommander.PreserveLocalDirectory || ManagedSession->LocalBrowser))
     {
-      if (!ManagedSession->SessionData->UpdateDirectories)
+      try
       {
-        ManagedSession->ShowExtendedException(&E);
+        ALocalDirView->Path = LocalDirectory;
       }
-      else
+      catch(Exception & E)
       {
-        ALocalDirView->OpenFallbackPath(LocalDirectory);
+        if (!ManagedSession->SessionData->UpdateDirectories)
+        {
+          ManagedSession->ShowExtendedException(&E);
+        }
+        else
+        {
+          ALocalDirView->OpenFallbackPath(LocalDirectory);
+        }
       }
     }
   }
+  __finally
+  {
+    ALocalDirView->AnnounceState(NULL);
+  }
 }
 //---------------------------------------------------------------------------
 void __fastcall TScpCommanderForm::SessionChanged(bool Replaced)
@@ -643,11 +652,17 @@ void __fastcall TScpCommanderForm::SessionChanged(bool Replaced)
 
   if (ManagedSession != NULL)
   {
-    RestoreSessionLocalDirView(LocalDirView, ManagedSession->StateData->LocalDirectory);
+    bool RestoreState =
+      WinConfiguration->PreservePanelState &&
+        (!WinConfiguration->ScpCommander.PreserveLocalDirectory || ManagedSession->LocalBrowser);
+
+    RestoreSessionLocalDirView(
+      LocalDirView, ManagedSession->StateData->LocalDirectory, ManagedSession->LocalExplorerState);
 
     if (ManagedSession->LocalBrowser)
     {
-      RestoreSessionLocalDirView(OtherLocalDirView, ManagedSession->StateData->OtherLocalDirectory);
+      RestoreSessionLocalDirView(
+        OtherLocalDirView, ManagedSession->StateData->OtherLocalDirectory, ManagedSession->OtherLocalExplorerState);
     }
 
     FFirstTerminal = false;
@@ -667,8 +682,7 @@ void __fastcall TScpCommanderForm::SessionChanged(bool Replaced)
       LocalDirView->HomeDirectory = ManagedSession->SessionData->LocalDirectoryExpanded;
     }
 
-    if (WinConfiguration->PreservePanelState &&
-        (!WinConfiguration->ScpCommander.PreserveLocalDirectory || ManagedSession->LocalBrowser))
+    if (RestoreState)
     {
       LocalDirView->RestoreState(ManagedSession->LocalExplorerState);
 

+ 1 - 1
source/forms/ScpCommander.h

@@ -634,7 +634,7 @@ protected:
   virtual void __fastcall UpdateRemotePathComboBox(bool TextOnly);
   void __fastcall SetToolbar2ItemAction(TTBXItem * Item, TBasicAction * Action);
   virtual void __fastcall NeedSession(bool Startup);
-  void RestoreSessionLocalDirView(TDirView * ALocalDirView, const UnicodeString & LocalDirectory);
+  void RestoreSessionLocalDirView(TDirView * ALocalDirView, const UnicodeString & LocalDirectory, TObject * State);
   virtual UnicodeString GetTabHintDetails(TManagedTerminal * ASession);
   virtual UnicodeString GetNewTabHintDetails();
 

+ 42 - 15
source/packages/filemng/CustomDirView.pas

@@ -220,6 +220,7 @@ type
     FWatchForChanges: Boolean;
     FInvalidNameChars: string;
     FDragDrive: string;
+    FAnnouncedState: TObject;
 
     procedure AddToDragFileList(FileList: TFileList; Item: TListItem); virtual;
     function CanEdit(Item: TListItem): Boolean; override;
@@ -337,7 +338,7 @@ type
     procedure UpdateDarkMode;
     procedure DoUpdateStatusBar(Force: Boolean = False);
     procedure DoCustomDrawItem(Item: TListItem; Stage: TCustomDrawStage);
-    procedure RestoreState(AState: TObject);
+    procedure RestoreFocus(FocusedItem: string);
     property ImageList16: TImageList read FImageList16;
     property ImageList32: TImageList read FImageList32;
   public
@@ -378,6 +379,8 @@ type
     function CanPasteFromClipBoard: Boolean; dynamic;
     function PasteFromClipBoard(TargetPath: string = ''): Boolean; virtual; abstract;
     function SaveState: TObject; virtual;
+    procedure RestoreState(AState: TObject); virtual;
+    procedure AnnounceState(AState: TObject); virtual;
     procedure DisplayContextMenu(Where: TPoint); virtual; abstract;
     procedure DisplayContextMenuInSitu;
     procedure UpdateStatusBar;
@@ -2054,6 +2057,10 @@ begin
 
         if DoFocusSomething then
         begin
+          if FAnnouncedState is TDirViewState then
+          begin
+            RestoreFocus(TDirViewState(FAnnouncedState).FocusedItem);
+          end;
           FocusSomething;
         end;
 
@@ -2880,12 +2887,21 @@ begin
   if FCaseSensitive then CompareFunc := CompareStr
     else CompareFunc := CompareText;
 
-  for Index := 0 to Items.Count - 1 do
+  // Optimization to avoid duplicate lookups in consequent RestoreFocus calls from Load and RestoreState.
+  if Assigned(ItemFocused) and (CompareFunc(FileName, ItemFileName(ItemFocused)) = 0) then
   begin
-    if CompareFunc(FileName, ItemFileName(Items[Index])) = 0 then
+    Result := ItemFocused;
+    Exit;
+  end
+    else
+  begin
+    for Index := 0 to Items.Count - 1 do
     begin
-      Result := Items[Index];
-      Exit;
+      if CompareFunc(FileName, ItemFileName(Items[Index])) = 0 then
+      begin
+        Result := Items[Index];
+        Exit;
+      end;
     end;
   end;
   Result := nil;
@@ -3246,6 +3262,11 @@ begin
     else FLastPath := '';
 end;
 
+procedure TCustomDirView.AnnounceState(AState: TObject);
+begin
+  FAnnouncedState := AState;
+end;
+
 function TCustomDirView.SaveState: TObject;
 var
   State: TDirViewState;
@@ -3265,11 +3286,25 @@ begin
   Result := State;
 end;
 
+procedure TCustomDirView.RestoreFocus(FocusedItem: string);
+var
+  ListItem: TListItem;
+begin
+  if FocusedItem <> '' then
+  begin
+    ListItem := FindFileItem(FocusedItem);
+    if Assigned(ListItem) then
+    begin
+      ItemFocused := ListItem;
+      ListItem.MakeVisible(False);
+    end;
+  end;
+end;
+
 procedure TCustomDirView.RestoreState(AState: TObject);
 var
   State: TDirViewState;
   DirColProperties: TCustomDirViewColProperties;
-  ListItem: TListItem;
 begin
   if Assigned(AState) then
   begin
@@ -3289,15 +3324,7 @@ begin
       DirColProperties.SortStr := State.SortStr;
     end;
     Mask := State.Mask;
-    if State.FocusedItem <> '' then
-    begin
-      ListItem := FindFileItem(State.FocusedItem);
-      if Assigned(ListItem) then
-      begin
-        ItemFocused := ListItem;
-        ListItem.MakeVisible(False);
-      end;
-    end;
+    RestoreFocus(State.FocusedItem);
   end
     else
   begin

+ 0 - 7
source/packages/filemng/DirView.pas

@@ -261,7 +261,6 @@ type
     function DuplicateSelectedFiles: Boolean; dynamic;
     procedure DisplayPropertiesMenu; override;
     procedure DisplayContextMenu(Where: TPoint); override;
-    procedure RestoreState(AState: TObject);
 
     procedure ExecuteParentDirectory; override;
     procedure ExecuteRootDirectory; override;
@@ -2455,12 +2454,6 @@ begin
   end;
 end;
 
-// Just to make it public
-procedure TDirView.RestoreState(AState: TObject);
-begin
-  inherited;
-end;
-
 procedure TDirView.GetDisplayInfo(ListItem: TListItem;
   var DispInfo: TLVItem);
 var