1 #include "platform/wxwidgets/window_messages.hpp"
2 #include "platform/wxwidgets/platform.hpp"
3 #include "platform/wxwidgets/loadsave.hpp"
4 #include <wx/clipbrd.h>
6 #include "library/minmax.hpp"
7 #include "core/window.hpp"
8 #include "core/project.hpp"
10 #define MAXMESSAGES 20
12 #define COMMAND_HISTORY_SIZE 500
14 wxwin_messages::panel::panel(wxwin_messages
* _parent
, unsigned lines
)
15 : text_framebuffer_panel(_parent
, PANELWIDTH
, lines
, wxID_ANY
, NULL
)
18 auto pcell
= get_cell();
19 line_separation
= pcell
.second
;
24 this->Connect(wxEVT_SIZE
, wxSizeEventHandler(wxwin_messages::panel::on_resize
), NULL
, this);
25 this->Connect(wxEVT_RIGHT_DOWN
, wxMouseEventHandler(wxwin_messages::panel::on_mouse
), NULL
, this);
26 this->Connect(wxEVT_RIGHT_UP
, wxMouseEventHandler(wxwin_messages::panel::on_mouse
), NULL
, this);
27 this->Connect(wxEVT_MOTION
, wxMouseEventHandler(wxwin_messages::panel::on_mouse
), NULL
, this);
28 this->Connect(wxEVT_MOUSEWHEEL
, wxMouseEventHandler(wxwin_messages::panel::on_mouse
), NULL
, this);
30 SetMinSize(wxSize(PANELWIDTH
* pcell
.first
, lines
* pcell
.second
));
33 void wxwin_messages::panel::on_mouse(wxMouseEvent
& e
)
35 //Handle mouse wheels first.
36 if(e
.GetWheelRotation() && e
.GetWheelDelta()) {
37 int unit
= e
.GetWheelDelta();
38 scroll_acc
+= e
.GetWheelRotation();
39 while(scroll_acc
<= -unit
) {
40 threads::alock
h(platform::msgbuf_lock());
41 platform::msgbuf
.scroll_down_line();
44 while(scroll_acc
>= e
.GetWheelDelta()) {
45 threads::alock
h(platform::msgbuf_lock());
46 platform::msgbuf
.scroll_up_line();
53 threads::alock
h(platform::msgbuf_lock());
54 gfirst
= platform::msgbuf
.get_visible_first();
56 uint64_t local_line
= e
.GetY() / line_separation
;
57 uint64_t global_line
= gfirst
+ local_line
;
59 line_clicked
= global_line
;
62 } else if(e
.RightUp()) {
63 line_declicked
= global_line
;
66 menu
.Connect(wxEVT_COMMAND_MENU_SELECTED
, wxCommandEventHandler(wxwin_messages::panel::on_menu
),
68 menu
.Append(wxID_COPY
, wxT("Copy to clipboard"));
69 menu
.Append(wxID_SAVE
, wxT("Save to file"));
72 line_current
= global_line
;
77 void wxwin_messages::panel::on_menu(wxCommandEvent
& e
)
80 uint64_t m
= min(line_clicked
, line_declicked
);
81 uint64_t M
= max(line_clicked
, line_declicked
);
84 threads::alock
h(platform::msgbuf_lock());
85 for(uint64_t i
= m
; i
<= M
; i
++) {
87 std::string mline
= platform::msgbuf
.get_message(i
);
88 if(lines
== 1) str
+= "\n";
90 if(lines
>= 1) str
+= "\n";
98 if (wxTheClipboard
->Open()) {
99 wxTheClipboard
->SetData(new wxTextDataObject(towxstring(str
)));
100 wxTheClipboard
->Close();
105 std::string filename
= choose_file_save(this, "Save messages to",
106 lsnes_instance
.project
.otherpath(), filetype_textfile
);
107 std::ofstream
s(filename
, std::ios::app
);
108 if(!s
) throw std::runtime_error("Error opening output file");
109 if(lines
== 1) str
+= "\n";
111 if(!s
) throw std::runtime_error("Error writing output file");
112 } catch(canceled_exception
& e
) {
113 } catch(std::exception
& e
) {
114 wxMessageBox(towxstring(e
.what()), _T("Error creating file"), wxICON_EXCLAMATION
| wxOK
,
121 wxSize
wxwin_messages::panel::DoGetBestSize() const
123 return wxSize(80 * 8, ilines
* 16);
126 wxwin_messages::wxwin_messages()
127 : wxFrame(NULL
, wxID_ANY
, wxT("lsnes: Messages"), wxDefaultPosition
, wxSize(-1, -1),
128 wxMINIMIZE_BOX
| wxCLOSE_BOX
| wxSYSTEM_MENU
| wxCAPTION
| wxCLIP_CHILDREN
|
131 wxBoxSizer
* top_s
= new wxBoxSizer(wxVERTICAL
);
133 top_s
->Add(mpanel
= new panel(this, MAXMESSAGES
), 1, wxEXPAND
);
134 platform::msgbuf
.set_max_window_size(MAXMESSAGES
);
136 wxFlexGridSizer
* buttons_s
= new wxFlexGridSizer(1, 6, 0, 0);
137 wxButton
* beginning
, * pageup
, * lineup
, * linedown
, * pagedown
, * end
;
138 buttons_s
->Add(beginning
= new wxButton(this, wxID_ANY
, wxT("Beginning")), 1, wxGROW
);
139 buttons_s
->Add(pageup
= new wxButton(this, wxID_ANY
, wxT("Page Up")), 1, wxGROW
);
140 buttons_s
->Add(lineup
= new wxButton(this, wxID_ANY
, wxT("Line Up")), 1, wxGROW
);
141 buttons_s
->Add(linedown
= new wxButton(this, wxID_ANY
, wxT("Line Down")), 1, wxGROW
);
142 buttons_s
->Add(pagedown
= new wxButton(this, wxID_ANY
, wxT("Page Down")), 1, wxGROW
);
143 buttons_s
->Add(end
= new wxButton(this, wxID_ANY
, wxT("End")), 1, wxGROW
);
144 beginning
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
, wxCommandEventHandler(wxwin_messages::on_scroll_home
),
146 pageup
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
, wxCommandEventHandler(wxwin_messages::on_scroll_pageup
),
148 lineup
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
, wxCommandEventHandler(wxwin_messages::on_scroll_lineup
),
150 linedown
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
, wxCommandEventHandler(wxwin_messages::on_scroll_linedown
),
152 pagedown
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
, wxCommandEventHandler(wxwin_messages::on_scroll_pagedown
),
154 end
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
, wxCommandEventHandler(wxwin_messages::on_scroll_end
),
156 top_s
->Add(buttons_s
, 0, wxGROW
);
158 wxBoxSizer
* cmd_s
= new wxBoxSizer(wxHORIZONTAL
);
160 cmd_s
->Add(command
= new wxComboBox(this, wxID_ANY
, wxT(""), wxDefaultPosition
, wxDefaultSize
,
161 0, NULL
, wxTE_PROCESS_ENTER
), 1, wxEXPAND
);
162 cmd_s
->Add(execute
= new wxButton(this, wxID_ANY
, wxT("Execute")), 0, wxGROW
);
163 command
->Connect(wxEVT_COMMAND_TEXT_ENTER
, wxCommandEventHandler(wxwin_messages::on_execute
),
165 execute
->Connect(wxEVT_COMMAND_BUTTON_CLICKED
, wxCommandEventHandler(wxwin_messages::on_execute
),
167 cmd_s
->SetSizeHints(this);
168 top_s
->Add(cmd_s
, 0, wxGROW
);
170 Connect(wxEVT_CLOSE_WINDOW
, wxCloseEventHandler(wxwin_messages::on_close
));
172 wxSize tmp
= mpanel
->GetMinSize();
173 mpanel
->SetMinSize(mpanel
->DoGetBestSize());
174 top_s
->SetSizeHints(this);
175 wxSize tmp2
= GetClientSize();
176 mpanel
->SetMinSize(tmp
);
177 top_s
->SetSizeHints(this);
181 wxwin_messages::~wxwin_messages()
185 void wxwin_messages::panel::prepare_paint()
188 uint64_t lines
, first
;
189 uint64_t xm
= min(line_clicked
, line_current
);
190 uint64_t xM
= max(line_clicked
, line_current
);
191 std::vector
<std::string
> msgs
;
193 threads::alock
h(platform::msgbuf_lock());
194 lines
= platform::msgbuf
.get_visible_count();
195 first
= platform::msgbuf
.get_visible_first();
197 for(size_t i
= 0; i
< lines
; i
++)
198 msgs
[i
] = platform::msgbuf
.get_message(first
+ i
);
200 auto size
= get_characters();
201 for(size_t i
= 0; i
< lines
; i
++) {
202 uint64_t global_line
= first
+ i
;
203 bool sel
= (global_line
>= xm
&& global_line
<= xM
) && mouse_held
;
204 std::string
& msg
= msgs
[i
];
205 uint32_t fg
= sel
? 0x0000FF : 0x000000;
206 uint32_t bg
= sel
? 0x000000 : 0xFFFFFF;
207 write(msg
, size
.first
, 0, i
, fg
, bg
);
212 void wxwin_messages::panel::on_resize(wxSizeEvent
& e
)
214 wxSize newsize
= e
.GetSize();
215 auto tcell
= get_cell();
216 size_t lines
= newsize
.y
/ tcell
.second
;
217 size_t linelen
= newsize
.x
/ tcell
.first
;
218 if(lines
< 1) lines
= 1;
219 if(linelen
< 1) linelen
= 1;
220 platform::msgbuf
.set_max_window_size(lines
);
221 set_size(linelen
, lines
);
226 void wxwin_messages::on_close(wxCloseEvent
& e
)
228 if(wxwidgets_exiting
)
234 void wxwin_messages::reshow()
239 void wxwin_messages::on_scroll_home(wxCommandEvent
& e
)
241 threads::alock
h(platform::msgbuf_lock());
242 platform::msgbuf
.scroll_beginning();
245 void wxwin_messages::on_scroll_pageup(wxCommandEvent
& e
)
247 threads::alock
h(platform::msgbuf_lock());
248 platform::msgbuf
.scroll_up_page();
251 void wxwin_messages::on_scroll_lineup(wxCommandEvent
& e
)
253 threads::alock
h(platform::msgbuf_lock());
254 platform::msgbuf
.scroll_up_line();
257 void wxwin_messages::on_scroll_linedown(wxCommandEvent
& e
)
259 threads::alock
h(platform::msgbuf_lock());
260 platform::msgbuf
.scroll_down_line();
263 void wxwin_messages::on_scroll_pagedown(wxCommandEvent
& e
)
265 threads::alock
h(platform::msgbuf_lock());
266 platform::msgbuf
.scroll_down_page();
269 void wxwin_messages::on_scroll_end(wxCommandEvent
& e
)
271 threads::alock
h(platform::msgbuf_lock());
272 platform::msgbuf
.scroll_end();
275 void wxwin_messages::on_execute(wxCommandEvent
& e
)
277 std::string cmd
= tostdstring(command
->GetValue());
280 command
->Insert(towxstring(cmd
), 0);
281 //If command is already there, delete the previous.
282 for(unsigned i
= 1; i
< command
->GetCount(); i
++)
283 if(tostdstring(command
->GetString(i
)) == cmd
) {
287 //Delete old commands to prevent box becoming unmageable.
288 if(command
->GetCount() > COMMAND_HISTORY_SIZE
)
289 command
->Delete(command
->GetCount() - 1);
290 lsnes_instance
.iqueue
.queue(cmd
);
293 void wxwin_messages::notify_update() throw()
295 mpanel
->request_paint();
298 bool wxwin_messages::ShouldPreventAppExit() const