Wxwidgets: Don't resize in paint handler, it makes wxwidgets blow up
[lsnes.git] / src / platform / wxwidgets / status.cpp
blob6fed7dad62c960a46fbe749e01975752abdcdd33
1 #include "core/window.hpp"
2 #include "platform/wxwidgets/platform.hpp"
3 #include "platform/wxwidgets/window_status.hpp"
4 #include "library/string.hpp"
5 #include "library/minmax.hpp"
6 #include <iostream>
8 #define STATWIDTH 40
9 #define MAXSTATUS 15
11 namespace
13 std::string string_pad(const std::string& x, size_t width)
15 if(x.length() >= width)
16 return x;
17 std::string y = x;
18 y.append(width - y.length(), ' ');
19 return y;
23 wxwin_status::panel::panel(wxWindow* _parent, wxWindow* focuswin, unsigned lines)
24 : wxPanel(_parent)
26 tfocuswin = focuswin;
27 parent = _parent;
28 dirty = false;
29 statusvars.set_size(STATWIDTH, lines ? lines : MAXSTATUS);
30 auto s = statusvars.get_pixels();
31 SetMinSize(wxSize(s.first, s.second));
32 this->Connect(wxEVT_PAINT, wxPaintEventHandler(wxwin_status::panel::on_paint), NULL, this);
33 this->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(wxwin_status::panel::on_focus), NULL, this);
34 watch_flag = 0;
37 bool wxwin_status::panel::AcceptsFocus () const
39 return false;
42 void wxwin_status::panel::on_focus(wxFocusEvent& e)
44 if(tfocuswin)
45 tfocuswin->SetFocus();
48 wxwin_status::wxwin_status(int flag, const std::string& title)
49 : wxFrame(NULL, wxID_ANY, towxstring(title), wxDefaultPosition, wxSize(-1, -1),
50 wxMINIMIZE_BOX | wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION | wxCLIP_CHILDREN)
52 wxBoxSizer* top_s = new wxBoxSizer(wxVERTICAL);
53 top_s->Add(spanel = new wxwin_status::panel(this, NULL, MAXSTATUS), 1, wxGROW);
54 spanel->set_watch_flag(flag);
55 top_s->SetSizeHints(this);
56 SetSizer(top_s);
57 Fit();
60 wxwin_status::~wxwin_status()
64 void wxwin_status::panel::on_paint(wxPaintEvent& e)
66 //Quickly copy the status area.
67 auto& s = platform::get_emustatus();
68 std::map<std::string, std::string> newstatus;
69 emulator_status::iterator i = s.first();
70 while(s.next(i))
71 newstatus[i.key] = i.value;
73 memorywatches.clear();
74 statusvars.clear();
76 int y = 0;
77 size_t mem_width = 0;
78 size_t oth_width = 0;
79 size_t mem_count = 0;
80 size_t oth_count = 0;
81 bool single = false;
82 for(auto i : newstatus) {
83 bool x = regex_match("M\\[.*\\]", i.first);
84 if(x) {
85 mem_width = max(mem_width, text_framebuffer::text_width(i.first) - 3);
86 mem_count++;
87 } else {
88 oth_width = max(oth_width, text_framebuffer::text_width(i.first));
89 oth_count++;
92 if(watch_flag < 0)
93 oth_count = 0;
94 if(watch_flag > 0)
95 mem_count = 0;
96 if(!oth_count || !mem_count)
97 single = true;
99 regex_results r;
100 if(mem_count) {
101 size_t p = single ? 0 : 1;
102 memorywatches.set_size(STATWIDTH, mem_count + p);
103 if(!single)
104 memorywatches.write("Memory watches:", 0, 0, 0, 0, 0xFFFFFF);
105 for(auto i : newstatus) {
106 if(r = regex("M\\[(.*)\\]", i.first)) {
107 size_t n = memorywatches.write(r[1], mem_width + 1, 0, p, 0, 0xFFFFFF);
108 memorywatches.write(i.second, 0, n, p, 0, 0xFFFFFF);
109 p++;
114 if(oth_count) {
115 size_t p = single ? 0 : 1;
116 statusvars.set_size(STATWIDTH, oth_count + p);
117 if(!single)
118 statusvars.write("Status:", 0, 0, 0, 0, 0xFFFFFF);
119 for(auto i : newstatus) {
120 if(regex_match("M\\[.*\\]", i.first))
121 continue;
122 size_t n = statusvars.write(i.first, oth_width + 1, 0, p, 0, 0xFFFFFF);
123 statusvars.write(i.second, 0, n, p, 0, 0xFFFFFF);
124 p++;
128 auto ssize = statusvars.get_pixels();
129 auto msize = memorywatches.get_pixels();
130 size_t y2 = !single ? ssize.second + 3 : 0;
131 size_t yt = (oth_count ? ssize.second : 0) + (mem_count ? msize.second : 0) + (!single ? 3 : 0);
132 size_t yl = msize.second + 1;
133 std::vector<char> buffer1, buffer2;
134 buffer1.resize(msize.first * msize.second * 3);
135 buffer2.resize(ssize.first * ssize.second * 3);
137 wxPaintDC dc(this);
138 dc.Clear();
139 if(oth_count) {
140 statusvars.render(&buffer2[0]);
141 wxBitmap bmp2(wxImage(ssize.first, ssize.second, reinterpret_cast<unsigned char*>(&buffer2[0]),
142 true));
143 dc.DrawBitmap(bmp2, 0, 0, false);
145 if(!single) {
146 dc.SetPen(wxPen(wxColour(0, 0, 0)));
147 dc.DrawLine(0, yl, msize.first, yl);
149 if(mem_count) {
150 memorywatches.render(&buffer1[0]);
151 wxBitmap bmp1(wxImage(msize.first, msize.second, reinterpret_cast<unsigned char*>(&buffer1[0]),
152 true));
153 dc.DrawBitmap(bmp1, 0, y2, false);
155 dirty = false;
158 void wxwin_status::notify_update() throw()
160 if(spanel->dirty)
161 return;
162 spanel->dirty = true;
163 spanel->Refresh();
166 bool wxwin_status::ShouldPreventAppExit() const
168 return false;