1
0
mirror of https://github.com/winscp/winscp.git synced 2026-10-24 02:28:55 +03:00

Preventing session tabs flicker with large number of sessions

Source commit: 03cfa5b1411b866567a4b71c69ff7c15ce61556e
This commit is contained in:
Martin Prikryl
2018-09-10 14:10:54 +00:00
parent 50c9881608
commit 2645892878
7 changed files with 155 additions and 108 deletions

View File

@@ -584,7 +584,7 @@ void __fastcall TCustomScpExplorerForm::TerminalChanged()
InitStatusBar();
}
DoTerminalListChanged(false);
DoTerminalListChanged();
if (ManagedTerminal != NULL)
{
@@ -6235,68 +6235,64 @@ void __fastcall TCustomScpExplorerForm::NeedSession(bool ReloadSessions)
}
}
//---------------------------------------------------------------------------
void __fastcall TCustomScpExplorerForm::DoTerminalListChanged(bool Force)
void __fastcall TCustomScpExplorerForm::DoTerminalListChanged()
{
TStrings * TerminalList = TTerminalManager::Instance()->TerminalList;
int ActiveTerminalIndex = TTerminalManager::Instance()->ActiveTerminalIndex;
Configuration->Usage->SetMax(L"MaxOpenedSessions", TerminalList->Count);
bool ListChanged = Force || (TerminalList->Count + 1 != SessionsPageControl->PageCount);
if (!ListChanged)
SendMessage(SessionsPageControl->Handle, WM_SETREDRAW, 0, 0);
try
{
int Index = 0;
while (!ListChanged && (Index < TerminalList->Count))
while ((SessionsPageControl->PageCount > TerminalList->Count + 1) ||
// Clear the design time unthemed tab
((SessionsPageControl->PageCount > 0) &&
(dynamic_cast<TThemeTabSheet *>(SessionsPageControl->Pages[SessionsPageControl->PageCount - 1]) == NULL)))
{
ListChanged =
(GetSessionTabTerminal(SessionsPageControl->Pages[Index]) != TerminalList->Objects[Index]) ||
(SessionsPageControl->Pages[Index]->Caption != TerminalList->Strings[Index]);
Index++;
delete SessionsPageControl->Pages[SessionsPageControl->PageCount - 1];
}
}
if (ListChanged)
{
SendMessage(SessionsPageControl->Handle, WM_SETREDRAW, 0, 0);
try
for (int Index = 0; Index <= TerminalList->Count; Index++)
{
FSessionColors->Clear();
AddFixedSessionImages();
while (SessionsPageControl->PageCount > 0)
TTabSheet * TabSheet;
if (Index >= SessionsPageControl->PageCount)
{
delete SessionsPageControl->Pages[0];
TabSheet = new TThemeTabSheet(SessionsPageControl);
TabSheet->PageControl = SessionsPageControl;
}
else
{
TabSheet = SessionsPageControl->Pages[Index];
}
for (int Index = 0; Index < TerminalList->Count; Index++)
if (Index < TerminalList->Count)
{
TThemeTabSheet * TabSheet = new TThemeTabSheet(SessionsPageControl);
TabSheet->Caption = TerminalList->Strings[Index];
TTerminal * Terminal = dynamic_cast<TTerminal *>(TerminalList->Objects[Index]);
TabSheet->Tag = reinterpret_cast<int>(Terminal);
TabSheet->PageControl = SessionsPageControl;
UpdateSessionTab(TabSheet);
}
TTabSheet * TabSheet = new TTabSheet(SessionsPageControl);
TabSheet->PageControl = SessionsPageControl;
TabSheet->ImageIndex = FNewSessionTabImageIndex;
UpdateNewSessionTab();
}
__finally
{
SendMessage(SessionsPageControl->Handle, WM_SETREDRAW, 1, 0);
else
{
TabSheet->ImageIndex = FNewSessionTabImageIndex;
TabSheet->Tag = 0; // not really needed
// We know that we are at the last page, sotherwise we could not call this (it assumes that new session tab is the last one)
UpdateNewSessionTab();
}
}
}
__finally
{
SendMessage(SessionsPageControl->Handle, WM_SETREDRAW, 1, 0);
}
SessionsPageControl->ActivePageIndex = ActiveTerminalIndex;
}
//---------------------------------------------------------------------------
void __fastcall TCustomScpExplorerForm::TerminalListChanged(TObject * /*Sender*/)
{
DoTerminalListChanged(false);
DoTerminalListChanged();
}
//---------------------------------------------------------------------------
void __fastcall TCustomScpExplorerForm::UpdateNewSessionTab()
@@ -6324,11 +6320,11 @@ void __fastcall TCustomScpExplorerForm::UpdateSessionTab(TTabSheet * TabSheet)
dynamic_cast<TManagedTerminal *>(GetSessionTabTerminal(TabSheet));
if (DebugAlwaysTrue(ManagedTerminal != NULL))
{
TColor Color =
(ManagedTerminal == FTerminal) ? FSessionColor : ManagedTerminal->StateData->Color;
TColor Color = (ManagedTerminal == FTerminal) ? FSessionColor : ManagedTerminal->StateData->Color;
TabSheet->ImageIndex = AddSessionColor(Color);
TabSheet->Caption = TTerminalManager::Instance()->GetTerminalTitle(ManagedTerminal, true);
UnicodeString TabCaption = TTerminalManager::Instance()->GetTerminalTitle(ManagedTerminal, true);
TabSheet->Caption = TabCaption;
TThemeTabSheet * ThemeTabSheet = dynamic_cast<TThemeTabSheet *>(TabSheet);
if (DebugAlwaysTrue(ThemeTabSheet != NULL))
@@ -6356,7 +6352,7 @@ bool __fastcall TCustomScpExplorerForm::SessionTabSwitched()
}
__finally
{
DoTerminalListChanged(false);
DoTerminalListChanged();
}
FSessionsPageControlNewSessionTime = Now();
@@ -6599,7 +6595,7 @@ void __fastcall TCustomScpExplorerForm::UpdatePixelsPerInchMainWindowCounter()
//---------------------------------------------------------------------------
void __fastcall TCustomScpExplorerForm::StartingDisconnected()
{
DoTerminalListChanged(true);
DoTerminalListChanged();
}
//---------------------------------------------------------------------------
void __fastcall TCustomScpExplorerForm::PopupTrayBalloon(TTerminal * Terminal,
@@ -8592,8 +8588,9 @@ void __fastcall TCustomScpExplorerForm::UpdateImages()
void __fastcall TCustomScpExplorerForm::CMDpiChanged(TMessage & Message)
{
TForm::Dispatch(&Message);
// regenerate session images
DoTerminalListChanged(true);
FSessionColors->Clear();
AddFixedSessionImages();
RegenerateSessionColorsImageList(FSessionColors, FSessionColorMaskImageIndex);
UpdateImages();
}
//---------------------------------------------------------------------------
@@ -9414,8 +9411,7 @@ int __fastcall TCustomScpExplorerForm::AddSessionColor(TColor Color)
{
if (Color != 0)
{
AddSessionColorImage(FSessionColors, Color, FSessionColorMaskImageIndex);
return FSessionColors->Count - 1;
return GetSessionColorImage(FSessionColors, Color, FSessionColorMaskImageIndex);
}
else
{

View File

@@ -596,7 +596,7 @@ protected:
void * Arg);
void __fastcall AnyInternalEditorModified(TObject * Sender, bool & Modified);
virtual void __fastcall StartingDisconnected();
void __fastcall DoTerminalListChanged(bool Force);
void __fastcall DoTerminalListChanged();
void __fastcall NeedSession(bool ReloadSessions);
bool __fastcall DraggingAllFilesFromDirView(TOperationSide Side, TStrings * FileList);
bool __fastcall SelectedAllFilesInDirView(TCustomDirView * DView);

View File

@@ -358,8 +358,7 @@ int __fastcall TLoginDialog::GetSessionImageIndex(TSessionData * Data)
int Result;
if (Data->Color != 0)
{
AddSessionColorImage(SessionTree->Images, static_cast<TColor>(Data->Color), SiteColorMaskImageIndex);
Result = SessionTree->Images->Count - 1;
Result = GetSessionColorImage(SessionTree->Images, static_cast<TColor>(Data->Color), SiteColorMaskImageIndex);
}
else
{

View File

@@ -107,7 +107,7 @@ void __fastcall TSiteAdvancedDialog::InitControls()
UpdateNavigationTree();
SelectScaledImageList(ColorImageList);
SetSessionColor((TColor)0);
FColor = TColor();
MenuButton(PrivateKeyToolsButton);
}
@@ -404,7 +404,7 @@ void __fastcall TSiteAdvancedDialog::LoadSession()
GetEncryptKeyEdit()->Text = FSessionData->EncryptKey;
// color
SetSessionColor((TColor)FSessionData->Color);
FColor = (TColor)FSessionData->Color;
}
UpdateControls();
@@ -1017,7 +1017,7 @@ void __fastcall TSiteAdvancedDialog::UpdateControls()
else
{
ColorButton->Images = ColorImageList;
ColorButton->ImageIndex = 1;
ColorButton->ImageIndex = GetSessionColorImage(ColorImageList, FColor, 0);
ColorButton->ImageAlignment = iaRight;
}
}
@@ -1423,24 +1423,9 @@ void __fastcall TSiteAdvancedDialog::ColorButtonClick(TObject * /*Sender*/)
}
//---------------------------------------------------------------------------
void __fastcall TSiteAdvancedDialog::SessionColorChange(TColor Color)
{
SetSessionColor(Color);
UpdateControls();
}
//---------------------------------------------------------------------------
void __fastcall TSiteAdvancedDialog::SetSessionColor(TColor Color)
{
FColor = Color;
while (ColorImageList->Count > 1)
{
ColorImageList->Delete(1);
}
if (Color != 0)
{
AddSessionColorImage(ColorImageList, Color, 0);
}
UpdateControls();
}
//---------------------------------------------------------------------------
TTlsVersion __fastcall TSiteAdvancedDialog::IndexToTlsVersion(int Index)

View File

@@ -347,7 +347,6 @@ private:
int __fastcall GetFtpProxyLogonType();
void __fastcall UpdateNavigationTree();
TSshProt __fastcall GetSshProt();
void __fastcall SetSessionColor(TColor Color);
void __fastcall SessionColorChange(TColor Color);
TTlsVersion __fastcall IndexToTlsVersion(int Index);
int __fastcall TlsVersionToIndex(TTlsVersion TlsVersion);

View File

@@ -496,56 +496,123 @@ bool __fastcall DeleteDirectory(const UnicodeString DirName)
return retval;
}
//---------------------------------------------------------------------------
void __fastcall AddSessionColorImage(
class TSessionColors : public TComponent
{
public:
__fastcall TSessionColors(TComponent * Owner) : TComponent(Owner)
{
Name = QualifiedClassName();
}
static TSessionColors * __fastcall Retrieve(TComponent * Component)
{
TSessionColors * SessionColors = dynamic_cast<TSessionColors *>(Component->FindComponent(QualifiedClassName()));
if (SessionColors == NULL)
{
SessionColors = new TSessionColors(Component);
}
return SessionColors;
}
typedef std::map<TColor, int> TColorMap;
TColorMap ColorMap;
};
//---------------------------------------------------------------------------
int __fastcall GetSessionColorImage(
TCustomImageList * ImageList, TColor Color, int MaskIndex)
{
// This overly complex drawing is here to support color button on SiteAdvanced
// dialog. There we use plain TImageList, instead of TPngImageList,
// TButton does not work with transparent images
// (not even TBitmap with Transparent = true)
std::unique_ptr<TBitmap> MaskBitmap(new TBitmap());
ImageList->GetBitmap(MaskIndex, MaskBitmap.get());
TSessionColors * SessionColors = TSessionColors::Retrieve(ImageList);
std::unique_ptr<TPngImage> MaskImage(new TPngImage());
MaskImage->Assign(MaskBitmap.get());
std::unique_ptr<TPngImage> ColorImage(new TPngImage(COLOR_RGB, 16, ImageList->Width, ImageList->Height));
TColor MaskTransparentColor = MaskImage->Pixels[0][0];
TColor TransparentColor = MaskTransparentColor;
// Expecting that the color to be replaced is in the centre of the image (HACK)
TColor MaskColor = MaskImage->Pixels[ImageList->Width / 2][ImageList->Height / 2];
for (int Y = 0; Y < ImageList->Height; Y++)
int Result;
TSessionColors::TColorMap::const_iterator I = SessionColors->ColorMap.find(Color);
if (I != SessionColors->ColorMap.end())
{
for (int X = 0; X < ImageList->Width; X++)
Result = I->second;
}
else
{
// This overly complex drawing is here to support color button on SiteAdvanced
// dialog. There we use plain TImageList, instead of TPngImageList,
// TButton does not work with transparent images
// (not even TBitmap with Transparent = true)
std::unique_ptr<TBitmap> MaskBitmap(new TBitmap());
ImageList->GetBitmap(MaskIndex, MaskBitmap.get());
std::unique_ptr<TPngImage> MaskImage(new TPngImage());
MaskImage->Assign(MaskBitmap.get());
std::unique_ptr<TPngImage> ColorImage(new TPngImage(COLOR_RGB, 16, ImageList->Width, ImageList->Height));
TColor MaskTransparentColor = MaskImage->Pixels[0][0];
TColor TransparentColor = MaskTransparentColor;
// Expecting that the color to be replaced is in the centre of the image (HACK)
TColor MaskColor = MaskImage->Pixels[ImageList->Width / 2][ImageList->Height / 2];
for (int Y = 0; Y < ImageList->Height; Y++)
{
TColor SourceColor = MaskImage->Pixels[X][Y];
TColor DestColor;
// this branch is pointless as long as MaskTransparentColor and
// TransparentColor are the same
if (SourceColor == MaskTransparentColor)
for (int X = 0; X < ImageList->Width; X++)
{
DestColor = TransparentColor;
TColor SourceColor = MaskImage->Pixels[X][Y];
TColor DestColor;
// this branch is pointless as long as MaskTransparentColor and
// TransparentColor are the same
if (SourceColor == MaskTransparentColor)
{
DestColor = TransparentColor;
}
else if (SourceColor == MaskColor)
{
DestColor = Color;
}
else
{
DestColor = SourceColor;
}
ColorImage->Pixels[X][Y] = DestColor;
}
else if (SourceColor == MaskColor)
{
DestColor = Color;
}
else
{
DestColor = SourceColor;
}
ColorImage->Pixels[X][Y] = DestColor;
}
std::unique_ptr<TBitmap> Bitmap(new TBitmap());
Bitmap->SetSize(ImageList->Width, ImageList->Height);
ColorImage->AssignTo(Bitmap.get());
Result = ImageList->AddMasked(Bitmap.get(), TransparentColor);
SessionColors->ColorMap.insert(std::make_pair(Color, Result));
}
return Result;
}
//---------------------------------------------------------------------------
void __fastcall RegenerateSessionColorsImageList(TCustomImageList * ImageList, int MaskIndex)
{
TSessionColors * SessionColors = TSessionColors::Retrieve(ImageList);
std::vector<TColor> Colors;
int FixedImages = ImageList->Count;
Colors.resize(FixedImages + SessionColors->ColorMap.size());
TSessionColors::TColorMap::const_iterator I = SessionColors->ColorMap.begin();
while (I != SessionColors->ColorMap.end())
{
DebugAssert(Colors[I->second] == TColor());
Colors[I->second] = I->first;
I++;
}
TSessionColors::TColorMap ColorMap = SessionColors->ColorMap;
SessionColors->ColorMap.clear();
for (size_t Index = 0; Index < Colors.size(); Index++)
{
bool IsFixedImageIndex = (Index < FixedImages);
DebugAssert((Colors[Index] == TColor()) == IsFixedImageIndex);
if (!IsFixedImageIndex)
{
GetSessionColorImage(ImageList, Colors[Index], MaskIndex);
}
}
std::unique_ptr<TBitmap> Bitmap(new TBitmap());
Bitmap->SetSize(ImageList->Width, ImageList->Height);
ColorImage->AssignTo(Bitmap.get());
ImageList->AddMasked(Bitmap.get(), TransparentColor);
DebugAssert(SessionColors->ColorMap == ColorMap);
}
//---------------------------------------------------------------------------
void __fastcall SetSubmenu(TTBXCustomItem * Item)

View File

@@ -27,7 +27,8 @@ bool __fastcall SpecialFolderLocation(int PathID, UnicodeString & Path);
UnicodeString __fastcall UniqTempDir(const UnicodeString BaseDir,
const UnicodeString Identity, bool Mask = false);
bool __fastcall DeleteDirectory(const UnicodeString DirName);
void __fastcall AddSessionColorImage(TCustomImageList * ImageList, TColor Color, int MaskIndex);
int __fastcall GetSessionColorImage(TCustomImageList * ImageList, TColor Color, int MaskIndex);
void __fastcall RegenerateSessionColorsImageList(TCustomImageList * ImageList, int MaskIndex);
void __fastcall SetSubmenu(TTBXCustomItem * Item);
typedef int __fastcall (*TCalculateWidth)(UnicodeString Text, void * Arg);
void __fastcall ApplyTabs(