Wxwidgets: Improve memory search and refactor text panel code

This commit is contained in:
Ilari Liusvaara 2013-05-11 02:19:49 +03:00
parent d1c8435fa2
commit 9dc12ae746
6 changed files with 366 additions and 188 deletions

View file

@ -1,6 +1,7 @@
#ifndef _textrender__hpp__included__ #ifndef _textrender__hpp__included__
#define _textrender__hpp__included__ #define _textrender__hpp__included__
#include <wx/panel.h>
#include <cstdint> #include <cstdint>
#include <map> #include <map>
#include <cstdlib> #include <cstdlib>
@ -37,4 +38,25 @@ private:
size_t height; 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<char> buffer;
wxWindow* redirect;
};
#endif #endif

View file

@ -9,22 +9,16 @@
class wxwin_status : public wxFrame class wxwin_status : public wxFrame
{ {
public: public:
class panel : public wxPanel class panel : public text_framebuffer_panel
{ {
public: public:
panel(wxWindow* _parent, wxWindow* tfocus, unsigned lines); 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. //-1: memory watch only, 0: Both, 1: Status only.
void set_watch_flag(int f) { watch_flag = f; } void set_watch_flag(int f) { watch_flag = f; }
protected:
void prepare_paint();
private: private:
text_framebuffer statusvars; text_framebuffer fb;
text_framebuffer memorywatches;
int watch_flag; int watch_flag;
size_t previous_size; size_t previous_size;
}; };

View file

@ -984,10 +984,7 @@ void wxwin_mainwindow::notify_resized() throw()
void wxwin_mainwindow::notify_update_status() throw() void wxwin_mainwindow::notify_update_status() throw()
{ {
if(!spanel->dirty) { spanel->request_paint();
spanel->dirty = true;
spanel->Refresh();
}
if(mwindow) if(mwindow)
mwindow->notify_update(); mwindow->notify_update();
} }

View file

@ -4,6 +4,7 @@
#include "library/string.hpp" #include "library/string.hpp"
#include "platform/wxwidgets/platform.hpp" #include "platform/wxwidgets/platform.hpp"
#include "platform/wxwidgets/textrender.hpp"
#include <sstream> #include <sstream>
#include <iomanip> #include <iomanip>
@ -33,6 +34,17 @@ class wxwindow_memorysearch;
namespace 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"; const char* watchchars = "bBwWdDqQ";
wxwindow_memorysearch* mwatch; wxwindow_memorysearch* mwatch;
@ -251,29 +263,54 @@ void wxwindow_memorysearch_vmasel::on_cancel(wxCommandEvent& e)
class wxwindow_memorysearch : public wxFrame class wxwindow_memorysearch : public wxFrame
{ {
public: 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();
~wxwindow_memorysearch(); ~wxwindow_memorysearch();
bool ShouldPreventAppExit() const; bool ShouldPreventAppExit() const;
void on_close(wxCloseEvent& e); void on_close(wxCloseEvent& e);
void on_button_click(wxCommandEvent& e); void on_button_click(wxCommandEvent& e);
void auto_update(); void auto_update();
void on_mousedrag(wxMouseEvent& e);
void on_mouse(wxMouseEvent& e); void on_mouse(wxMouseEvent& e);
void on_scroll(wxScrollEvent& e);
bool update_queued; bool update_queued;
private: private:
friend class panel;
template<typename T> void valuesearch(bool diff); template<typename T> void valuesearch(bool diff);
template<typename T> void valuesearch2(T value); template<typename T> void valuesearch2(T value);
template<typename T> void valuesearch3(T value); template<typename T> void valuesearch3(T value);
void update(); void update();
void on_mouse2(); void on_mouse0(wxMouseEvent& e, bool polarity);
void on_mousedrag();
void on_mouse2(wxMouseEvent& e);
memorysearch* msearch; memorysearch* msearch;
wxStaticText* count; wxStaticText* count;
wxTextCtrl* matches; wxScrollBar* scroll;
panel* matches;
wxComboBox* type; wxComboBox* type;
wxCheckBox* hexmode2; wxCheckBox* hexmode2;
wxCheckBox* autoupdate; wxCheckBox* autoupdate;
std::map<long, uint64_t> addresses; std::map<uint64_t, uint64_t> addresses;
uint64_t act_line;
uint64_t drag_startline;
bool dragging;
int mpx, mpy;
unsigned typecode; unsigned typecode;
bool hexmode; bool hexmode;
bool toomany;
int scroll_delta;
std::set<std::string> vmas_enabled; std::set<std::string> vmas_enabled;
}; };
@ -318,21 +355,30 @@ wxwindow_memorysearch::wxwindow_memorysearch()
} }
toplevel->Add(searches); toplevel->Add(searches);
toplevel->Add(count = new wxStaticText(this, wxID_ANY, wxT("XXX candidates")), 0, wxGROW); toplevel->Add(count = new wxStaticText(this, wxID_ANY, wxT("XXXXXX candidates")), 0, wxGROW);
toplevel->Add(matches = new wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(500, 300), wxBoxSizer* matchesb = new wxBoxSizer(wxHORIZONTAL);
wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP | wxTE_NOHIDESEL), 1, wxGROW); 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()) for(auto i : get_regions())
if(!i.readonly && !i.iospace) if(!i.readonly && !i.iospace)
vmas_enabled.insert(i.region_name); vmas_enabled.insert(i.region_name);
//matches->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this); dragging = false;
//matches->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this); toomany = true;
//matches->Connect(wxEVT_MIDDLE_DOWN, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this); matches->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this);
//matches->Connect(wxEVT_MIDDLE_UP, 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_DOWN, wxMouseEventHandler(wxwindow_memorysearch::on_mouse), NULL, this);
matches->Connect(wxEVT_RIGHT_UP, 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); toplevel->SetSizeHints(this);
Fit(); Fit();
@ -341,6 +387,115 @@ wxwindow_memorysearch::wxwindow_memorysearch()
hexmode = false; 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<std::string> lines;
lines.reserve(ssize.second);
std::map<uint64_t, uint64_t> 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<uint64_t> 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() wxwindow_memorysearch::~wxwindow_memorysearch()
{ {
delete msearch; delete msearch;
@ -352,19 +507,79 @@ bool wxwindow_memorysearch::ShouldPreventAppExit() const
return false; return false;
} }
void wxwindow_memorysearch::on_scroll(wxScrollEvent& e)
{
matches->request_paint();
}
void wxwindow_memorysearch::on_mouse(wxMouseEvent& e) void wxwindow_memorysearch::on_mouse(wxMouseEvent& e)
{ {
if(e.RightUp() || (e.LeftUp() && e.ControlDown())) 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; wxMenu menu;
bool some_selected; bool some_selected;
long start, end; uint64_t start, end;
matches->GetSelection(&start, &end); matches->get_selection(start, end);
some_selected = (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.Append(wxID_ADD, wxT("Add watch..."))->Enable(some_selected);
menu.AppendSeparator(); menu.AppendSeparator();
menu.Append(wxID_DISQUALIFY, wxT("Disqualify"))->Enable(some_selected); menu.Append(wxID_DISQUALIFY, wxT("Disqualify"))->Enable(some_selected);
@ -390,58 +605,7 @@ void wxwindow_memorysearch::auto_update()
void wxwindow_memorysearch::update() void wxwindow_memorysearch::update()
{ {
std::string ret; matches->request_paint();
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<uint64_t> 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;
} }
void wxwindow_memorysearch::on_button_click(wxCommandEvent& e) 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) { } else if(id == wxID_HEX_SELECT) {
hexmode = hexmode2->GetValue(); hexmode = hexmode2->GetValue();
} else if(id == wxID_ADD) { } else if(id == wxID_ADD) {
long start, end; uint64_t start, end;
long startx, starty, endx, endy; matches->get_selection(start, end);
matches->GetSelection(&start, &end); if(start == end) {
if(start == end) start = act_line;
return; end = act_line + 1;
if(!matches->PositionToXY(start, &startx, &starty)) }
return;
if(!matches->PositionToXY(end, &endx, &endy))
return;
if(endx == 0 && endy != 0)
endy--;
char wch = watchchars[typecode]; char wch = watchchars[typecode];
for(long r = starty; r <= endy; r++) { for(long r = start; r < end; r++) {
if(!addresses.count(r)) if(!addresses.count(r))
return; return;
uint64_t addr = addresses[r]; uint64_t addr = addresses[r];
@ -489,25 +648,22 @@ void wxwindow_memorysearch::on_button_click(wxCommandEvent& e)
} catch(canceled_exception& e) { } catch(canceled_exception& e) {
} }
} }
matches->set_selection(0, 0);
} else if(id == wxID_DISQUALIFY) { } else if(id == wxID_DISQUALIFY) {
long start, end; uint64_t start, end;
long startx, starty, endx, endy; matches->get_selection(start, end);
matches->GetSelection(&start, &end); if(start == end) {
if(start == end) start = act_line;
return; end = act_line + 1;
if(!matches->PositionToXY(start, &startx, &starty)) }
return; for(long r = start; r < end; r++) {
if(!matches->PositionToXY(end, &endx, &endy))
return;
if(endx == 0 && endy != 0)
endy--;
for(long r = starty; r <= endy; r++) {
if(!addresses.count(r)) if(!addresses.count(r))
return; return;
uint64_t addr = addresses[r]; uint64_t addr = addresses[r];
auto ms = msearch; auto ms = msearch;
runemufn([addr, ms]() { ms->dq_range(addr, addr); }); runemufn([addr, ms]() { ms->dq_range(addr, addr); });
} }
matches->set_selection(0, 0);
} else if(id == wxID_SET_REGIONS) { } else if(id == wxID_SET_REGIONS) {
wxwindow_memorysearch_vmasel* d = new wxwindow_memorysearch_vmasel(this, vmas_enabled); wxwindow_memorysearch_vmasel* d = new wxwindow_memorysearch_vmasel(this, vmas_enabled);
if(d->ShowModal() == wxID_OK) if(d->ShowModal() == wxID_OK)

View file

@ -21,35 +21,9 @@ namespace
} }
wxwin_status::panel::panel(wxWindow* _parent, wxWindow* focuswin, unsigned lines) 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; 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) 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. //Quickly copy the status area.
auto& s = platform::get_emustatus(); auto& s = platform::get_emustatus();
@ -77,10 +51,8 @@ void wxwin_status::panel::on_paint(wxPaintEvent& e)
while(s.next(i)) while(s.next(i))
newstatus[i.key] = i.value; newstatus[i.key] = i.value;
memorywatches.clear(); clear();
statusvars.clear();
int y = 0;
size_t mem_width = 0; size_t mem_width = 0;
size_t oth_width = 0; size_t oth_width = 0;
size_t mem_count = 0; size_t mem_count = 0;
@ -104,75 +76,39 @@ void wxwin_status::panel::on_paint(wxPaintEvent& e)
single = true; single = true;
regex_results r; regex_results r;
size_t p = 0;
if(mem_count) { if(mem_count) {
size_t p = single ? 0 : 1;
memorywatches.set_size(STATWIDTH, mem_count + p);
if(!single) if(!single)
memorywatches.write("Memory watches:", 0, 0, 0, 0, 0xFFFFFF); write("Memory watches:", 0, 0, p++, 0, 0xFFFFFF);
for(auto i : newstatus) { for(auto i : newstatus) {
if(r = regex("M\\[(.*)\\]", i.first)) { if(r = regex("M\\[(.*)\\]", i.first)) {
size_t n = memorywatches.write(r[1], mem_width + 1, 0, p, 0, 0xFFFFFF); size_t n = write(r[1], mem_width + 1, 0, p, 0, 0xFFFFFF);
memorywatches.write(i.second, 0, n, 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++; p++;
} }
}
}
if(oth_count) { if(oth_count) {
size_t p = single ? 0 : 1;
statusvars.set_size(STATWIDTH, oth_count + p);
if(!single) if(!single)
statusvars.write("Status:", 0, 0, 0, 0, 0xFFFFFF); write("Status:", 0, 0, p++, 0, 0xFFFFFF);
for(auto i : newstatus) { for(auto i : newstatus) {
if(regex_match("M\\[.*\\]", i.first)) if(regex_match("M\\[.*\\]", i.first))
continue; continue;
size_t n = statusvars.write(i.first, oth_width + 1, 0, p, 0, 0xFFFFFF); size_t n = write(i.first, oth_width + 1, 0, p, 0, 0xFFFFFF);
statusvars.write(i.second, 0, n, p, 0, 0xFFFFFF); write(i.second, 0, n, p++, 0, 0xFFFFFF);
p++;
} }
} }
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<char> 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<unsigned char*>(&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<unsigned char*>(&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<size_t>(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() void wxwin_status::notify_update() throw()
{ {
if(spanel->dirty) spanel->request_paint();
return;
spanel->dirty = true;
spanel->Refresh();
} }
bool wxwin_status::ShouldPreventAppExit() const bool wxwin_status::ShouldPreventAppExit() const

View file

@ -1,6 +1,8 @@
#include "platform/wxwidgets/textrender.hpp" #include "platform/wxwidgets/textrender.hpp"
#include "fonts/wrapper.hpp" #include "fonts/wrapper.hpp"
#include "library/utf8.hpp" #include "library/utf8.hpp"
#include <wx/dc.h>
#include <wx/dcclient.h>
extern const uint32_t text_framebuffer::element::white = 0xFFFFFF; extern const uint32_t text_framebuffer::element::white = 0xFFFFFF;
extern const uint32_t text_framebuffer::element::black = 0x000000; 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) 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 spos = 0;
size_t slen = str.length(); size_t slen = str.length();
size_t pused = 0; 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; 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<unsigned char*>(&buffer[0]),
true));
dc.DrawBitmap(bmp1, 0, 0, false);
paint_requested = false;
}
void text_framebuffer_panel::on_focus(wxFocusEvent& e)
{
if(redirect)
redirect->SetFocus();
}