Add AutoCompUseListCtrl method to STC

The AutoCompUseListCtrl method can be used to make an autocompletion
list look like it's being shown with a wxListCtrl instead of a
wxListBox. When this style is used, the list will have hot tracking.
On MSW, the colours will also be slightly different.
This commit is contained in:
New Pagodi
2019-03-18 22:55:48 -05:00
parent 3900cfec27
commit 267540d233
7 changed files with 248 additions and 27 deletions

View File

@@ -37,6 +37,7 @@
#include "wx/sizer.h"
#include "wx/renderer.h"
#include "wx/hashset.h"
#include "wx/dcclient.h"
#ifdef wxHAS_RAW_BITMAP
#include "wx/rawbmp.h"
@@ -2328,6 +2329,12 @@ public:
const wxColour& GetHighlightBgColour() const;
const wxColour& GetHighlightTextColour() const;
// ListCtrl Style
void UseListCtrlStyle(bool, const wxColour&, const wxColour&);
bool HasListCtrlAppearance() const;
const wxColour& GetCurrentBgColour() const;
const wxColour& GetCurrentTextColour() const;
private:
WX_DECLARE_HASH_MAP(int, wxBitmap, wxIntegerHash, wxIntegerEqual, ImgList);
@@ -2343,12 +2350,21 @@ private:
bool m_textColourIsSet;
bool m_highlightBgColourIsSet;
bool m_highlightTextColourIsSet;
bool m_hasListCtrlAppearance;
wxColour m_currentBgColour;
wxColour m_currentTextColour;
bool m_currentBgColourIsSet;
bool m_currentTextColourIsSet;
};
wxSTCListBoxVisualData::wxSTCListBoxVisualData(int d):m_desiredVisibleRows(d),
m_bgColourIsSet(false), m_textColourIsSet(false),
m_highlightBgColourIsSet(false),
m_highlightTextColourIsSet(false)
m_highlightTextColourIsSet(false),
m_hasListCtrlAppearance(false),
m_currentBgColourIsSet(false),
m_currentTextColourIsSet(false)
{
ComputeColours();
}
@@ -2434,18 +2450,46 @@ void wxSTCListBoxVisualData::ComputeColours()
if ( !m_textColourIsSet )
m_textColour = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOXTEXT);
#ifdef __WXOSX_COCOA__
if ( !m_highlightBgColourIsSet )
m_highlightBgColour = GetListHighlightColour();
#else
if ( !m_highlightBgColourIsSet )
m_highlightBgColour =
wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
#endif
if ( m_hasListCtrlAppearance )
{
// If m_highlightBgColour and/or m_currentBgColour are not
// explicitly set, set them to wxNullColour to indicate that they
// should be drawn with wxRendererNative.
if ( !m_highlightBgColourIsSet )
m_highlightBgColour = wxNullColour;
if ( !m_highlightTextColourIsSet )
m_highlightTextColour =
wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT);
if ( !m_currentBgColourIsSet )
m_currentBgColour = wxNullColour;
#ifdef __WXMSW__
if ( !m_highlightTextColourIsSet )
m_highlightTextColour =
wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOXTEXT);
#else
if ( !m_highlightTextColourIsSet )
m_highlightTextColour = wxSystemSettings::GetColour(
wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT);
#endif
if ( !m_currentTextColour.IsOk() )
m_currentTextColour = wxSystemSettings::GetColour(
wxSYS_COLOUR_LISTBOXTEXT);
}
else
{
#ifdef __WXOSX_COCOA__
if ( !m_highlightBgColourIsSet )
m_highlightBgColour = GetListHighlightColour();
#else
if ( !m_highlightBgColourIsSet )
m_highlightBgColour =
wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
#endif
if ( !m_highlightTextColourIsSet )
m_highlightTextColour =
wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT);
}
}
void SetColourHelper(bool& isSet, wxColour& itemCol, const wxColour& newColour)
@@ -2491,10 +2535,34 @@ const wxColour& wxSTCListBoxVisualData::GetHighlightTextColour() const
return m_highlightTextColour;
}
void wxSTCListBoxVisualData::UseListCtrlStyle(bool useListCtrlStyle,
const wxColour& curBg,
const wxColour& curText)
{
m_hasListCtrlAppearance = useListCtrlStyle;
SetColourHelper(m_currentBgColourIsSet, m_currentBgColour, curBg);
SetColourHelper(m_currentTextColourIsSet, m_currentTextColour, curText);
ComputeColours();
}
bool wxSTCListBoxVisualData::HasListCtrlAppearance() const
{
return m_hasListCtrlAppearance;
}
const wxColour& wxSTCListBoxVisualData::GetCurrentBgColour() const
{
return m_currentBgColour;
}
const wxColour& wxSTCListBoxVisualData::GetCurrentTextColour() const
{
return m_currentTextColour;
}
// The class is intended to look like a standard listbox (with an optional
// icon). However, it needs to look like it has focus even when it doesn't.
class wxSTCListBox : public wxVListBox
class wxSTCListBox : public wxSystemThemedControl<wxVListBox>
{
public:
wxSTCListBox(wxWindow*, wxSTCListBoxVisualData*, int);
@@ -2530,6 +2598,8 @@ protected:
// Event handlers
void OnDClick(wxCommandEvent&);
void OnSysColourChanged(wxSysColourChangedEvent& event);
void OnMouseMotion(wxMouseEvent& event);
void OnMouseLeaveWindow(wxMouseEvent& event);
// wxVListBox overrides
virtual wxCoord OnMeasureItem(size_t) const wxOVERRIDE;
@@ -2543,6 +2613,7 @@ private:
wxVector<wxString> m_labels;
wxVector<int> m_imageNos;
size_t m_maxStrWidth;
int m_currentRow;
CallBackAction m_doubleClickAction;
void* m_doubleClickActionData;
@@ -2564,7 +2635,8 @@ private:
};
wxSTCListBox::wxSTCListBox(wxWindow* parent, wxSTCListBoxVisualData* v, int ht)
:wxVListBox(), m_visualData(v), m_maxStrWidth(0),
:wxSystemThemedControl<wxVListBox>(),
m_visualData(v), m_maxStrWidth(0), m_currentRow(wxNOT_FOUND),
m_doubleClickAction(NULL), m_doubleClickActionData(NULL),
m_aveCharWidth(8), m_textHeight(ht), m_itemHeight(ht),
m_textTopGap(0), m_imageAreaWidth(0), m_imageAreaHeight(0)
@@ -2580,6 +2652,20 @@ wxSTCListBox::wxSTCListBox(wxWindow* parent, wxSTCListBoxVisualData* v, int ht)
Bind(wxEVT_LISTBOX_DCLICK, &wxSTCListBox::OnDClick, this);
Bind(wxEVT_SYS_COLOUR_CHANGED, &wxSTCListBox::OnSysColourChanged, this);
if ( m_visualData->HasListCtrlAppearance() )
{
EnableSystemTheme();
Bind(wxEVT_MOTION, &wxSTCListBox::OnMouseMotion, this);
Bind(wxEVT_LEAVE_WINDOW, &wxSTCListBox::OnMouseLeaveWindow, this);
#ifdef __WXMSW__
// On MSW when using wxRendererNative to draw items in list control
// style, the colours used seem to be based on the parent's
// background colour. So set the popup's background.
parent->SetOwnBackgroundColour(m_visualData->GetBgColour());
#endif
}
}
wxSTCListBox::~wxSTCListBox()
@@ -2771,8 +2857,37 @@ void wxSTCListBox::OnDClick(wxCommandEvent& WXUNUSED(event))
void wxSTCListBox::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event))
{
m_visualData->ComputeColours();
GetParent()->SetOwnBackgroundColour(m_visualData->GetBgColour());
SetBackgroundColour(m_visualData->GetBgColour());
Refresh();
GetParent()->Refresh();
}
void wxSTCListBox::OnMouseLeaveWindow(wxMouseEvent& event)
{
const int old = m_currentRow;
m_currentRow = wxNOT_FOUND;
if ( old != wxNOT_FOUND )
RefreshRow(old);
event.Skip();
}
void wxSTCListBox::OnMouseMotion(wxMouseEvent& event)
{
const int old = m_currentRow;
m_currentRow = VirtualHitTest(event.GetY());
if ( old != m_currentRow )
{
if( m_currentRow != wxNOT_FOUND )
RefreshRow(m_currentRow);
if( old != wxNOT_FOUND )
RefreshRow(old);
}
event.Skip();
}
wxCoord wxSTCListBox::OnMeasureItem(size_t WXUNUSED(n)) const
@@ -2821,6 +2936,8 @@ void wxSTCListBox::OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const
if ( IsSelected(n) )
tcc.Set(m_visualData->GetHighlightTextColour());
else if ( static_cast<int>(n) == m_currentRow )
tcc.Set(m_visualData->GetCurrentTextColour());
else
tcc.Set(m_visualData->GetTextColour());
@@ -2845,19 +2962,50 @@ void wxSTCListBox::OnDrawBackground(wxDC &dc, const wxRect &rect,size_t n) const
const wxColour& highlightBgColour =m_visualData->GetHighlightBgColour();
#ifdef __WXMSW__
// On windows the selection rectangle in Scintilla's
// autocompletion list only covers the text and not the icon.
const int textBoxFromClientEdge = TextBoxFromClientEdge();
selectionRect.SetLeft(rect.GetLeft() + textBoxFromClientEdge);
selectionRect.SetWidth(rect.GetWidth() - textBoxFromClientEdge);
if ( !m_visualData->HasListCtrlAppearance() )
{
// On windows the selection rectangle in Scintilla's
// autocompletion list only covers the text and not the icon.
const int textBoxFromClientEdge = TextBoxFromClientEdge();
selectionRect.SetLeft(rect.GetLeft() + textBoxFromClientEdge);
selectionRect.SetWidth(rect.GetWidth() - textBoxFromClientEdge);
}
#endif // __WXMSW__
wxDCBrushChanger bc(dc, highlightBgColour);
wxDCPenChanger pc(dc, highlightBgColour);
dc.DrawRectangle(selectionRect);
if ( highlightBgColour.IsOk() )
{
wxDCBrushChanger bc(dc, highlightBgColour);
wxDCPenChanger pc(dc, highlightBgColour);
dc.DrawRectangle(selectionRect);
}
else
{
wxRendererNative::GetDefault().DrawItemSelectionRect(
const_cast<wxSTCListBox*>(this), dc, selectionRect,
wxCONTROL_SELECTED | wxCONTROL_FOCUSED);
}
wxRendererNative::GetDefault().DrawFocusRect(
const_cast<wxSTCListBox*>(this), dc, selectionRect);
if ( !m_visualData->HasListCtrlAppearance() )
wxRendererNative::GetDefault().DrawFocusRect(
const_cast<wxSTCListBox*>(this), dc, selectionRect);
}
else if ( static_cast<int>(n) == m_currentRow )
{
const wxColour& currentBgColour = m_visualData->GetCurrentBgColour();
if ( currentBgColour.IsOk() )
{
wxDCBrushChanger bc(dc, currentBgColour);
wxDCPenChanger pc(dc, currentBgColour);
dc.DrawRectangle(rect);
}
else
{
wxRendererNative::GetDefault().DrawItemSelectionRect(
const_cast<wxSTCListBox*>(this), dc, rect,
wxCONTROL_CURRENT | wxCONTROL_FOCUSED);
}
}
}
@@ -2867,6 +3015,12 @@ class wxSTCListBoxWin : public wxSTCPopupWindow
{
public:
wxSTCListBoxWin(wxWindow*, wxSTCListBox**, wxSTCListBoxVisualData*, int);
protected:
void OnPaint(wxPaintEvent&);
private:
wxSTCListBoxVisualData* m_visualData;
};
wxSTCListBoxWin::wxSTCListBoxWin(wxWindow* parent, wxSTCListBox** lb,
@@ -2885,9 +3039,22 @@ wxSTCListBoxWin::wxSTCListBoxWin(wxWindow* parent, wxSTCListBox** lb,
wxBoxSizer* bSizer = new wxBoxSizer(wxVERTICAL);
bSizer->Add(*lb, 1, wxEXPAND|wxALL, borderThickness);
SetSizer(bSizer);
(*lb)->SetContainerBorderSize(borderThickness);
SetOwnBackgroundColour(v->GetBorderColour());
// When drawing highlighting in listctrl style with wxRendererNative on MSW,
// the colours used seem to be based on the background of the parent window.
// So manually paint this window to give it the border colour instead of
// setting the background colour.
m_visualData = v;
Bind(wxEVT_PAINT, &wxSTCListBoxWin::OnPaint, this);
SetBackgroundStyle(wxBG_STYLE_PAINT);
}
void wxSTCListBoxWin::OnPaint(wxPaintEvent& WXUNUSED(evt))
{
wxPaintDC dc(this);
dc.SetBackground(m_visualData->GetBorderColour());
dc.Clear();
}
@@ -3014,6 +3181,12 @@ void ListBoxImpl::SetColours(const wxColour& background, const wxColour& text,
m_visualData->SetColours(background, text, hiliBg, hiliText);
}
void ListBoxImpl::UseListCtrlStyle(bool useListCtrl, const wxColour& currentBg,
const wxColour& currentText)
{
m_visualData->UseListCtrlStyle(useListCtrl, currentBg, currentText);
}
ListBox::ListBox() {
}

View File

@@ -51,6 +51,7 @@ public:
virtual void SetList(const char* list, char separator, char typesep) wxOVERRIDE;
void SetColours(const wxColour&, const wxColour&,
const wxColour&, const wxColour&);
void UseListCtrlStyle(bool, const wxColour&, const wxColour&);
};

View File

@@ -1346,6 +1346,15 @@ void ScintillaWX::SetListBoxColours(const wxColour& background,
highlight, highlightText);
}
void ScintillaWX::UseListCtrlStyleForLists(bool useListCtrl,
const wxColour& currentBgColour,
const wxColour& currentTextColour)
{
static_cast<ListBoxImpl*>(ac.lb)->UseListCtrlStyle(useListCtrl,
currentBgColour,
currentTextColour);
}
sptr_t ScintillaWX::DirectFunction(
ScintillaWX* swx, unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
return swx->WndProc(iMessage, wParam, lParam);

View File

@@ -203,6 +203,7 @@ public:
void DoRegisterImage(int type, const wxBitmap& bmp);
void SetListBoxColours(const wxColour&, const wxColour&,
const wxColour&, const wxColour&);
void UseListCtrlStyleForLists(bool, const wxColour&, const wxColour&);
private:
bool capturedMouse;

View File

@@ -581,6 +581,14 @@ void wxStyledTextCtrl::AutoCompSetColours(const wxColour& background,
m_swx->SetListBoxColours(background, text, highlight, highlightText);
}
void wxStyledTextCtrl::AutoCompUseListCtrl(bool useListCtrl,
const wxColour& currentBgColour,
const wxColour& currentTextColour)
{
m_swx->UseListCtrlStyleForLists(useListCtrl, currentBgColour,
currentTextColour);
}

View File

@@ -309,6 +309,11 @@ public:
const wxColour& highlight,
const wxColour& highlightText);
// Use a wxListCtrl to display autocompletion lists.
void AutoCompUseListCtrl(bool useListCtrl = true,
const wxColour& currentBgColour = wxNullColour,
const wxColour& currentTextColour = wxNullColour);
// The following methods are nearly equivalent to their similarly named

View File

@@ -387,6 +387,30 @@ public:
const wxColour& highlight,
const wxColour& highlightText);
/**
Use a wxListCtrl to display autocompletion and user lists.
By default lists will be displayed in a wxListBox. Use this method to
display them in a wxListCtrl instead. The primary difference is that
wxListCtrl has hot tracking to highlight the item under the mouse cursor.
@param useListCtrl
Set this to true to use a wxListCtrl and to false to use a
wxListBox.
@param currentBgColour
The colour used to highlight the item under the mouse cursor.
@param currentTextColour
The colour used for the text of the item under the mouse cursor.
@remarks
To reset one or more of the colours to its default,
call this method with wxNullColour for the colour or colours
to be reset.
@since 3.1.3
*/
void AutoCompUseListCtrl(bool useListCtrl = true,
const wxColour& currentBgColour = wxNullColour,
const wxColour& currentTextColour = wxNullColour);
//@}