Fix location of stc autocomp popup with images

The stc autocomp popup is supposed to report the location at which text
is drawn with the wxSTCListBox::CaretFromEdge function. To return the
correct value, the popup needs to compute the largest width of any
bitmap used for icons in the popup since text is drawn to the right of
the popup's images.

Previously the wxSTCListBox tried to compute this largest width when
the listbox items were set. However, Scintilla actually calls
CaretFromEdge before setting the listbox items. Consequently the
CaretFromEdge was returning a value that assumed zero width for the
list's images since images had not been set yet.

Instead, keep a running tally of the widest image width when images are
registered. This means that this variable must be moved to the
wxSTCListBoxVisualData class since that is where image registration is
handled. Also track the largest image height since that is also needed.
This commit is contained in:
New Pagodi
2020-06-24 17:23:28 -05:00
parent 8ff434c2a5
commit c11582320d

View File

@@ -2330,6 +2330,8 @@ public:
// Image data // Image data
const wxBitmap* GetImage(int i) const; const wxBitmap* GetImage(int i) const;
int GetImageAreaWidth() const;
int GetImageAreaHeight() const;
// Colour data // Colour data
void ComputeColours(); void ComputeColours();
@@ -2358,6 +2360,8 @@ private:
int m_desiredVisibleRows; int m_desiredVisibleRows;
ImgList m_imgList; ImgList m_imgList;
int m_imageAreaWidth;
int m_imageAreaHeight;
wxColour m_borderColour; wxColour m_borderColour;
wxColour m_bgColour; wxColour m_bgColour;
@@ -2381,6 +2385,7 @@ private:
}; };
wxSTCListBoxVisualData::wxSTCListBoxVisualData(int d):m_desiredVisibleRows(d), wxSTCListBoxVisualData::wxSTCListBoxVisualData(int d):m_desiredVisibleRows(d),
m_imageAreaWidth(0), m_imageAreaHeight(0),
m_useDefaultBgColour(true), m_useDefaultBgColour(true),
m_useDefaultTextColour(true), m_useDefaultTextColour(true),
m_useDefaultHighlightBgColour(true), m_useDefaultHighlightBgColour(true),
@@ -2414,10 +2419,40 @@ void wxSTCListBoxVisualData::RegisterImage(int type, const wxBitmap& bmp)
return; return;
ImgList::iterator it=m_imgList.find(type); ImgList::iterator it=m_imgList.find(type);
bool preExisting = false;
if ( it != m_imgList.end() ) if ( it != m_imgList.end() )
{
m_imgList.erase(it); m_imgList.erase(it);
preExisting = true;
}
m_imgList[type] = bmp; m_imgList[type] = bmp;
if ( preExisting )
{
m_imageAreaWidth = 0;
m_imageAreaHeight = 0;
for ( ImgList::iterator it = m_imgList.begin() ; it != m_imgList.end() ; ++it )
{
wxBitmap bmp = it->second;
if ( bmp.GetWidth() > m_imageAreaWidth )
{
m_imageAreaWidth = bmp.GetWidth();
}
if ( bmp.GetHeight() > m_imageAreaHeight )
{
m_imageAreaHeight = bmp.GetHeight();
}
}
}
else
{
m_imageAreaWidth = wxMax(m_imageAreaWidth, bmp.GetWidth());
m_imageAreaHeight = wxMax(m_imageAreaHeight, bmp.GetHeight());
}
} }
void wxSTCListBoxVisualData::RegisterImage(int type, const char *xpm_data) void wxSTCListBoxVisualData::RegisterImage(int type, const char *xpm_data)
@@ -2451,6 +2486,8 @@ void wxSTCListBoxVisualData::RegisterRGBAImage(int type, int width, int height,
void wxSTCListBoxVisualData::ClearRegisteredImages() void wxSTCListBoxVisualData::ClearRegisteredImages()
{ {
m_imgList.clear(); m_imgList.clear();
m_imageAreaWidth = 0;
m_imageAreaHeight = 0;
} }
const wxBitmap* wxSTCListBoxVisualData::GetImage(int i) const const wxBitmap* wxSTCListBoxVisualData::GetImage(int i) const
@@ -2463,6 +2500,16 @@ const wxBitmap* wxSTCListBoxVisualData::GetImage(int i) const
return NULL; return NULL;
} }
int wxSTCListBoxVisualData::GetImageAreaWidth() const
{
return m_imageAreaWidth;
}
int wxSTCListBoxVisualData::GetImageAreaHeight() const
{
return m_imageAreaHeight;
}
void wxSTCListBoxVisualData::ComputeColours() void wxSTCListBoxVisualData::ComputeColours()
{ {
// wxSYS_COLOUR_BTNSHADOW seems to be the closest match with most themes. // wxSYS_COLOUR_BTNSHADOW seems to be the closest match with most themes.
@@ -2640,7 +2687,6 @@ protected:
// Helpers // Helpers
void AppendHelper(const wxString& text, int type); void AppendHelper(const wxString& text, int type);
void SelectHelper(int i); void SelectHelper(int i);
void AccountForBitmap(int type, bool recalculateItemHeight);
void RecalculateItemHeight(); void RecalculateItemHeight();
int TextBoxFromClientEdge() const; int TextBoxFromClientEdge() const;
@@ -2658,8 +2704,6 @@ protected:
virtual void OnDrawBackground(wxDC&, const wxRect&,size_t) const wxOVERRIDE; virtual void OnDrawBackground(wxDC&, const wxRect&,size_t) const wxOVERRIDE;
private: private:
WX_DECLARE_HASH_SET(int, wxIntegerHash, wxIntegerEqual, SetOfInts);
wxSTCListBoxVisualData* m_visualData; wxSTCListBoxVisualData* m_visualData;
wxVector<wxString> m_labels; wxVector<wxString> m_labels;
wxVector<int> m_imageNos; wxVector<int> m_imageNos;
@@ -2675,8 +2719,6 @@ private:
int m_textHeight; int m_textHeight;
int m_itemHeight; int m_itemHeight;
int m_textTopGap; int m_textTopGap;
int m_imageAreaWidth;
int m_imageAreaHeight;
// These drawing parameters are set internally and can be changed if needed // These drawing parameters are set internally and can be changed if needed
// to better match the appearance of a list box on a specific platform. // to better match the appearance of a list box on a specific platform.
@@ -2690,7 +2732,7 @@ wxSTCListBox::wxSTCListBox(wxWindow* parent, wxSTCListBoxVisualData* v, int ht)
m_visualData(v), m_maxStrWidth(0), m_currentRow(wxNOT_FOUND), m_visualData(v), m_maxStrWidth(0), m_currentRow(wxNOT_FOUND),
m_doubleClickAction(NULL), m_doubleClickActionData(NULL), m_doubleClickAction(NULL), m_doubleClickActionData(NULL),
m_aveCharWidth(8), m_textHeight(ht), m_itemHeight(ht), m_aveCharWidth(8), m_textHeight(ht), m_itemHeight(ht),
m_textTopGap(0), m_imageAreaWidth(0), m_imageAreaHeight(0) m_textTopGap(0)
{ {
wxVListBox::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVListBox::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxBORDER_NONE, "AutoCompListBox"); wxBORDER_NONE, "AutoCompListBox");
@@ -2796,8 +2838,6 @@ int wxSTCListBox::CaretFromEdge() const
void wxSTCListBox::Clear() void wxSTCListBox::Clear()
{ {
m_imageAreaWidth = 0;
m_imageAreaHeight = 0;
m_labels.clear(); m_labels.clear();
m_imageNos.clear(); m_imageNos.clear();
} }
@@ -2805,7 +2845,7 @@ void wxSTCListBox::Clear()
void wxSTCListBox::Append(char *s, int type) void wxSTCListBox::Append(char *s, int type)
{ {
AppendHelper(stc2wx(s), type); AppendHelper(stc2wx(s), type);
AccountForBitmap(type, true); RecalculateItemHeight();
} }
int wxSTCListBox::Length() const int wxSTCListBox::Length() const
@@ -2835,7 +2875,6 @@ void wxSTCListBox::SetList(const char* list, char separator, char typesep)
{ {
wxWindowUpdateLocker noUpdates(this); wxWindowUpdateLocker noUpdates(this);
Clear(); Clear();
SetOfInts bitmapNos;
wxStringTokenizer tkzr(stc2wx(list), (wxChar)separator); wxStringTokenizer tkzr(stc2wx(list), (wxChar)separator);
while ( tkzr.HasMoreTokens() ) { while ( tkzr.HasMoreTokens() ) {
wxString token = tkzr.GetNextToken(); wxString token = tkzr.GetNextToken();
@@ -2846,14 +2885,9 @@ void wxSTCListBox::SetList(const char* list, char separator, char typesep)
token.Truncate(pos); token.Truncate(pos);
} }
AppendHelper(token, (int)type); AppendHelper(token, (int)type);
bitmapNos.insert(static_cast<int>(type));
} }
for ( SetOfInts::iterator it=bitmapNos.begin(); it!=bitmapNos.end(); ++it ) RecalculateItemHeight();
AccountForBitmap(*it, false);
if ( m_imageAreaHeight > 0 )
RecalculateItemHeight();
} }
void wxSTCListBox::AppendHelper(const wxString& text, int type) void wxSTCListBox::AppendHelper(const wxString& text, int type)
@@ -2895,34 +2929,17 @@ void wxSTCListBox::SelectHelper(int i)
} }
} }
void wxSTCListBox::AccountForBitmap(int type, bool recalculateItemHeight)
{
const int oldHeight = m_imageAreaHeight;
const wxBitmap* bmp = m_visualData->GetImage(type);
if ( bmp )
{
if ( bmp->GetWidth() > m_imageAreaWidth )
m_imageAreaWidth = bmp->GetWidth();
if ( bmp->GetHeight() > m_imageAreaHeight )
m_imageAreaHeight = bmp->GetHeight();
}
if ( recalculateItemHeight && m_imageAreaHeight != oldHeight )
RecalculateItemHeight();
}
void wxSTCListBox::RecalculateItemHeight() void wxSTCListBox::RecalculateItemHeight()
{ {
m_itemHeight = wxMax(m_textHeight + 2 * m_textExtraVerticalPadding, m_itemHeight = wxMax(m_textHeight + 2 * m_textExtraVerticalPadding,
m_imageAreaHeight + 2 * m_imagePadding); m_visualData->GetImageAreaHeight() + 2 * m_imagePadding);
m_textTopGap = (m_itemHeight - m_textHeight)/2; m_textTopGap = (m_itemHeight - m_textHeight)/2;
} }
int wxSTCListBox::TextBoxFromClientEdge() const int wxSTCListBox::TextBoxFromClientEdge() const
{ {
return (m_imageAreaWidth == 0 ? 0 : m_imageAreaWidth + 2 * m_imagePadding); const int width = m_visualData->GetImageAreaWidth();
return (width == 0 ? 0 : width + 2 * m_imagePadding);
} }
void wxSTCListBox::OnSelection(wxCommandEvent& event) void wxSTCListBox::OnSelection(wxCommandEvent& event)
@@ -2993,7 +3010,7 @@ wxCoord wxSTCListBox::OnMeasureItem(size_t WXUNUSED(n)) const
// //
// +++++++++++++++++++++++++ =====ITEM TEXT================ // +++++++++++++++++++++++++ =====ITEM TEXT================
// | | | | // | | | |
// | m_imageAreaWidth | | // | imageAreaWidth | |
// | | | // | | |
// m_imagePadding | m_textBoxToTextGap // m_imagePadding | m_textBoxToTextGap
// | // |
@@ -3002,8 +3019,8 @@ wxCoord wxSTCListBox::OnMeasureItem(size_t WXUNUSED(n)) const
// //
// m_imagePadding : Used to give a little extra space between the // m_imagePadding : Used to give a little extra space between the
// client edge and an item's bitmap. // client edge and an item's bitmap.
// m_imageAreaWidth : Computed as the width of the largest registered // imageAreaWidth : Computed as the width of the largest registered
// bitmap. // bitmap (part of wxSTCListBoxVisualData).
// m_textBoxToTextGap : Used so that item text does not begin immediately // m_textBoxToTextGap : Used so that item text does not begin immediately
// at the edge of the highlight box. // at the edge of the highlight box.
// //
@@ -3042,8 +3059,9 @@ void wxSTCListBox::OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const
const wxBitmap* b = m_visualData->GetImage(imageNo); const wxBitmap* b = m_visualData->GetImage(imageNo);
if ( b ) if ( b )
{ {
const int width = m_visualData->GetImageAreaWidth();
topGap = (m_itemHeight - b->GetHeight())/2; topGap = (m_itemHeight - b->GetHeight())/2;
leftGap = m_imagePadding + (m_imageAreaWidth - b->GetWidth())/2; leftGap = m_imagePadding + (width - b->GetWidth())/2;
dc.DrawBitmap(*b, rect.GetLeft()+leftGap, rect.GetTop()+topGap, true); dc.DrawBitmap(*b, rect.GetLeft()+leftGap, rect.GetTop()+topGap, true);
} }
} }