31 #include "allheaders.h"
35 #include "config_auto.h"
52 static std::map<int, ScrollView*> svmap;
53 static std::mutex* svmap_mu;
55 static std::map<std::pair<ScrollView*, SVEventType>,
56 std::pair<SVSemaphore*, SVEvent*> > waiting_for_events;
57 static std::mutex* waiting_for_events_mu;
63 any->parameter =
new char[strlen(
parameter) + 1];
79 #ifndef GRAPHICS_DISABLED
80 void ScrollView::MessageReceiver() {
85 int counter_event_id = 0;
86 char* message =
nullptr;
89 message = ScrollView::GetStream()->
Receive();
90 }
while (message ==
nullptr);
105 sscanf(message,
"%d,%d,%d,%d,%d,%d,%d,%n", &window_id, &ev_type, &cur->x,
106 &cur->y, &cur->x_size, &cur->y_size, &cur->command_id, &n);
107 char* p = (message + n);
110 cur->window = svmap[window_id];
112 if (cur->window !=
nullptr) {
113 cur->parameter =
new char[strlen(p) + 1];
114 strcpy(cur->parameter, p);
116 cur->parameter[strlen(p)] =
'\0';
118 cur->type = static_cast<SVEventType>(ev_type);
121 cur->x -= cur->x_size;
123 cur->x_size = -cur->x_size;
125 cur->y -= cur->y_size;
127 cur->y_size = -cur->y_size;
129 if (cur->window->y_axis_is_reversed_)
130 cur->y = cur->window->TranslateYCoordinate(cur->y + cur->y_size);
131 cur->counter = counter_event_id;
135 counter_event_id += 2;
141 cur->window->SetEvent(cur);
144 std::pair<ScrollView*, SVEventType> awaiting_list(cur->window,
146 std::pair<ScrollView*, SVEventType> awaiting_list_any(cur->window,
148 std::pair<ScrollView*, SVEventType> awaiting_list_any_window((
ScrollView*)
nullptr,
150 waiting_for_events_mu->lock();
151 if (waiting_for_events.count(awaiting_list) > 0) {
152 waiting_for_events[awaiting_list].second = cur;
153 waiting_for_events[awaiting_list].first->Signal();
154 }
else if (waiting_for_events.count(awaiting_list_any) > 0) {
155 waiting_for_events[awaiting_list_any].second = cur;
156 waiting_for_events[awaiting_list_any].first->Signal();
157 }
else if (waiting_for_events.count(awaiting_list_any_window) > 0) {
158 waiting_for_events[awaiting_list_any_window].second = cur;
159 waiting_for_events[awaiting_list_any_window].first->Signal();
164 waiting_for_events_mu->unlock();
178 message = ScrollView::GetStream()->
Receive();
179 }
while (message ==
nullptr);
187 {255, 255, 255, 255},
196 {128, 128, 255, 255},
200 {192, 192, 255, 255},
203 {255, 128, 128, 255},
207 {192, 192, 128, 255},
212 {192, 255, 192, 255},
214 {192, 192, 192, 255},
217 {128, 128, 128, 255},
222 {255, 192, 192, 255},
227 {255, 192, 128, 255},
241 SVNetwork* ScrollView::stream_ =
nullptr;
242 int ScrollView::nr_created_windows_ = 0;
243 int ScrollView::image_index_ = 0;
247 int y_size,
int x_canvas_size,
int y_canvas_size,
248 bool y_axis_reversed,
const char* server_name) {
249 Initialize(name, x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size,
250 y_axis_reversed, server_name);}
254 int y_size,
int x_canvas_size,
int y_canvas_size,
255 bool y_axis_reversed) {
256 Initialize(name, x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size,
257 y_axis_reversed,
"localhost");
262 int y_size,
int x_canvas_size,
int y_canvas_size) {
263 Initialize(name, x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size,
268 void ScrollView::Initialize(
const char* name,
int x_pos,
int y_pos,
int x_size,
269 int y_size,
int x_canvas_size,
int y_canvas_size,
270 bool y_axis_reversed,
const char* server_name) {
273 if (stream_ ==
nullptr) {
274 nr_created_windows_ = 0;
276 waiting_for_events_mu =
new std::mutex();
277 svmap_mu =
new std::mutex();
279 "svmain = luajava.bindClass('com.google.scrollview.ScrollView')\n");
280 std::thread t(&ScrollView::MessageReceiver);
285 nr_created_windows_++;
286 event_handler_ =
nullptr;
287 event_handler_ended_ =
false;
288 y_axis_is_reversed_ = y_axis_reversed;
289 y_size_ = y_canvas_size;
291 window_id_ = nr_created_windows_;
294 points_->
empty =
true;
297 svmap[window_id_] =
this;
300 for (
auto & i : event_table_) {
304 mutex_ =
new std::mutex();
309 snprintf(message,
sizeof(message),
310 "w%u = luajava.newInstance('com.google.scrollview.ui"
311 ".SVWindow','%s',%u,%u,%u,%u,%u,%u,%u)\n",
312 window_id_, window_name_, window_id_,
313 x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size);
316 std::thread t(&ScrollView::StartEventHandler,
this);
321 void ScrollView::StartEventHandler() {
334 if (event_table_[i] !=
nullptr &&
335 (serial < 0 || event_table_[i]->counter < serial)) {
336 new_event = event_table_[i];
337 serial = event_table_[i]->
counter;
342 if (new_event !=
nullptr) {
343 event_table_[k] =
nullptr;
345 if (event_handler_ !=
nullptr) { event_handler_->
Notify(new_event); }
348 event_handler_ended_ =
true;
359 #endif // GRAPHICS_DISABLED
362 #ifndef GRAPHICS_DISABLED
364 if (svmap[window_id_] !=
nullptr) {
372 svmap[window_id_] =
nullptr;
377 while (!event_handler_ended_)
385 for (
auto & i : event_table_) {
388 #endif // GRAPHICS_DISABLED
391 #ifndef GRAPHICS_DISABLED
399 va_start(args, format);
400 vsnprintf(message,
sizeof(message), format, args);
404 snprintf(form,
sizeof(form),
"w%u:%s\n", window_id_, message);
417 event_handler_ = listener;
420 void ScrollView::Signal() {
424 void ScrollView::SetEvent(
SVEvent* svevent) {
431 std::lock_guard<std::mutex> guard(*mutex_);
433 delete event_table_[specific->
type];
436 event_table_[specific->
type] = specific;
447 std::pair<ScrollView*, SVEventType> ea(
this,
type);
448 waiting_for_events_mu->lock();
449 waiting_for_events[ea] = std::pair<SVSemaphore*, SVEvent*> (sem, (
SVEvent*)
nullptr);
450 waiting_for_events_mu->unlock();
455 waiting_for_events_mu->lock();
456 SVEvent* ret = waiting_for_events[ea].second;
457 waiting_for_events.erase(ea);
459 waiting_for_events_mu->unlock();
469 waiting_for_events_mu->lock();
470 waiting_for_events[ea] = std::pair<SVSemaphore*, SVEvent*> (sem, (
SVEvent*)
nullptr);
471 waiting_for_events_mu->unlock();
476 waiting_for_events_mu->lock();
477 SVEvent* ret = waiting_for_events[ea].second;
478 waiting_for_events.erase(ea);
479 waiting_for_events_mu->unlock();
484 void ScrollView::SendPolygon() {
485 if (!points_->
empty) {
486 points_->
empty =
true;
487 int length = points_->
xcoords.size();
492 SendMsg(
"drawLine(%d,%d,%d,%d)",
495 }
else if (length > 2) {
497 SendMsg(
"createPolyline(%d)", length);
500 for (
int i = 0; i < length; ++i) {
503 decimal_coords += coordpair;
505 decimal_coords +=
'\n';
529 points_->
empty =
false;
538 }
else if (!points_->
xcoords.empty() && x2 == points_->
xcoords.back() &&
551 if (visible) {
SendMsg(
"setVisible(true)");
552 }
else {
SendMsg(
"setVisible(false)"); }
557 if (b) {
SendMsg(
"setAlwaysOnTop(true)");
558 }
else {
SendMsg(
"setAlwaysOnTop(false)"); }
566 va_start(args, format);
567 vsnprintf(message,
sizeof(message), format, args);
571 snprintf(form,
sizeof(form),
"w%u:%s", window_id_, message);
573 char* esc = AddEscapeChars(form);
574 SendMsg(
"addMessage(\"%s\")", esc);
596 SendMsg(
"setStrokeWidth(%f)", width);
602 if (x1 == x2 && y1 == y2)
604 SendMsg(
"drawRectangle(%d,%d,%d,%d)",
611 SendMsg(
"drawEllipse(%d,%d,%u,%u)",
617 SendMsg(
"pen(%d,%d,%d)", red, green, blue);
622 SendMsg(
"pen(%d,%d,%d,%d)", red, green, blue, alpha);
627 SendMsg(
"brush(%d,%d,%d)", red, green, blue);
632 SendMsg(
"brush(%d,%d,%d,%d)", red, green, blue, alpha);
637 bool bold,
bool italic,
bool underlined) {
642 if (bold) { b =
"true";
643 }
else { b =
"false"; }
644 if (italic) { i =
"true";
645 }
else { i =
"false"; }
646 if (underlined) { u =
"true";
647 }
else { u =
"false"; }
648 SendMsg(
"textAttributes('%s',%u,%s,%s,%s)", font, pixel_size,
659 SendMsg(
"openImage('%s')", image);
660 SendMsg(
"drawImage('%s',%d,%d)",
666 int cmdEvent,
bool flag) {
667 if (parent ==
nullptr) { parent =
""; }
668 if (flag) {
SendMsg(
"addMenuBarItem('%s','%s',%d,true)",
669 parent, name, cmdEvent);
670 }
else {
SendMsg(
"addMenuBarItem('%s','%s',%d,false)",
671 parent, name, cmdEvent); }
676 if (parent ==
nullptr) { parent =
""; }
677 SendMsg(
"addMenuBarItem('%s','%s',%d)", parent, name, cmdEvent);
682 if (parent ==
nullptr) { parent =
""; }
683 SendMsg(
"addMenuBarItem('%s','%s')", parent, name);
688 if (parent ==
nullptr) { parent =
""; }
689 SendMsg(
"addPopupMenuItem('%s','%s')", parent, name);
694 int cmdEvent,
const char* value,
const char* desc) {
695 if (parent ==
nullptr) { parent =
""; }
696 char* esc = AddEscapeChars(value);
697 char* esc2 = AddEscapeChars(desc);
698 SendMsg(
"addPopupMenuItem('%s','%s',%d,'%s','%s')", parent, name,
699 cmdEvent, esc, esc2);
711 std::lock_guard<std::mutex> guard(*svmap_mu);
712 for (
auto & iter : svmap) {
713 if (iter.second !=
nullptr)
714 iter.second->UpdateWindow();
720 Pen(table_colors[color][0], table_colors[color][1],
721 table_colors[color][2], table_colors[color][3]);
726 Brush(table_colors[color][0],
727 table_colors[color][1],
728 table_colors[color][2],
729 table_colors[color][3]);
734 SendMsg(
"showInputDialog(\"%s\")", msg);
738 char* p =
new char[strlen(ev->
parameter) + 1];
746 SendMsg(
"showYesNoDialog(\"%s\")", msg);
760 SendMsg(
"zoomRectangle(%d,%d,%d,%d)",
761 std::min(x1, x2), std::min(y1, y2), std::max(x1, x2), std::max(y1, y2));
768 pixWriteMem(&data, &size, image, IFF_PNG);
769 int base64_len = (size + 2) / 3 * 4;
771 SendMsg(
"readImage(%d,%d,%d)", x_pos, y_pos, base64_len);
773 const char kBase64Table[64] = {
774 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
775 'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
776 'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
777 'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
778 'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
779 'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
780 'w',
'x',
'y',
'z',
'0',
'1',
'2',
'3',
781 '4',
'5',
'6',
'7',
'8',
'9',
'+',
'/',
783 char* base64 =
new char[base64_len + 1];
784 memset(base64,
'=', base64_len);
785 base64[base64_len] =
'\0';
789 for (
size_t i = 0; i < size; ++i) {
790 int code = (data[i] >> (bits_left + 2)) | remainder;
791 base64[code_len++] = kBase64Table[code & 63];
793 remainder = data[i] << (6 - bits_left);
794 if (bits_left == 6) {
795 base64[code_len++] = kBase64Table[remainder & 63];
801 base64[code_len++] = kBase64Table[remainder & 63];
809 char* ScrollView::AddEscapeChars(
const char* input) {
810 const char* nextptr = strchr(input,
'\'');
811 const char* lastptr = input;
814 while (nextptr !=
nullptr) {
815 strncpy(message+pos, lastptr, nextptr-lastptr);
816 pos += nextptr - lastptr;
820 nextptr = strchr(nextptr+1,
'\'');
822 strcpy(message+pos, lastptr);
828 if (!y_axis_is_reversed_) {
return y;
829 }
else {
return y_size_ - y; }
832 #endif // GRAPHICS_DISABLED