Browse Source

Bug 582: Toolbar buttons can be hidden

https://winscp.net/tracker/582

Source commit: 497415de7fdd788b555d96bd7394f50f62fd4e2c
Martin Prikryl 7 years ago
parent
commit
bb6d9ddf8f

+ 10 - 0
source/core/Common.cpp

@@ -260,6 +260,16 @@ UnicodeString CopyToChar(const UnicodeString & Str, wchar_t Ch, bool Trim)
   return CopyToChars(Str, From, UnicodeString(Ch), Trim);
 }
 //---------------------------------------------------------------------------
+UnicodeString RemoveSuffix(const UnicodeString & Str, const UnicodeString & Suffix)
+{
+  UnicodeString Result = Str;
+  if (EndsStr(Suffix, Result))
+  {
+    Result.SetLength(Result.Length() - Suffix.Length());
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
 UnicodeString DelimitStr(UnicodeString Str, UnicodeString Chars)
 {
   for (int i = 1; i <= Str.Length(); i++)

+ 1 - 0
source/core/Common.h

@@ -50,6 +50,7 @@ UnicodeString CutToChar(UnicodeString &Str, wchar_t Ch, bool Trim);
 UnicodeString CopyToChars(const UnicodeString & Str, int & From, UnicodeString Chs, bool Trim,
   wchar_t * Delimiter = NULL, bool DoubleDelimiterEscapes = false);
 UnicodeString CopyToChar(const UnicodeString & Str, wchar_t Ch, bool Trim);
+UnicodeString RemoveSuffix(const UnicodeString & Str, const UnicodeString & Suffix);
 UnicodeString DelimitStr(UnicodeString Str, UnicodeString Chars);
 UnicodeString ShellDelimitStr(UnicodeString Str, wchar_t Quote);
 UnicodeString ExceptionLogString(Exception *E);

+ 81 - 1
source/forms/CustomScpExplorer.cpp

@@ -1238,9 +1238,39 @@ void __fastcall TCustomScpExplorerForm::SetDockAllowDrag(bool value)
   }
 }
 //---------------------------------------------------------------------------
-void __fastcall TCustomScpExplorerForm::LoadToolbarsLayoutStr(UnicodeString LayoutStr)
+void __fastcall TCustomScpExplorerForm::LoadToolbarsLayoutStr(UnicodeString LayoutStr, UnicodeString ButtonsStr)
 {
   SetDockAllowDrag(true);
+
+  while (!ButtonsStr.IsEmpty())
+  {
+    UnicodeString S = CutToChar(ButtonsStr, L';', true);
+    UnicodeString Name = CutToChar(S, L'=', true);
+    for (int ToolbarIndex = 0; ToolbarIndex < ComponentCount; ToolbarIndex++)
+    {
+      TTBCustomToolbar * Toolbar = dynamic_cast<TTBCustomToolbar *>(Components[ToolbarIndex]);
+      if ((Toolbar != NULL) && SameText(Name, GetToolbarKey(Toolbar->Name)))
+      {
+        while (!S.IsEmpty())
+        {
+          UnicodeString S2 = CutToChar(S, L',', true);
+          UnicodeString Name = CutToChar(S2, L':', true);
+          for (int ItemIndex = 0; ItemIndex < Toolbar->Items->Count; ItemIndex++)
+          {
+            TTBCustomItem * Item = Toolbar->Items->Items[ItemIndex];
+            if (SameText(GetToolbarItemName(Item), Name))
+            {
+              // forward compatibility
+              UnicodeString S3 = CutToChar(S2, L':', true);
+              bool Visible = StrToIntDef(S3, 0);
+              Item->Visible = Visible;
+            }
+          }
+        }
+      }
+    }
+  }
+
   ::LoadToolbarsLayoutStr(this, LayoutStr);
   SetDockAllowDrag(!WinConfiguration->LockToolbars);
 }
@@ -1254,6 +1284,56 @@ UnicodeString __fastcall TCustomScpExplorerForm::GetToolbarsLayoutStr()
   return Result;
 }
 //---------------------------------------------------------------------------
+UnicodeString __fastcall TCustomScpExplorerForm::GetToolbarItemName(TTBCustomItem * Item)
+{
+  UnicodeString Result;
+  if (Item->Action != NULL)
+  {
+    Result = Item->Action->Name;
+    Result = RemoveSuffix(Result, L"Action");
+  }
+  else
+  {
+    Result = Item->Name;
+    Result = RemoveSuffix(Result, L"SubmenuItem");
+    Result = RemoveSuffix(Result, L"Item");
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
+UnicodeString __fastcall TCustomScpExplorerForm::GetToolbarsButtonsStr()
+{
+  UnicodeString Result;
+  for (int ToolbarIndex = 0; ToolbarIndex < ComponentCount; ToolbarIndex++)
+  {
+    UnicodeString ToolbarStr;
+    TTBCustomToolbar * Toolbar = dynamic_cast<TTBCustomToolbar *>(Components[ToolbarIndex]);
+    if ((Toolbar != NULL) && (Toolbar != QueueToolbar))
+    {
+      for (int ItemIndex = 0; ItemIndex < Toolbar->Items->Count; ItemIndex++)
+      {
+        TTBCustomItem * Item = Toolbar->Items->Items[ItemIndex];
+        // Currently all buttons are visible by default, so we can safely remember all hidden buttons.
+        // Once we introduce any buttons that aer hidden by default, we would have to remember their initial state
+        // and save the changes here only.
+        if (!Item->Visible)
+        {
+          UnicodeString Name = GetToolbarItemName(Item);
+          DebugAssert(Name.Pos(L"TBX") == 0);
+          AddToList(ToolbarStr, FORMAT(L"%s:0", (Name)), L",");
+        }
+      }
+    }
+
+    if (!ToolbarStr.IsEmpty())
+    {
+      AddToList(Result, FORMAT(L"%s=%s", (GetToolbarKey(Toolbar->Name), ToolbarStr)), L";");
+    }
+  }
+
+  return Result;
+}
+//---------------------------------------------------------------------------
 void __fastcall TCustomScpExplorerForm::FileOperationProgress(
   TFileOperationProgressType & ProgressData)
 {

+ 4 - 2
source/forms/CustomScpExplorer.h

@@ -341,7 +341,6 @@ protected:
   bool __fastcall RemoteTransferFiles(TStrings * FileList, bool NoConfirmation,
     bool Move, TTerminal * Session);
   virtual void __fastcall DoDirViewExecFile(TObject * Sender, TListItem * Item, bool & AllowExec);
-  virtual TControl * __fastcall GetComponent(Byte Component);
   bool __fastcall GetComponentVisible(Byte Component);
   virtual Boolean __fastcall GetHasDirView(TOperationSide Side);
   DYNAMIC void __fastcall KeyDown(Word & Key, Classes::TShiftState Shift);
@@ -498,8 +497,10 @@ protected:
   inline bool __fastcall CustomCommandRemoteAllowed();
   void __fastcall CustomCommandMenu(
     TAction * Action, TStrings * LocalFileList, TStrings * RemoteFileList);
-  void __fastcall LoadToolbarsLayoutStr(UnicodeString LayoutStr);
+  void __fastcall LoadToolbarsLayoutStr(UnicodeString LayoutStr, UnicodeString ButtonsStr);
+  UnicodeString __fastcall GetToolbarItemName(TTBCustomItem * Item);
   UnicodeString __fastcall GetToolbarsLayoutStr();
+  UnicodeString __fastcall GetToolbarsButtonsStr();
   virtual void __fastcall Dispatch(void * Message);
   void __fastcall PostComponentHide(Byte Component);
   void __fastcall GetSpaceAvailable(const UnicodeString Path,
@@ -618,6 +619,7 @@ public:
   void __fastcall UnlockWindow();
   void __fastcall SuspendWindowLock();
   void __fastcall ResumeWindowLock();
+  virtual TControl * __fastcall GetComponent(Byte Component);
 
   void __fastcall NewSession(bool FromSite, const UnicodeString & SessionUrl = L"");
   void __fastcall DuplicateSession();

+ 2 - 9
source/forms/FileSystemInfo.cpp

@@ -259,18 +259,11 @@ void __fastcall TFileSystemInfoDialog::ClipboardAddItem(TControl * Control,
         TLabel * Label = dynamic_cast<TLabel *>(Control->Parent->Controls[Index]);
         if ((Label != NULL) && (Label->FocusControl == Control))
         {
-          UnicodeString S = StripHotkey(Label->Caption);
-          if (EndsStr(L":", S))
-          {
-            S.SetLength(S.Length() - 1);
-          }
+          UnicodeString S = RemoveSuffix(StripHotkey(Label->Caption), L":");
           FClipboard += FORMAT(L"%s = ", (S));
         }
       }
-      if (EndsStr(L"\r\n", Value))
-      {
-        Value.SetLength(Value.Length() - 2);
-      }
+      Value = RemoveSuffix(Value, L"\r\n");
       FClipboard += FORMAT(L"%s\r\n", (Value));
     }
     else

+ 83 - 52
source/forms/NonVisual.cpp

@@ -80,6 +80,34 @@ TNonVisualDataModule *NonVisualDataModule;
 #define EXESHCOL(SIDE, PREFIX, COL) \
   EXE(ShowHide ## SIDE ## COL ## ColumnAction, \
     COLPROPS(SIDE)->Visible[PREFIX ## COL] = !COLPROPS(SIDE)->Visible[PREFIX ## COL])
+
+#define BAND_COMPONENTS \
+  EMIT_BAND_COMPONENT(ExplorerMenuBand) \
+  EMIT_BAND_COMPONENT(ExplorerAddressBand) \
+  EMIT_BAND_COMPONENT(ExplorerToolbarBand) \
+  EMIT_BAND_COMPONENT(ExplorerSelectionBand) \
+  EMIT_BAND_COMPONENT(ExplorerSessionBand) \
+  EMIT_BAND_COMPONENT(ExplorerPreferencesBand) \
+  EMIT_BAND_COMPONENT(ExplorerSortBand) \
+  EMIT_BAND_COMPONENT(ExplorerUpdatesBand) \
+  EMIT_BAND_COMPONENT(ExplorerTransferBand) \
+  EMIT_BAND_COMPONENT(ExplorerCustomCommandsBand) \
+  EMIT_BAND_COMPONENT(CommanderMenuBand) \
+  EMIT_BAND_COMPONENT(CommanderSessionBand) \
+  EMIT_BAND_COMPONENT(CommanderPreferencesBand) \
+  EMIT_BAND_COMPONENT(CommanderSortBand) \
+  EMIT_BAND_COMPONENT(CommanderCommandsBand) \
+  EMIT_BAND_COMPONENT(CommanderUpdatesBand) \
+  EMIT_BAND_COMPONENT(CommanderTransferBand) \
+  EMIT_BAND_COMPONENT(CommanderCustomCommandsBand) \
+  EMIT_BAND_COMPONENT(CommanderLocalHistoryBand) \
+  EMIT_BAND_COMPONENT(CommanderLocalNavigationBand) \
+  EMIT_BAND_COMPONENT(CommanderLocalFileBand) \
+  EMIT_BAND_COMPONENT(CommanderLocalSelectionBand) \
+  EMIT_BAND_COMPONENT(CommanderRemoteHistoryBand) \
+  EMIT_BAND_COMPONENT(CommanderRemoteNavigationBand) \
+  EMIT_BAND_COMPONENT(CommanderRemoteFileBand) \
+  EMIT_BAND_COMPONENT(CommanderRemoteSelectionBand)
 //---------------------------------------------------------------------------
 __fastcall TNonVisualDataModule::TNonVisualDataModule(TComponent* Owner)
         : TDataModule(Owner)
@@ -283,32 +311,11 @@ void __fastcall TNonVisualDataModule::ExplorerActionsUpdate(
   UPDCOMP(CommandLinePanel)
   UPDCOMP(RemoteTree)
   UPDCOMP(LocalTree)
-  UPDCOMP(ExplorerMenuBand)
-  UPDCOMP(ExplorerAddressBand)
-  UPDCOMP(ExplorerToolbarBand)
-  UPDCOMP(ExplorerSelectionBand)
-  UPDCOMP(ExplorerSessionBand)
-  UPDCOMP(ExplorerPreferencesBand)
-  UPDCOMP(ExplorerSortBand)
-  UPDCOMP(ExplorerUpdatesBand)
-  UPDCOMP(ExplorerTransferBand)
-  UPDCOMP(ExplorerCustomCommandsBand)
-  UPDCOMP(CommanderMenuBand)
-  UPDCOMP(CommanderSessionBand)
-  UPDCOMP(CommanderPreferencesBand)
-  UPDCOMP(CommanderSortBand)
-  UPDCOMP(CommanderCommandsBand)
-  UPDCOMP(CommanderUpdatesBand)
-  UPDCOMP(CommanderTransferBand)
-  UPDCOMP(CommanderCustomCommandsBand)
-  UPDCOMP(CommanderLocalHistoryBand)
-  UPDCOMP(CommanderLocalNavigationBand)
-  UPDCOMP(CommanderLocalFileBand)
-  UPDCOMP(CommanderLocalSelectionBand)
-  UPDCOMP(CommanderRemoteHistoryBand)
-  UPDCOMP(CommanderRemoteNavigationBand)
-  UPDCOMP(CommanderRemoteFileBand)
-  UPDCOMP(CommanderRemoteSelectionBand)
+  #define EMIT_BAND_COMPONENT(COMP) UPDCOMP(COMP)
+  BAND_COMPONENTS
+  #undef EMIT_BAND_COMPONENT
+
+
 
   UPD(GoToCommandLineAction, true)
   UPD(GoToTreeAction, true)
@@ -621,32 +628,9 @@ void __fastcall TNonVisualDataModule::ExplorerActionsExecute(
     EXECOMP(ToolBar2)
     EXECOMP(LocalStatusBar)
     EXECOMP(RemoteStatusBar)
-    EXECOMP(ExplorerMenuBand)
-    EXECOMP(ExplorerAddressBand)
-    EXECOMP(ExplorerToolbarBand)
-    EXECOMP(ExplorerSelectionBand)
-    EXECOMP(ExplorerSessionBand)
-    EXECOMP(ExplorerPreferencesBand)
-    EXECOMP(ExplorerSortBand)
-    EXECOMP(ExplorerUpdatesBand)
-    EXECOMP(ExplorerTransferBand)
-    EXECOMP(ExplorerCustomCommandsBand)
-    EXECOMP(CommanderMenuBand)
-    EXECOMP(CommanderSessionBand)
-    EXECOMP(CommanderPreferencesBand)
-    EXECOMP(CommanderSortBand)
-    EXECOMP(CommanderCommandsBand)
-    EXECOMP(CommanderUpdatesBand)
-    EXECOMP(CommanderTransferBand)
-    EXECOMP(CommanderCustomCommandsBand)
-    EXECOMP(CommanderLocalHistoryBand)
-    EXECOMP(CommanderLocalNavigationBand)
-    EXECOMP(CommanderLocalFileBand)
-    EXECOMP(CommanderLocalSelectionBand)
-    EXECOMP(CommanderRemoteHistoryBand)
-    EXECOMP(CommanderRemoteNavigationBand)
-    EXECOMP(CommanderRemoteFileBand)
-    EXECOMP(CommanderRemoteSelectionBand)
+    #define EMIT_BAND_COMPONENT(COMP) EXECOMP(COMP)
+    BAND_COMPONENTS
+    #undef EMIT_BAND_COMPONENT
     EXECOMP(CommandLinePanel)
     EXECOMP(RemoteTree)
     EXECOMP(LocalTree)
@@ -1820,3 +1804,50 @@ void __fastcall TNonVisualDataModule::QueuePopupSpeedComboBoxItemAdjustImageInde
   ImageIndex = Sender->ImageIndex;
 }
 //---------------------------------------------------------------------------
+void __fastcall TNonVisualDataModule::ToolbarButtonItemClick(TObject * Sender)
+{
+  TTBCustomItem * Item = DebugNotNull(dynamic_cast<TTBCustomItem *>(Sender));
+  TTBCustomItem * ButtonItem = reinterpret_cast<TTBCustomItem *>(Item->Tag);
+  ButtonItem->Visible = !ButtonItem->Visible;
+}
+//---------------------------------------------------------------------------
+void __fastcall TNonVisualDataModule::ToolbarComponentPopup(TTBCustomItem * Sender, bool /*FromLink*/)
+{
+  Byte Component = 0;
+  #define EMIT_BAND_COMPONENT(COMP) if (Sender->Action == COMP ## Action) { Component = fc ## COMP; }
+  BAND_COMPONENTS
+  #undef EMIT_BAND_COMPONENT
+
+  if (DebugAlwaysTrue(Component != 0))
+  {
+    TTBCustomToolbar * Toolbar = dynamic_cast<TTBCustomToolbar *>(ScpExplorer->GetComponent(Component));
+    if (DebugAlwaysTrue(Toolbar != NULL))
+    {
+      Sender->Clear();
+
+      for (int Index = 0; Index < Toolbar->Items->Count; Index++)
+      {
+        TTBCustomItem * ButtonItem = Toolbar->Items->Items[Index];
+
+        TTBCustomItem * Item;
+        if (dynamic_cast<TTBSeparatorItem *>(ButtonItem) != NULL)
+        {
+          Item = new TTBSeparatorItem(Sender);
+        }
+        else
+        {
+          Item = new TTBXItem(Sender);
+          Item->Caption = StripEllipsis(ButtonItem->Caption);
+          Item->ImageIndex = ButtonItem->ImageIndex;
+          Item->Tag = reinterpret_cast<int>(ButtonItem);
+          Item->OnClick = ToolbarButtonItemClick;
+          Item->Checked = ButtonItem->Visible;
+          Item->Enabled = Toolbar->Visible;
+        }
+
+        Sender->Insert(Sender->Count, Item);
+      }
+    }
+  }
+}
+//---------------------------------------------------------------------------

+ 75 - 25
source/forms/NonVisual.dfm

@@ -2233,20 +2233,30 @@ object NonVisualDataModule: TNonVisualDataModule
     object Address2: TTBXItem
       Action = ExplorerAddressBandAction
     end
-    object StandardButtons1: TTBXItem
+    object StandardButtons1: TTBXSubmenuItem
       Action = ExplorerToolbarBandAction
+      DropdownCombo = True
+      OnPopup = ToolbarComponentPopup
     end
-    object SelectionButtons1: TTBXItem
+    object SelectionButtons1: TTBXSubmenuItem
       Action = ExplorerSelectionBandAction
+      DropdownCombo = True
+      OnPopup = ToolbarComponentPopup
     end
-    object SessionButtons2: TTBXItem
+    object SessionButtons2: TTBXSubmenuItem
       Action = ExplorerSessionBandAction
+      DropdownCombo = True
+      OnPopup = ToolbarComponentPopup
     end
-    object PreferencesButtons1: TTBXItem
+    object PreferencesButtons1: TTBXSubmenuItem
       Action = ExplorerPreferencesBandAction
+      DropdownCombo = True
+      OnPopup = ToolbarComponentPopup
     end
-    object SortButtons3: TTBXItem
+    object SortButtons3: TTBXSubmenuItem
       Action = ExplorerSortBandAction
+      DropdownCombo = True
+      OnPopup = ToolbarComponentPopup
     end
     object TBXItem3: TTBXItem
       Action = ExplorerUpdatesBandAction
@@ -2316,17 +2326,25 @@ object NonVisualDataModule: TNonVisualDataModule
     Options = [tboShowHint]
     Left = 424
     Top = 264
-    object CommandsButtons2: TTBXItem
+    object CommandsButtons2: TTBXSubmenuItem
       Action = CommanderCommandsBandAction
+      DropdownCombo = True
+      OnPopup = ToolbarComponentPopup
     end
-    object SessionButtons5: TTBXItem
+    object SessionButtons5: TTBXSubmenuItem
       Action = CommanderSessionBandAction
+      DropdownCombo = True
+      OnPopup = ToolbarComponentPopup
     end
-    object PreferencesButtons4: TTBXItem
+    object PreferencesButtons4: TTBXSubmenuItem
       Action = CommanderPreferencesBandAction
+      DropdownCombo = True
+      OnPopup = ToolbarComponentPopup
     end
-    object SortButtons2: TTBXItem
+    object SortButtons2: TTBXSubmenuItem
       Action = CommanderSortBandAction
+      DropdownCombo = True
+      OnPopup = ToolbarComponentPopup
     end
     object TBXItem2: TTBXItem
       Action = CommanderUpdatesBandAction
@@ -2363,17 +2381,25 @@ object NonVisualDataModule: TNonVisualDataModule
       Caption = '&Local Panel'
       HelpKeyword = 'ui_file_panel'
       Hint = 'Change local panel layout'
-      object HistoryButtons3: TTBXItem
+      object HistoryButtons3: TTBXSubmenuItem
         Action = CommanderLocalHistoryBandAction
+        DropdownCombo = True
+        OnPopup = ToolbarComponentPopup
       end
-      object NavigationButtons3: TTBXItem
+      object NavigationButtons3: TTBXSubmenuItem
         Action = CommanderLocalNavigationBandAction
+        DropdownCombo = True
+        OnPopup = ToolbarComponentPopup
       end
-      object TBXItem40: TTBXItem
+      object TBXItem40: TTBXSubmenuItem
         Action = CommanderLocalFileBandAction
+        DropdownCombo = True
+        OnPopup = ToolbarComponentPopup
       end
-      object TBXItem43: TTBXItem
+      object TBXItem43: TTBXSubmenuItem
         Action = CommanderLocalSelectionBandAction
+        DropdownCombo = True
+        OnPopup = ToolbarComponentPopup
       end
       object N23: TTBXSeparatorItem
       end
@@ -2390,17 +2416,25 @@ object NonVisualDataModule: TNonVisualDataModule
       Caption = '&Remote Panel'
       HelpKeyword = 'ui_file_panel'
       Hint = 'Change remote panel layout'
-      object HistoryButtons4: TTBXItem
+      object HistoryButtons4: TTBXSubmenuItem
         Action = CommanderRemoteHistoryBandAction
+        DropdownCombo = True
+        OnPopup = ToolbarComponentPopup
       end
-      object NavigationButtons4: TTBXItem
+      object NavigationButtons4: TTBXSubmenuItem
         Action = CommanderRemoteNavigationBandAction
+        DropdownCombo = True
+        OnPopup = ToolbarComponentPopup
       end
-      object TBXItem41: TTBXItem
+      object TBXItem41: TTBXSubmenuItem
         Action = CommanderRemoteFileBandAction
+        DropdownCombo = True
+        OnPopup = ToolbarComponentPopup
       end
-      object TBXItem42: TTBXItem
+      object TBXItem42: TTBXSubmenuItem
         Action = CommanderRemoteSelectionBandAction
+        DropdownCombo = True
+        OnPopup = ToolbarComponentPopup
       end
       object N25: TTBXSeparatorItem
       end
@@ -2463,17 +2497,25 @@ object NonVisualDataModule: TNonVisualDataModule
     end
     object N51: TTBXSeparatorItem
     end
-    object HistoryButtons5: TTBXItem
+    object HistoryButtons5: TTBXSubmenuItem
       Action = CommanderRemoteHistoryBandAction
+      DropdownCombo = True
+      OnPopup = ToolbarComponentPopup
     end
-    object NavigationButtons5: TTBXItem
+    object NavigationButtons5: TTBXSubmenuItem
       Action = CommanderRemoteNavigationBandAction
+      DropdownCombo = True
+      OnPopup = ToolbarComponentPopup
     end
-    object TBXItem14: TTBXItem
+    object TBXItem14: TTBXSubmenuItem
       Action = CommanderRemoteFileBandAction
+      DropdownCombo = True
+      OnPopup = ToolbarComponentPopup
     end
-    object TBXItem45: TTBXItem
+    object TBXItem45: TTBXSubmenuItem
       Action = CommanderRemoteSelectionBandAction
+      DropdownCombo = True
+      OnPopup = ToolbarComponentPopup
     end
     object TBXItem37: TTBXItem
       Action = LockToolbarsAction
@@ -2514,17 +2556,25 @@ object NonVisualDataModule: TNonVisualDataModule
     end
     object N52: TTBXSeparatorItem
     end
-    object HistoryButtons6: TTBXItem
+    object HistoryButtons6: TTBXSubmenuItem
       Action = CommanderLocalHistoryBandAction
+      DropdownCombo = True
+      OnPopup = ToolbarComponentPopup
     end
-    object NavigationButtons6: TTBXItem
+    object NavigationButtons6: TTBXSubmenuItem
       Action = CommanderLocalNavigationBandAction
+      DropdownCombo = True
+      OnPopup = ToolbarComponentPopup
     end
-    object TBXItem39: TTBXItem
+    object TBXItem39: TTBXSubmenuItem
       Action = CommanderLocalFileBandAction
+      DropdownCombo = True
+      OnPopup = ToolbarComponentPopup
     end
-    object TBXItem44: TTBXItem
+    object TBXItem44: TTBXSubmenuItem
       Action = CommanderLocalSelectionBandAction
+      DropdownCombo = True
+      OnPopup = ToolbarComponentPopup
     end
     object TBXItem38: TTBXItem
       Action = LockToolbarsAction

+ 27 - 25
source/forms/NonVisual.h

@@ -235,25 +235,25 @@ __published:    // IDE-managed Components
   TAction *FileGenerateUrlAction2;
   TAction *TableOfContentsAction;
   TTBXPopupMenu *CommanderBarPopup;
-  TTBXItem *SessionButtons5;
-  TTBXItem *PreferencesButtons4;
-  TTBXItem *SortButtons2;
-  TTBXItem *CommandsButtons2;
+  TTBXSubmenuItem *SessionButtons5;
+  TTBXSubmenuItem *PreferencesButtons4;
+  TTBXSubmenuItem *SortButtons2;
+  TTBXSubmenuItem *CommandsButtons2;
   TTBXSeparatorItem *N26;
   TTBXItem *CommandLine2;
   TTBXItem *CommandsToolbar1;
   TTBXItem *StatusBar8;
   TTBXSeparatorItem *N27;
   TTBXSubmenuItem *LocalPanel1;
-  TTBXItem *HistoryButtons3;
-  TTBXItem *NavigationButtons3;
+  TTBXSubmenuItem *HistoryButtons3;
+  TTBXSubmenuItem *NavigationButtons3;
   TTBXSeparatorItem *N23;
   TTBXItem *Tree7;
   TTBXSeparatorItem *N77;
   TTBXItem *StatusBar6;
   TTBXSubmenuItem *RemotePanel2;
-  TTBXItem *HistoryButtons4;
-  TTBXItem *NavigationButtons4;
+  TTBXSubmenuItem *HistoryButtons4;
+  TTBXSubmenuItem *NavigationButtons4;
   TTBXSeparatorItem *N25;
   TTBXItem *Tree8;
   TTBXSeparatorItem *N78;
@@ -270,8 +270,8 @@ __published:    // IDE-managed Components
   TTBXItem *CopyPathtoClipboard1;
   TTBXItem *OpenDirectoryBookmark1;
   TTBXSeparatorItem *N51;
-  TTBXItem *HistoryButtons5;
-  TTBXItem *NavigationButtons5;
+  TTBXSubmenuItem *HistoryButtons5;
+  TTBXSubmenuItem *NavigationButtons5;
   TTBXSeparatorItem *N28;
   TTBXItem *Tree5;
   TTBXSeparatorItem *N75;
@@ -280,8 +280,8 @@ __published:    // IDE-managed Components
   TTBXItem *CopyPathtoClipboard2;
   TTBXItem *OpenDirectoryBookmark2;
   TTBXSeparatorItem *N52;
-  TTBXItem *HistoryButtons6;
-  TTBXItem *NavigationButtons6;
+  TTBXSubmenuItem *HistoryButtons6;
+  TTBXSubmenuItem *NavigationButtons6;
   TTBXSeparatorItem *N29;
   TTBXItem *Tree6;
   TTBXSeparatorItem *N76;
@@ -379,11 +379,11 @@ __published:    // IDE-managed Components
   TTBXItem *Customize3;
   TTBXPopupMenu *ExplorerBarPopup;
   TTBXItem *Address2;
-  TTBXItem *StandardButtons1;
-  TTBXItem *SelectionButtons1;
-  TTBXItem *SessionButtons2;
-  TTBXItem *PreferencesButtons1;
-  TTBXItem *SortButtons3;
+  TTBXSubmenuItem *StandardButtons1;
+  TTBXSubmenuItem *SelectionButtons1;
+  TTBXSubmenuItem *SessionButtons2;
+  TTBXSubmenuItem *PreferencesButtons1;
+  TTBXSubmenuItem *SortButtons3;
   TTBXSeparatorItem *N5;
   TTBXItem *StatusBar2;
   TTBXSeparatorItem *N72;
@@ -514,10 +514,10 @@ __published:    // IDE-managed Components
   TAction *RemoteAddEditLinkAction2;
   TAction *CommanderLocalFileBandAction;
   TAction *CommanderRemoteFileBandAction;
-  TTBXItem *TBXItem14;
-  TTBXItem *TBXItem39;
-  TTBXItem *TBXItem40;
-  TTBXItem *TBXItem41;
+  TTBXSubmenuItem *TBXItem14;
+  TTBXSubmenuItem *TBXItem39;
+  TTBXSubmenuItem *TBXItem40;
+  TTBXSubmenuItem *TBXItem41;
   TAction *RemoteCopyFocusedAction;
   TAction *RemoteMoveFocusedAction;
   TAction *LocalSelectAction;
@@ -528,10 +528,10 @@ __published:    // IDE-managed Components
   TAction *RemoteSelectAllAction;
   TAction *CommanderLocalSelectionBandAction;
   TAction *CommanderRemoteSelectionBandAction;
-  TTBXItem *TBXItem42;
-  TTBXItem *TBXItem43;
-  TTBXItem *TBXItem44;
-  TTBXItem *TBXItem45;
+  TTBXSubmenuItem *TBXItem42;
+  TTBXSubmenuItem *TBXItem43;
+  TTBXSubmenuItem *TBXItem44;
+  TTBXSubmenuItem *TBXItem45;
   TAction *SelectiveToolbarTextAction;
   TTBXItem *TBXItem46;
   TTBXItem *TBXItem47;
@@ -623,6 +623,7 @@ __published:    // IDE-managed Components
           const UnicodeString AText, int AIndex, int &ImageIndex);
   UnicodeString __fastcall CustomCommandCaption(const TCustomCommandType * Command, bool Toolbar);
   UnicodeString __fastcall CustomCommandHint(const TCustomCommandType * Command);
+  void __fastcall ToolbarComponentPopup(TTBCustomItem *Sender, bool FromLink);
 
 private:
   TListColumn * FListColumn;
@@ -668,6 +669,7 @@ protected:
   void __fastcall SetQueueOnceEmptyAction(TAction * Action);
   TAction * __fastcall CurrentQueueOnceEmptyAction();
   void __fastcall CloneShortcuts();
+  void __fastcall ToolbarButtonItemClick(TObject * Sender);
 
 public:
   __fastcall TNonVisualDataModule(TComponent * Owner);

+ 2 - 1
source/forms/ScpCommander.cpp

@@ -157,7 +157,7 @@ void __fastcall TScpCommanderForm::RestoreParams()
 
   TCustomScpExplorerForm::RestoreParams();
   LeftPanelWidth = WinConfiguration->ScpCommander.LocalPanelWidth;
-  LoadToolbarsLayoutStr(WinConfiguration->ScpCommander.ToolbarsLayout);
+  LoadToolbarsLayoutStr(WinConfiguration->ScpCommander.ToolbarsLayout, WinConfiguration->ScpCommander.ToolbarsButtons);
   SessionsPageControl->Visible = WinConfiguration->ScpCommander.SessionsTabs;
   StatusBar->Visible = WinConfiguration->ScpCommander.StatusBar;
 
@@ -187,6 +187,7 @@ void __fastcall TScpCommanderForm::StoreParams()
   try
   {
     WinConfiguration->ScpCommander.ToolbarsLayout = GetToolbarsLayoutStr();
+    WinConfiguration->ScpCommander.ToolbarsButtons = GetToolbarsButtonsStr();
     WinConfiguration->ScpCommander.LocalPanelWidth = LeftPanelWidth;
     WinConfiguration->ScpCommander.SessionsTabs = SessionsPageControl->Visible;
     WinConfiguration->ScpCommander.StatusBar = StatusBar->Visible;

+ 2 - 1
source/forms/ScpExplorer.cpp

@@ -95,7 +95,7 @@ void __fastcall TScpExplorerForm::RestoreParams()
     RemoteDirView->HandleNeeded();
   }
 
-  LoadToolbarsLayoutStr(WinConfiguration->ScpExplorer.ToolbarsLayout);
+  LoadToolbarsLayoutStr(WinConfiguration->ScpExplorer.ToolbarsLayout, WinConfiguration->ScpExplorer.ToolbarsButtons);
   SessionsPageControl->Visible = WinConfiguration->ScpExplorer.SessionsTabs;
   RemoteStatusBar->Visible = WinConfiguration->ScpExplorer.StatusBar;
   RemoteDriveView->Visible = WinConfiguration->ScpExplorer.DriveView;
@@ -112,6 +112,7 @@ void __fastcall TScpExplorerForm::StoreParams()
   try
   {
     WinConfiguration->ScpExplorer.ToolbarsLayout = GetToolbarsLayoutStr();
+    WinConfiguration->ScpExplorer.ToolbarsButtons = GetToolbarsButtonsStr();
     WinConfiguration->ScpExplorer.SessionsTabs = SessionsPageControl->Visible;
     WinConfiguration->ScpExplorer.StatusBar = RemoteStatusBar->Visible;
 

+ 8 - 11
source/windows/UserInterface.cpp

@@ -415,20 +415,17 @@ int __fastcall GetToolbarLayoutPixelsPerInch(TStrings * Storage, TControl * Cont
   return Result;
 }
 //---------------------------------------------------------------------
+UnicodeString __fastcall GetToolbarKey(const UnicodeString & ToolbarName)
+{
+  UnicodeString Result = ToolbarName;
+  Result = RemoveSuffix(Result, L"Toolbar");
+  return Result;
+}
+//---------------------------------------------------------------------
 static inline void __fastcall GetToolbarKey(const UnicodeString & ToolbarName,
   const UnicodeString & Value, UnicodeString & ToolbarKey)
 {
-  int ToolbarNameLen;
-  if ((ToolbarName.Length() > 7) &&
-      (ToolbarName.SubString(ToolbarName.Length() - 7 + 1, 7) == L"Toolbar"))
-  {
-    ToolbarNameLen = ToolbarName.Length() - 7;
-  }
-  else
-  {
-    ToolbarNameLen = ToolbarName.Length();
-  }
-  ToolbarKey = ToolbarName.SubString(1, ToolbarNameLen) + L"_" + Value;
+  ToolbarKey = GetToolbarKey(ToolbarName) + L"_" + Value;
 }
 //---------------------------------------------------------------------------
 static int __fastcall ToolbarReadInt(const UnicodeString ToolbarName,

+ 4 - 0
source/windows/WinConfiguration.cpp

@@ -642,6 +642,7 @@ void __fastcall TWinConfiguration::Default()
        "Transfer_Visible=1,Transfer_DockedTo=TopDock,Transfer_LastDock=TopDock,Transfer_DockRow=4,Transfer_DockPos=194,Transfer_FloatLeft=0,Transfer_FloatTop=0,Transfer_FloatRightX=0,"
        "CustomCommands_Visible=0,CustomCommands_DockedTo=TopDock,CustomCommands_LastDock=TopDock,CustomCommands_DockRow=7,CustomCommands_DockPos=0,CustomCommands_FloatLeft=0,CustomCommands_FloatTop=0,CustomCommands_FloatRightX=0,") +
     PixelsPerInchToolbarValue;
+  FScpExplorer.ToolbarsButtons = UnicodeString();
   FScpExplorer.SessionsTabs = true;
   FScpExplorer.StatusBar = true;
   FScpExplorer.LastLocalTargetDirectory = GetPersonalFolder();
@@ -686,6 +687,7 @@ void __fastcall TWinConfiguration::Default()
        "Toolbar2_Visible=0,Toolbar2_DockedTo=BottomDock,Toolbar2_LastDock=BottomDock,Toolbar2_DockRow=1,Toolbar2_DockPos=0,Toolbar2_FloatLeft=0,Toolbar2_FloatTop=0,Toolbar2_FloatRightX=1,"
        "CommandLine_Visible=0,CommandLine_DockedTo=BottomDock,CommandLine_LastDock=BottomDock,CommandLine_DockRow=0,CommandLine_DockPos=0,CommandLine_FloatLeft=0,CommandLine_FloatTop=0,CommandLine_FloatRightX=0,") +
     PixelsPerInchToolbarValue;
+  FScpCommander.ToolbarsButtons = UnicodeString();
   FScpCommander.CurrentPanel = osLocal;
   FScpCommander.CompareByTime = true;
   FScpCommander.CompareBySize = false;
@@ -1039,6 +1041,7 @@ THierarchicalStorage * TWinConfiguration::CreateScpStorage(bool & SessionList)
   ); \
   BLOCK(L"Interface\\Explorer", CANCREATE, \
     KEY(String,  ScpExplorer.ToolbarsLayout); \
+    KEY(String,  ScpExplorer.ToolbarsButtons); \
     KEY(String,  ScpExplorer.DirViewParams); \
     KEY(String,  ScpExplorer.LastLocalTargetDirectory); \
     KEY(Bool,    ScpExplorer.SessionsTabs); \
@@ -1052,6 +1055,7 @@ THierarchicalStorage * TWinConfiguration::CreateScpStorage(bool & SessionList)
   ); \
   BLOCK(L"Interface\\Commander", CANCREATE, \
     KEY(String,  ScpCommander.ToolbarsLayout); \
+    KEY(String,  ScpCommander.ToolbarsButtons); \
     KEY(Integer, ScpCommander.CurrentPanel); \
     KEY(Float,   ScpCommander.LocalPanelWidth); \
     KEY(Bool,    ScpCommander.SwappedPanels); \

+ 4 - 2
source/windows/WinConfiguration.h

@@ -16,6 +16,7 @@ struct TScpExplorerConfiguration {
   UnicodeString WindowParams;
   UnicodeString DirViewParams;
   UnicodeString ToolbarsLayout;
+  UnicodeString ToolbarsButtons;
   bool SessionsTabs;
   bool StatusBar;
   UnicodeString LastLocalTargetDirectory;
@@ -25,7 +26,7 @@ struct TScpExplorerConfiguration {
   int DriveViewWidth;
   int DriveViewWidthPixelsPerInch;
   bool __fastcall operator !=(TScpExplorerConfiguration & rhc)
-    { return C(WindowParams) C(DirViewParams) C(ToolbarsLayout)
+    { return C(WindowParams) C(DirViewParams) C(ToolbarsLayout) C(ToolbarsButtons)
         C(SessionsTabs) C(StatusBar)
         C(LastLocalTargetDirectory) C(ViewStyle) C(ShowFullAddress)
         C(DriveView) C(DriveViewWidth) C(DriveViewWidthPixelsPerInch) 0; };
@@ -49,6 +50,7 @@ struct TScpCommanderConfiguration {
   UnicodeString WindowParams;
   double LocalPanelWidth;
   UnicodeString ToolbarsLayout;
+  UnicodeString ToolbarsButtons;
   bool SessionsTabs;
   bool StatusBar;
   TOperationSide CurrentPanel;
@@ -63,7 +65,7 @@ struct TScpCommanderConfiguration {
   bool ExplorerKeyboardShortcuts;
   bool SystemContextMenu;
   bool __fastcall operator !=(TScpCommanderConfiguration & rhc)
-    { return C(WindowParams) C(LocalPanelWidth) C(ToolbarsLayout)
+    { return C(WindowParams) C(LocalPanelWidth) C(ToolbarsLayout) C(ToolbarsButtons)
       C(SessionsTabs) C(StatusBar)
       C(LocalPanel) C(RemotePanel) C(CurrentPanel)
       C(NortonLikeMode) C(PreserveLocalDirectory)

+ 1 - 0
source/windows/WinInterface.h

@@ -91,6 +91,7 @@ bool __fastcall CheckSafe(TProgramParams * Params);
 void __fastcall CheckLogParam(TProgramParams * Params);
 bool __fastcall CheckXmlLogParam(TProgramParams * Params);
 
+UnicodeString __fastcall GetToolbarKey(const UnicodeString & ToolbarName);
 UnicodeString __fastcall GetToolbarsLayoutStr(TControl * OwnerControl);
 void __fastcall LoadToolbarsLayoutStr(TControl * OwnerControl, UnicodeString LayoutStr);