mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-11 17:28:29 +12:00
317 lines
No EOL
8.3 KiB
C++
317 lines
No EOL
8.3 KiB
C++
#include "gui/wxgui.h"
|
|
#include "TextList.h"
|
|
#include <wx/setup.h>
|
|
#include <wx/tooltip.h>
|
|
|
|
TextList::~TextList()
|
|
{
|
|
m_tooltip_timer->Stop();
|
|
|
|
this->Unbind(wxEVT_MOTION, &TextList::OnMouseMoveEvent, this);
|
|
this->Unbind(wxEVT_KEY_DOWN, &TextList::OnKeyDownEvent, this);
|
|
this->Unbind(wxEVT_KEY_UP, &TextList::OnKeyUpEvent, this);
|
|
this->Unbind(wxEVT_PAINT, &TextList::OnPaintEvent, this);
|
|
this->Unbind(wxEVT_LEFT_DOWN, &TextList::OnMouseDownEvent, this);
|
|
this->Unbind(wxEVT_LEFT_UP, &TextList::OnMouseUpEvent, this);
|
|
this->Unbind(wxEVT_LEFT_DCLICK, &TextList::OnMouseDClickEvent, this);
|
|
this->Unbind(wxEVT_CONTEXT_MENU, &TextList::OnContextMenu, this);
|
|
this->Unbind(wxEVT_ERASE_BACKGROUND, &TextList::OnEraseBackground, this);
|
|
}
|
|
|
|
TextList::TextList(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
|
|
: wxControl(parent, id, pos, size, style), wxScrollHelper(this)
|
|
{
|
|
m_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
|
wxWindowBase::SetBackgroundStyle(wxBG_STYLE_PAINT);
|
|
|
|
wxClientDC dc(this);
|
|
m_line_height = dc.GetCharHeight();
|
|
m_char_width = dc.GetCharWidth();
|
|
|
|
m_yScrollPixelsPerLine = m_line_height;
|
|
|
|
this->ShowScrollbars(wxSHOW_SB_DEFAULT, wxSHOW_SB_DEFAULT);
|
|
|
|
m_tooltip = new wxToolTip(wxEmptyString);
|
|
|
|
this->Bind(wxEVT_MOTION, &TextList::OnMouseMoveEvent, this);
|
|
this->Bind(wxEVT_KEY_DOWN, &TextList::OnKeyDownEvent, this);
|
|
this->Bind(wxEVT_KEY_UP, &TextList::OnKeyUpEvent, this);
|
|
this->Bind(wxEVT_PAINT, &TextList::OnPaintEvent, this);
|
|
this->Bind(wxEVT_LEFT_DOWN, &TextList::OnMouseDownEvent, this);
|
|
this->Bind(wxEVT_LEFT_UP, &TextList::OnMouseUpEvent, this);
|
|
this->Bind(wxEVT_LEFT_DCLICK, &TextList::OnMouseDClickEvent, this);
|
|
this->Bind(wxEVT_CONTEXT_MENU, &TextList::OnContextMenu, this);
|
|
this->Bind(wxEVT_ERASE_BACKGROUND, &TextList::OnEraseBackground, this);
|
|
|
|
m_tooltip_window = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNO_BORDER);
|
|
m_tooltip_window->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK));
|
|
m_tooltip_window->Hide();
|
|
|
|
m_tooltip_timer = new wxTimer(this);
|
|
this->Bind(wxEVT_TIMER, &TextList::OnTooltipTimer, this);
|
|
}
|
|
|
|
void TextList::RefreshControl(const wxRect* update_region)
|
|
{
|
|
if(update_region)
|
|
Refresh(true, update_region);
|
|
else
|
|
{
|
|
wxRect region = GetClientRect();
|
|
update_region = ®ion;
|
|
Refresh(true, update_region);
|
|
}
|
|
}
|
|
|
|
void TextList::RefreshLine(uint32 line)
|
|
{
|
|
wxRect update_region = GetClientRect();
|
|
update_region.y = (sint32)line * m_line_height;
|
|
update_region.height = m_line_height;
|
|
CalcScrolledPosition(0, update_region.y, nullptr, &update_region.y);
|
|
// debug_printf("update: <%x, %x>\n", update_region.y, update_region.height);
|
|
Refresh(true, &update_region);
|
|
}
|
|
|
|
wxSize TextList::DoGetVirtualSize() const
|
|
{
|
|
return {wxDefaultCoord, (int)(m_element_count + 1) * m_line_height};
|
|
}
|
|
|
|
void TextList::DoSetSize(int x, int y, int width, int height, int sizeFlags)
|
|
{
|
|
wxControl::DoSetSize(x, y, width, height, sizeFlags);
|
|
|
|
m_elements_visible = (height + m_line_height - 1) / m_line_height;
|
|
Refresh();
|
|
}
|
|
|
|
void TextList::SetScrollPos(int orient, int pos, bool refresh)
|
|
{
|
|
wxControl::SetScrollPos(orient, pos, refresh);
|
|
}
|
|
|
|
void TextList::DrawLineBackground(wxDC& dc, uint32 line, const wxColour& colour, uint32 lines) const
|
|
{
|
|
wxRect rect;
|
|
rect.x = GetPosition().x;
|
|
rect.y = line * m_line_height;
|
|
rect.width = GetSize().x;
|
|
rect.height = m_line_height * lines;
|
|
|
|
dc.SetBrush(colour);
|
|
dc.DrawRectangle(rect);
|
|
}
|
|
|
|
void TextList::DrawLineBackground(wxDC& dc, const wxPoint& position, const wxColour& colour, uint32 lines) const
|
|
{
|
|
wxRect rect;
|
|
rect.x = position.x;
|
|
rect.y = position.y;
|
|
rect.width = this->GetSize().x;
|
|
rect.height = m_line_height * lines;
|
|
|
|
dc.SetBrush(colour);
|
|
dc.DrawRectangle(rect);
|
|
}
|
|
|
|
bool TextList::SetElementCount(size_t element_count)
|
|
{
|
|
if (m_element_count == element_count)
|
|
return false;
|
|
|
|
if (element_count > 0x7FFFFFFF)
|
|
element_count = 0x7FFFFFFF;
|
|
|
|
m_element_count = element_count;
|
|
this->AdjustScrollbars();
|
|
return true;
|
|
}
|
|
|
|
uint32 TextList::GetElementCount() const
|
|
{
|
|
return m_element_count;
|
|
}
|
|
|
|
bool TextList::IsKeyDown(sint32 keycode)
|
|
{
|
|
return m_key_states[keycode];
|
|
}
|
|
|
|
void TextList::WriteText(wxDC& dc, const wxString& text, wxPoint& position) const
|
|
{
|
|
dc.ResetBoundingBox();
|
|
dc.DrawText(text, position);
|
|
position.x += dc.MaxX() - dc.MinX();
|
|
}
|
|
|
|
void TextList::WriteText(wxDC& dc, const wxString& text, wxPoint& position, const wxColour& color) const
|
|
{
|
|
dc.SetTextForeground(color);
|
|
WriteText(dc, text, position);
|
|
}
|
|
|
|
void TextList::NextLine(wxPoint& position, const wxPoint* start_position) const
|
|
{
|
|
position.y += m_line_height;
|
|
|
|
if (start_position)
|
|
position.x = start_position->x;
|
|
}
|
|
|
|
void TextList::OnMouseDown() {}
|
|
void TextList::OnMouseUp() {}
|
|
|
|
bool TextList::OnShowTooltip(const wxPoint& position, uint32 line)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void TextList::OnMouseMoveEvent(wxMouseEvent& event)
|
|
{
|
|
m_tooltip_timer->Stop();
|
|
m_tooltip_timer->StartOnce(250);
|
|
|
|
wxPoint position = event.GetPosition();
|
|
CalcUnscrolledPosition(position.x, position.y, &position.x, &position.y);
|
|
|
|
m_mouse_position = position;
|
|
|
|
if(m_mouse_down)
|
|
m_selection.SetBottomRight(position);
|
|
|
|
const sint32 line = position.y / m_line_height;
|
|
OnMouseMove(position, line);
|
|
}
|
|
|
|
void TextList::OnKeyDownEvent(wxKeyEvent& event)
|
|
{
|
|
const auto key_code = event.GetKeyCode();
|
|
const auto it = m_key_states.find(key_code);
|
|
if(it == m_key_states.end() || !it->second)
|
|
{
|
|
m_key_states[key_code] = true;
|
|
OnKeyPressed(key_code, event.GetPosition());
|
|
}
|
|
|
|
event.Skip();
|
|
}
|
|
|
|
void TextList::OnKeyUpEvent(wxKeyEvent& event)
|
|
{
|
|
m_key_states[event.GetKeyCode()] = false;
|
|
}
|
|
|
|
void TextList::OnMouseDownEvent(wxMouseEvent& event)
|
|
{
|
|
m_mouse_down = true;
|
|
|
|
wxPoint position = event.GetPosition();
|
|
CalcUnscrolledPosition(position.x, position.y, &position.x, &position.y);
|
|
m_selection.SetPosition(position);
|
|
m_selection.SetBottomRight(position);
|
|
|
|
OnMouseDown();
|
|
|
|
event.Skip();
|
|
}
|
|
|
|
void TextList::OnMouseUpEvent(wxMouseEvent& event)
|
|
{
|
|
m_mouse_down = false;
|
|
OnMouseUp();
|
|
|
|
event.Skip();
|
|
}
|
|
|
|
void TextList::OnMouseDClickEvent(wxMouseEvent& event)
|
|
{
|
|
wxPoint position = event.GetPosition();
|
|
CalcUnscrolledPosition(position.x, position.y, &position.x, &position.y);
|
|
m_selection.SetPosition(position);
|
|
m_selection.SetBottomRight(position);
|
|
|
|
const uint32 line = position.y / m_line_height;
|
|
OnMouseDClick(position, line);
|
|
}
|
|
|
|
void TextList::OnContextMenu(wxContextMenuEvent& event)
|
|
{
|
|
wxPoint position = event.GetPosition();
|
|
if (position == wxDefaultPosition)
|
|
return;
|
|
|
|
wxPoint clientPosition = ScreenToClient(position);
|
|
|
|
CalcUnscrolledPosition(clientPosition.x, clientPosition.y, &clientPosition.x, &clientPosition.y);
|
|
m_selection.SetPosition(clientPosition);
|
|
m_selection.SetBottomRight(clientPosition);
|
|
|
|
const uint32 line = clientPosition.y / m_line_height;
|
|
OnContextMenu(clientPosition, line);
|
|
}
|
|
|
|
|
|
void TextList::OnTooltipTimer(wxTimerEvent& event)
|
|
{
|
|
m_tooltip_window->Hide();
|
|
|
|
const auto cursor_position = wxGetMousePosition();
|
|
|
|
const auto position = GetScreenPosition();
|
|
if (cursor_position.x < position.x || cursor_position.y < position.y)
|
|
return;
|
|
|
|
const auto size = GetSize();
|
|
if (position.x + size.x < cursor_position.x || position.y + size.y < cursor_position.y)
|
|
return;
|
|
|
|
const sint32 line = position.y / m_line_height;
|
|
if(OnShowTooltip(m_mouse_position, line))
|
|
{
|
|
m_tooltip_window->SetPosition(wxPoint(m_mouse_position.x + 15, m_mouse_position.y + 15));
|
|
m_tooltip_window->SendSizeEvent();
|
|
m_tooltip_window->Show();
|
|
}
|
|
}
|
|
|
|
void TextList::OnPaintEvent(wxPaintEvent& event)
|
|
{
|
|
wxBufferedPaintDC dc(m_targetWindow, wxBUFFER_VIRTUAL_AREA);
|
|
dc.SetFont(m_font);
|
|
|
|
// get window position
|
|
auto position = GetPosition();
|
|
|
|
// get current real position
|
|
wxRect rect_update = GetUpdateRegion().GetBox();
|
|
const auto count = (uint32)std::ceil((float)rect_update.GetHeight() / m_line_height);
|
|
|
|
position.y = (rect_update.y / m_line_height) * m_line_height;
|
|
|
|
// paint background
|
|
const wxColour window_colour = COLOR_WHITE;
|
|
dc.SetBrush(window_colour);
|
|
dc.SetPen(window_colour);
|
|
dc.DrawRectangle(rect_update);
|
|
|
|
//// paint selection
|
|
//if (!m_selected_text.eof())
|
|
//{
|
|
// dc.SetBrush(*wxBLUE_BRUSH);
|
|
// dc.SetPen(*wxBLUE_PEN);
|
|
// dc.DrawRectangle(m_selection);
|
|
//}
|
|
|
|
sint32 start;
|
|
CalcUnscrolledPosition(rect_update.x, rect_update.y, nullptr, &start);
|
|
|
|
start /= m_line_height;
|
|
m_scrolled_to_end = (start + count) >= m_element_count;
|
|
|
|
OnDraw(dc, start, count, position);
|
|
|
|
|
|
this->Update();
|
|
} |