Wxwidgets: Improve memory search and refactor text panel code
This commit is contained in:
parent
d1c8435fa2
commit
9dc12ae746
6 changed files with 366 additions and 188 deletions
|
@ -1,6 +1,7 @@
|
|||
#ifndef _textrender__hpp__included__
|
||||
#define _textrender__hpp__included__
|
||||
|
||||
#include <wx/panel.h>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <cstdlib>
|
||||
|
@ -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<char> buffer;
|
||||
wxWindow* redirect;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "library/string.hpp"
|
||||
|
||||
#include "platform/wxwidgets/platform.hpp"
|
||||
#include "platform/wxwidgets/textrender.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
@ -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<typename T> void valuesearch(bool diff);
|
||||
template<typename T> void valuesearch2(T value);
|
||||
template<typename T> 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<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;
|
||||
bool hexmode;
|
||||
bool toomany;
|
||||
int scroll_delta;
|
||||
std::set<std::string> 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<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()
|
||||
{
|
||||
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<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;
|
||||
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)
|
||||
|
|
|
@ -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();
|
||||
clear();
|
||||
|
||||
int y = 0;
|
||||
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);
|
||||
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<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()
|
||||
{
|
||||
if(spanel->dirty)
|
||||
return;
|
||||
spanel->dirty = true;
|
||||
spanel->Refresh();
|
||||
spanel->request_paint();
|
||||
}
|
||||
|
||||
bool wxwin_status::ShouldPreventAppExit() const
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "platform/wxwidgets/textrender.hpp"
|
||||
#include "fonts/wrapper.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::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<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();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue