From 9dc12ae74668bd47cd0f912e8a85c4232763897d Mon Sep 17 00:00:00 2001 From: Ilari Liusvaara Date: Sat, 11 May 2013 02:19:49 +0300 Subject: [PATCH] Wxwidgets: Improve memory search and refactor text panel code --- include/platform/wxwidgets/textrender.hpp | 22 ++ include/platform/wxwidgets/window_status.hpp | 14 +- src/platform/wxwidgets/mainwindow.cpp | 5 +- src/platform/wxwidgets/memorysearch.cpp | 338 ++++++++++++++----- src/platform/wxwidgets/status.cpp | 102 ++---- src/platform/wxwidgets/textrender.cpp | 73 ++++ 6 files changed, 366 insertions(+), 188 deletions(-) diff --git a/include/platform/wxwidgets/textrender.hpp b/include/platform/wxwidgets/textrender.hpp index abcfcc11..ce0111f8 100644 --- a/include/platform/wxwidgets/textrender.hpp +++ b/include/platform/wxwidgets/textrender.hpp @@ -1,6 +1,7 @@ #ifndef _textrender__hpp__included__ #define _textrender__hpp__included__ +#include #include #include #include @@ -37,4 +38,25 @@ private: size_t height; }; +struct text_framebuffer_panel : public wxPanel, public text_framebuffer +{ +public: + text_framebuffer_panel(wxWindow* parent, size_t w, size_t h, wxWindowID id, wxWindow* redirect); + ~text_framebuffer_panel(); + void set_size(size_t _width, size_t _height); + void request_paint(); + bool AcceptsFocus() { return (redirect != NULL); } +protected: + virtual void prepare_paint() = 0; +private: + void on_erase(wxEraseEvent& e); + void on_paint(wxPaintEvent& e); + void on_focus(wxFocusEvent& e); + bool paint_requested; + bool locked; + bool size_changed; + std::vector buffer; + wxWindow* redirect; +}; + #endif diff --git a/include/platform/wxwidgets/window_status.hpp b/include/platform/wxwidgets/window_status.hpp index dc74efda..cfec51a3 100644 --- a/include/platform/wxwidgets/window_status.hpp +++ b/include/platform/wxwidgets/window_status.hpp @@ -9,22 +9,16 @@ class wxwin_status : public wxFrame { public: - class panel : public wxPanel + class panel : public text_framebuffer_panel { public: panel(wxWindow* _parent, wxWindow* tfocus, unsigned lines); - bool AcceptsFocus () const; - void on_focus(wxFocusEvent& e); - void on_paint(wxPaintEvent& e); - void on_erase(wxEraseEvent& e); - bool dirty; - wxWindow* parent; - wxWindow* tfocuswin; //-1: memory watch only, 0: Both, 1: Status only. void set_watch_flag(int f) { watch_flag = f; } + protected: + void prepare_paint(); private: - text_framebuffer statusvars; - text_framebuffer memorywatches; + text_framebuffer fb; int watch_flag; size_t previous_size; }; diff --git a/src/platform/wxwidgets/mainwindow.cpp b/src/platform/wxwidgets/mainwindow.cpp index 25050262..f97c3671 100644 --- a/src/platform/wxwidgets/mainwindow.cpp +++ b/src/platform/wxwidgets/mainwindow.cpp @@ -984,10 +984,7 @@ void wxwin_mainwindow::notify_resized() throw() void wxwin_mainwindow::notify_update_status() throw() { - if(!spanel->dirty) { - spanel->dirty = true; - spanel->Refresh(); - } + spanel->request_paint(); if(mwindow) mwindow->notify_update(); } diff --git a/src/platform/wxwidgets/memorysearch.cpp b/src/platform/wxwidgets/memorysearch.cpp index f94cf2d0..79ff7c25 100644 --- a/src/platform/wxwidgets/memorysearch.cpp +++ b/src/platform/wxwidgets/memorysearch.cpp @@ -4,6 +4,7 @@ #include "library/string.hpp" #include "platform/wxwidgets/platform.hpp" +#include "platform/wxwidgets/textrender.hpp" #include #include @@ -33,6 +34,17 @@ class wxwindow_memorysearch; namespace { + void connect_events(wxScrollBar* s, wxObjectEventFunction fun, wxEvtHandler* obj) + { + s->Connect(wxEVT_SCROLL_THUMBTRACK, fun, NULL, obj); + s->Connect(wxEVT_SCROLL_PAGEDOWN, fun, NULL, obj); + s->Connect(wxEVT_SCROLL_PAGEUP, fun, NULL, obj); + s->Connect(wxEVT_SCROLL_LINEDOWN, fun, NULL, obj); + s->Connect(wxEVT_SCROLL_LINEUP, fun, NULL, obj); + s->Connect(wxEVT_SCROLL_TOP, fun, NULL, obj); + s->Connect(wxEVT_SCROLL_BOTTOM, fun, NULL, obj); + } + const char* watchchars = "bBwWdDqQ"; wxwindow_memorysearch* mwatch; @@ -251,29 +263,54 @@ void wxwindow_memorysearch_vmasel::on_cancel(wxCommandEvent& e) class wxwindow_memorysearch : public wxFrame { public: + class panel : public text_framebuffer_panel + { + public: + panel(wxwindow_memorysearch* parent); + void set_selection(uint64_t first, uint64_t last); + void get_selection(uint64_t& first, uint64_t& last); + protected: + void prepare_paint(); + private: + wxwindow_memorysearch* parent; + uint64_t first_sel; + uint64_t last_sel; + }; wxwindow_memorysearch(); ~wxwindow_memorysearch(); bool ShouldPreventAppExit() const; void on_close(wxCloseEvent& e); void on_button_click(wxCommandEvent& e); void auto_update(); + void on_mousedrag(wxMouseEvent& e); void on_mouse(wxMouseEvent& e); + void on_scroll(wxScrollEvent& e); bool update_queued; private: + friend class panel; template void valuesearch(bool diff); template void valuesearch2(T value); template void valuesearch3(T value); void update(); - void on_mouse2(); + void on_mouse0(wxMouseEvent& e, bool polarity); + void on_mousedrag(); + void on_mouse2(wxMouseEvent& e); memorysearch* msearch; wxStaticText* count; - wxTextCtrl* matches; + wxScrollBar* scroll; + panel* matches; wxComboBox* type; wxCheckBox* hexmode2; wxCheckBox* autoupdate; - std::map addresses; + std::map addresses; + uint64_t act_line; + uint64_t drag_startline; + bool dragging; + int mpx, mpy; unsigned typecode; bool hexmode; + bool toomany; + int scroll_delta; std::set vmas_enabled; }; @@ -318,21 +355,30 @@ wxwindow_memorysearch::wxwindow_memorysearch() } toplevel->Add(searches); - toplevel->Add(count = new wxStaticText(this, wxID_ANY, wxT("XXX candidates")), 0, wxGROW); - toplevel->Add(matches = new wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(500, 300), - wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP | wxTE_NOHIDESEL), 1, wxGROW); + toplevel->Add(count = new wxStaticText(this, wxID_ANY, wxT("XXXXXX candidates")), 0, wxGROW); + wxBoxSizer* matchesb = new wxBoxSizer(wxHORIZONTAL); + matchesb->Add(matches = new panel(this), 1, wxGROW); + matchesb->Add(scroll = new wxScrollBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSB_VERTICAL), 0, + wxGROW); + toplevel->Add(matchesb, 1, wxGROW); + + scroll->SetScrollbar(0, 0, 0, 0); for(auto i : get_regions()) if(!i.readonly && !i.iospace) vmas_enabled.insert(i.region_name); - //matches->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this); - //matches->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this); - //matches->Connect(wxEVT_MIDDLE_DOWN, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this); - //matches->Connect(wxEVT_MIDDLE_UP, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this); + dragging = false; + toomany = true; + matches->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this); + matches->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this); + matches->Connect(wxEVT_MIDDLE_DOWN, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this); + matches->Connect(wxEVT_MIDDLE_UP, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this); matches->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this); matches->Connect(wxEVT_RIGHT_UP, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this); - //matches->Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this); + matches->Connect(wxEVT_MOTION, wxMouseEventHandler(wxwindow_memorysearch::on_mousedrag), NULL, this); + matches->Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this); + connect_events(scroll, wxScrollEventHandler(wxwindow_memorysearch::on_scroll), this); toplevel->SetSizeHints(this); Fit(); @@ -341,6 +387,115 @@ wxwindow_memorysearch::wxwindow_memorysearch() hexmode = false; } +wxwindow_memorysearch::panel::panel(wxwindow_memorysearch* _parent) + : text_framebuffer_panel(_parent, 40, 25, wxID_ANY, NULL) +{ + parent = _parent; + first_sel = 0; + last_sel = 0; +} + +void wxwindow_memorysearch::panel::prepare_paint() +{ + uint64_t first = parent->scroll->GetThumbPosition(); + auto ssize = get_characters(); + uint64_t last = first + ssize.second; + std::vector lines; + lines.reserve(ssize.second); + std::map addrs; + auto* ms = parent->msearch; + uint64_t addr_count; + bool toomany = false; + auto _parent = parent; + runemufn([&toomany, &first, &last, ms, &lines, &addrs, &addr_count, _parent]() { + addr_count = ms->get_candidate_count(); + if(last > addr_count) { + uint64_t delta = last - addr_count; + if(first > delta) { + first -= delta; + last -= delta; + } else { + last -= first; + first = 0; + } + } + if(addr_count <= CANDIDATE_LIMIT) { + std::list addrs2 = ms->get_candidates(); + long j = 0; + for(auto i : addrs2) { + std::string row = hexformat_address(i) + " "; + switch(_parent->typecode) { + case 0: + row += format_number_signed(memory_read_byte(i), _parent->hexmode); + break; + case 1: + row += format_number_unsigned(memory_read_byte(i), _parent->hexmode); + break; + case 2: + row += format_number_signed(memory_read_word(i), _parent->hexmode); + break; + case 3: + row += format_number_unsigned(memory_read_word(i), _parent->hexmode); + break; + case 4: + row += format_number_signed(memory_read_dword(i), _parent->hexmode); + break; + case 5: + row += format_number_unsigned(memory_read_dword(i), _parent->hexmode); + break; + case 6: + row += format_number_signed(memory_read_qword(i), _parent->hexmode); + break; + case 7: + row += format_number_unsigned(memory_read_qword(i), _parent->hexmode); + break; + }; + if(j >= first && j < last) + lines.push_back(row); + addrs[j++] = i; + } + } else { + lines.push_back("Too many candidates to display"); + toomany = true; + } + }); + std::swap(parent->addresses, addrs); + + std::ostringstream x; + x << addr_count << " " << ((addr_count != 1) ? "candidates" : "candidate"); + parent->count->SetLabel(towxstring(x.str())); + + clear(); + for(unsigned i = 0; i < lines.size(); i++) { + bool sel = (first + i) >= first_sel && (first + i) < last_sel; + write(lines[i], 0, 0, i, sel ? 0xFFFFFF : 0, sel ? 0 : 0xFFFFFF); + } + + if(last_sel > last) + last_sel = last; + if(first_sel > last) + first_sel = last; + + parent->toomany = toomany; + if(!toomany && addr_count > ssize.second) + parent->scroll->SetScrollbar(first, ssize.second, addr_count, ssize.second); + else + parent->scroll->SetScrollbar(0, 0, 0, 0); +} + +void wxwindow_memorysearch::panel::set_selection(uint64_t first, uint64_t last) +{ + first_sel = first; + last_sel = last; + request_paint(); +} + +void wxwindow_memorysearch::panel::get_selection(uint64_t& first, uint64_t& last) +{ + first = first_sel; + last = last_sel; +} + wxwindow_memorysearch::~wxwindow_memorysearch() { delete msearch; @@ -352,19 +507,79 @@ bool wxwindow_memorysearch::ShouldPreventAppExit() const return false; } +void wxwindow_memorysearch::on_scroll(wxScrollEvent& e) +{ + matches->request_paint(); +} + void wxwindow_memorysearch::on_mouse(wxMouseEvent& e) { if(e.RightUp() || (e.LeftUp() && e.ControlDown())) - on_mouse2(); + on_mouse2(e); + else if(e.LeftDown()) + on_mouse0(e, true); + else if(e.LeftUp()) + on_mouse0(e, false); + + int wrotate = e.GetWheelRotation(); + int threshold = e.GetWheelDelta(); + if(threshold) + scroll_delta += wrotate; + while(wrotate && threshold && scroll_delta <= -threshold) { + //Scroll down by line. + uint64_t first = scroll->GetThumbPosition(); + if(addresses.count(first + matches->get_characters().second)) + scroll->SetThumbPosition(first + 1); + scroll_delta += threshold; + } + while(wrotate && threshold && scroll_delta >= threshold) { + //Scroll up by line. + //Scroll down by line. + uint64_t first = scroll->GetThumbPosition(); + if(first > 0 && addresses.count(first - 1)) + scroll->SetThumbPosition(first - 1); + scroll_delta -= threshold; + } } -void wxwindow_memorysearch::on_mouse2() +void wxwindow_memorysearch::on_mouse0(wxMouseEvent& e, bool polarity) +{ + dragging = polarity && !toomany; + if(dragging) { + mpx = e.GetX(); + mpy = e.GetY(); + uint64_t first = scroll->GetThumbPosition(); + drag_startline = first + e.GetY() / matches->get_cell().second; + } else if(mpx == e.GetX() && mpy == e.GetY()) { + matches->set_selection(0, 0); + } +} + +void wxwindow_memorysearch::on_mousedrag(wxMouseEvent& e) +{ + if(!dragging) + return; + uint64_t first = scroll->GetThumbPosition(); + uint64_t linenow = first + e.GetY() / matches->get_cell().second; + if(drag_startline < linenow) + matches->set_selection(drag_startline, linenow + 1); + else + matches->set_selection(linenow, drag_startline + 1); +} + +void wxwindow_memorysearch::on_mouse2(wxMouseEvent& e) { wxMenu menu; bool some_selected; - long start, end; - matches->GetSelection(&start, &end); + uint64_t start, end; + matches->get_selection(start, end); some_selected = (start < end); + if(!some_selected) { + uint64_t first = scroll->GetThumbPosition(); + act_line = first + e.GetY() / matches->get_cell().second; + if(addresses.count(act_line)) + some_selected = true; + } menu.Append(wxID_ADD, wxT("Add watch..."))->Enable(some_selected); menu.AppendSeparator(); menu.Append(wxID_DISQUALIFY, wxT("Disqualify"))->Enable(some_selected); @@ -390,58 +605,7 @@ void wxwindow_memorysearch::auto_update() void wxwindow_memorysearch::update() { - std::string ret; - uint64_t addr_count; - runemufn([this, &ret, &addr_count]() { - addr_count = this->msearch->get_candidate_count(); - if(addr_count <= CANDIDATE_LIMIT) { - this->addresses.clear(); - std::list addrs = this->msearch->get_candidates(); - long j = 0; - for(auto i : addrs) { - std::ostringstream row; - row << hexformat_address(i) << " "; - switch(this->typecode) { - case 0: - row << format_number_signed(memory_read_byte(i), this->hexmode); - break; - case 1: - row << format_number_unsigned(memory_read_byte(i), this->hexmode); - break; - case 2: - row << format_number_signed(memory_read_word(i), this->hexmode); - break; - case 3: - row << format_number_unsigned(memory_read_word(i), this->hexmode); - break; - case 4: - row << format_number_signed(memory_read_dword(i), this->hexmode); - break; - case 5: - row << format_number_unsigned(memory_read_dword(i), this->hexmode); - break; - case 6: - row << format_number_signed(memory_read_qword(i), this->hexmode); - break; - case 7: - row << format_number_unsigned(memory_read_qword(i), this->hexmode); - break; - }; - row << std::endl; - ret = ret + row.str(); - this->addresses[j++] = i; - } - } else { - ret = "Too many candidates to display"; - this->addresses.clear(); - } - }); - std::ostringstream x; - x << addr_count << " " << ((addr_count != 1) ? "candidates" : "candidate"); - count->SetLabel(towxstring(x.str())); - matches->SetValue(towxstring(ret)); - Fit(); - update_queued = false; + matches->request_paint(); } void wxwindow_memorysearch::on_button_click(wxCommandEvent& e) @@ -463,19 +627,14 @@ void wxwindow_memorysearch::on_button_click(wxCommandEvent& e) } else if(id == wxID_HEX_SELECT) { hexmode = hexmode2->GetValue(); } else if(id == wxID_ADD) { - long start, end; - long startx, starty, endx, endy; - matches->GetSelection(&start, &end); - if(start == end) - return; - if(!matches->PositionToXY(start, &startx, &starty)) - return; - if(!matches->PositionToXY(end, &endx, &endy)) - return; - if(endx == 0 && endy != 0) - endy--; + uint64_t start, end; + matches->get_selection(start, end); + if(start == end) { + start = act_line; + end = act_line + 1; + } char wch = watchchars[typecode]; - for(long r = starty; r <= endy; r++) { + for(long r = start; r < end; r++) { if(!addresses.count(r)) return; uint64_t addr = addresses[r]; @@ -489,25 +648,22 @@ void wxwindow_memorysearch::on_button_click(wxCommandEvent& e) } catch(canceled_exception& e) { } } + matches->set_selection(0, 0); } else if(id == wxID_DISQUALIFY) { - long start, end; - long startx, starty, endx, endy; - matches->GetSelection(&start, &end); - if(start == end) - return; - if(!matches->PositionToXY(start, &startx, &starty)) - return; - if(!matches->PositionToXY(end, &endx, &endy)) - return; - if(endx == 0 && endy != 0) - endy--; - for(long r = starty; r <= endy; r++) { + uint64_t start, end; + matches->get_selection(start, end); + if(start == end) { + start = act_line; + end = act_line + 1; + } + for(long r = start; r < end; r++) { if(!addresses.count(r)) return; uint64_t addr = addresses[r]; auto ms = msearch; runemufn([addr, ms]() { ms->dq_range(addr, addr); }); } + matches->set_selection(0, 0); } else if(id == wxID_SET_REGIONS) { wxwindow_memorysearch_vmasel* d = new wxwindow_memorysearch_vmasel(this, vmas_enabled); if(d->ShowModal() == wxID_OK) diff --git a/src/platform/wxwidgets/status.cpp b/src/platform/wxwidgets/status.cpp index 339b9e35..5844888f 100644 --- a/src/platform/wxwidgets/status.cpp +++ b/src/platform/wxwidgets/status.cpp @@ -21,35 +21,9 @@ namespace } wxwin_status::panel::panel(wxWindow* _parent, wxWindow* focuswin, unsigned lines) - : wxPanel(_parent) + : text_framebuffer_panel(_parent, STATWIDTH, lines ? lines : MAXSTATUS, wxID_ANY, focuswin) { - tfocuswin = focuswin; - parent = _parent; - dirty = false; - statusvars.set_size(STATWIDTH, lines ? lines : MAXSTATUS); - auto s = statusvars.get_pixels(); - SetMinSize(wxSize(s.first, s.second)); - this->Connect(wxEVT_PAINT, wxPaintEventHandler(wxwin_status::panel::on_paint), NULL, this); - this->Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(panel::on_erase), NULL, this); - this->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(wxwin_status::panel::on_focus), NULL, this); watch_flag = 0; - previous_size = 0; -} - -void wxwin_status::panel::on_erase(wxEraseEvent& e) -{ - //Blank. -} - -bool wxwin_status::panel::AcceptsFocus () const -{ - return false; -} - -void wxwin_status::panel::on_focus(wxFocusEvent& e) -{ - if(tfocuswin) - tfocuswin->SetFocus(); } wxwin_status::wxwin_status(int flag, const std::string& title) @@ -68,7 +42,7 @@ wxwin_status::~wxwin_status() { } -void wxwin_status::panel::on_paint(wxPaintEvent& e) +void wxwin_status::panel::prepare_paint() { //Quickly copy the status area. auto& s = platform::get_emustatus(); @@ -77,10 +51,8 @@ void wxwin_status::panel::on_paint(wxPaintEvent& e) while(s.next(i)) newstatus[i.key] = i.value; - memorywatches.clear(); - statusvars.clear(); - - int y = 0; + clear(); + size_t mem_width = 0; size_t oth_width = 0; size_t mem_count = 0; @@ -104,75 +76,39 @@ void wxwin_status::panel::on_paint(wxPaintEvent& e) single = true; regex_results r; + size_t p = 0; if(mem_count) { - size_t p = single ? 0 : 1; - memorywatches.set_size(STATWIDTH, mem_count + p); if(!single) - memorywatches.write("Memory watches:", 0, 0, 0, 0, 0xFFFFFF); + write("Memory watches:", 0, 0, p++, 0, 0xFFFFFF); for(auto i : newstatus) { if(r = regex("M\\[(.*)\\]", i.first)) { - size_t n = memorywatches.write(r[1], mem_width + 1, 0, p, 0, 0xFFFFFF); - memorywatches.write(i.second, 0, n, p, 0, 0xFFFFFF); - p++; + size_t n = write(r[1], mem_width + 1, 0, p, 0, 0xFFFFFF); + write(i.second, 0, n, p++, 0, 0xFFFFFF); } } } - + if(mem_count && oth_count) { + auto s = get_characters(); + for(unsigned i = 0; i < s.first; i++) + write(U"\u2500", 0, i, p, 0, 0xFFFFFF); + p++; + } + if(oth_count) { - size_t p = single ? 0 : 1; - statusvars.set_size(STATWIDTH, oth_count + p); if(!single) - statusvars.write("Status:", 0, 0, 0, 0, 0xFFFFFF); + write("Status:", 0, 0, p++, 0, 0xFFFFFF); for(auto i : newstatus) { if(regex_match("M\\[.*\\]", i.first)) continue; - size_t n = statusvars.write(i.first, oth_width + 1, 0, p, 0, 0xFFFFFF); - statusvars.write(i.second, 0, n, p, 0, 0xFFFFFF); - p++; + size_t n = write(i.first, oth_width + 1, 0, p, 0, 0xFFFFFF); + write(i.second, 0, n, p++, 0, 0xFFFFFF); } } - - auto ssize = statusvars.get_pixels(); - auto msize = memorywatches.get_pixels(); - size_t y2 = ssize.second + (!single ? 3 : 0); - size_t yl = ssize.second + 1; - std::vector buffer1, buffer2; - buffer1.resize(msize.first * msize.second * 3); - buffer2.resize(ssize.first * ssize.second * 3); - - wxPaintDC dc(this); - if(oth_count) { - statusvars.render(&buffer2[0]); - wxBitmap bmp2(wxImage(ssize.first, ssize.second, reinterpret_cast(&buffer2[0]), - true)); - dc.DrawBitmap(bmp2, 0, 0, false); - } - if(!single) { - dc.SetPen(*wxBLACK_PEN); - dc.DrawLine(0, yl, msize.first, yl); - } - if(mem_count) { - memorywatches.render(&buffer1[0]); - wxBitmap bmp1(wxImage(msize.first, msize.second, reinterpret_cast(&buffer1[0]), - true)); - dc.DrawBitmap(bmp1, 0, y2, false); - } - auto psize = GetSize(); - dc.SetPen(*wxWHITE_PEN); - dc.SetBrush(*wxWHITE_BRUSH); - size_t minsize = max(static_cast(psize.y), previous_size); - size_t maxuse = y2 + 16 * (mem_count + (!single ? 1 : 0)); - dc.DrawRectangle(0, maxuse, psize.x, minsize); - previous_size = maxuse; - dirty = false; } void wxwin_status::notify_update() throw() { - if(spanel->dirty) - return; - spanel->dirty = true; - spanel->Refresh(); + spanel->request_paint(); } bool wxwin_status::ShouldPreventAppExit() const diff --git a/src/platform/wxwidgets/textrender.cpp b/src/platform/wxwidgets/textrender.cpp index 47dc9bef..ef6ec4a9 100644 --- a/src/platform/wxwidgets/textrender.cpp +++ b/src/platform/wxwidgets/textrender.cpp @@ -1,6 +1,8 @@ #include "platform/wxwidgets/textrender.hpp" #include "fonts/wrapper.hpp" #include "library/utf8.hpp" +#include +#include extern const uint32_t text_framebuffer::element::white = 0xFFFFFF; extern const uint32_t text_framebuffer::element::black = 0x000000; @@ -141,6 +143,8 @@ size_t text_framebuffer::write(const std::string& str, size_t w, size_t x, size_ size_t text_framebuffer::write(const std::u32string& str, size_t w, size_t x, size_t y, uint32_t fg, uint32_t bg) { + if(y >= height) + return 0; size_t spos = 0; size_t slen = str.length(); size_t pused = 0; @@ -170,3 +174,72 @@ size_t text_framebuffer::write(const std::u32string& str, size_t w, size_t x, si return x; } +text_framebuffer_panel::text_framebuffer_panel(wxWindow* parent, size_t w, size_t h, wxWindowID id, + wxWindow* _redirect) + : wxPanel(parent, id), text_framebuffer(w, h) +{ + redirect = _redirect; + auto psize = get_pixels(); + SetMinSize(wxSize(psize.first, psize.second)); + this->Connect(wxEVT_PAINT, wxPaintEventHandler(text_framebuffer_panel::on_paint), NULL, this); + this->Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(text_framebuffer_panel::on_erase), NULL, this); + this->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(text_framebuffer_panel::on_focus), NULL, this); +} + +text_framebuffer_panel::~text_framebuffer_panel() +{ +} + +void text_framebuffer_panel::set_size(size_t _width, size_t _height) +{ + text_framebuffer::set_size(_width, _height); + auto psize = get_pixels(); + buffer.resize(psize.first * psize.second * 3); + if(!locked) { + SetMinSize(wxSize(psize.first, psize.second)); + } else + size_changed = true; + request_paint(); +} + +void text_framebuffer_panel::request_paint() +{ + if(size_changed) { + auto psize = get_pixels(); + SetMinSize(wxSize(psize.first, psize.second)); + size_changed = false; + paint_requested = true; + Refresh(); + } else if(!paint_requested) { + paint_requested = true; + Refresh(); + } +} + +void text_framebuffer_panel::on_erase(wxEraseEvent& e) +{ +} + +void text_framebuffer_panel::on_paint(wxPaintEvent& e) +{ + locked = true; + auto size = GetSize(); + text_framebuffer::set_size((size.x + 7) / 8, (size.y + 15) / 16); + auto psize = get_pixels(); + buffer.resize(psize.first * psize.second * 3); + prepare_paint(); + locked = false; + psize = get_pixels(); + wxPaintDC dc(this); + render(&buffer[0]); + wxBitmap bmp1(wxImage(psize.first, psize.second, reinterpret_cast(&buffer[0]), + true)); + dc.DrawBitmap(bmp1, 0, 0, false); + paint_requested = false; +} + +void text_framebuffer_panel::on_focus(wxFocusEvent& e) +{ + if(redirect) + redirect->SetFocus(); +}