32 #include "config_auto.h" 43 #include "allheaders.h" 52 static std::map<int, ScrollView*> svmap;
55 static std::map<std::pair<ScrollView*, SVEventType>,
56 std::pair<SVSemaphore*, SVEvent*> > waiting_for_events;
57 static SVMutex* waiting_for_events_mu;
62 any->counter = counter;
63 any->parameter =
new char[strlen(parameter) + 1];
64 strcpy(any->parameter, parameter);
79 #ifndef GRAPHICS_DISABLED 80 void* ScrollView::MessageReceiver(
void* a) {
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';
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);
188 {255, 255, 255, 255},
197 {128, 128, 255, 255},
201 {192, 192, 255, 255},
204 {255, 128, 128, 255},
208 {192, 192, 128, 255},
213 {192, 255, 192, 255},
215 {192, 192, 192, 255},
218 {128, 128, 128, 255},
223 {255, 192, 192, 255},
228 {255, 192, 128, 255},
242 SVNetwork* ScrollView::stream_ =
nullptr;
243 int ScrollView::nr_created_windows_ = 0;
244 int ScrollView::image_index_ = 0;
248 int y_size,
int x_canvas_size,
int y_canvas_size,
249 bool y_axis_reversed,
const char* server_name) {
250 Initialize(name, x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size,
251 y_axis_reversed, server_name);}
255 int y_size,
int x_canvas_size,
int y_canvas_size,
256 bool y_axis_reversed) {
257 Initialize(name, x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size,
258 y_axis_reversed,
"localhost");
263 int y_size,
int x_canvas_size,
int y_canvas_size) {
264 Initialize(name, x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size,
269 void ScrollView::Initialize(
const char* name,
int x_pos,
int y_pos,
int x_size,
270 int y_size,
int x_canvas_size,
int y_canvas_size,
271 bool y_axis_reversed,
const char* server_name) {
274 if (stream_ ==
nullptr) {
275 nr_created_windows_ = 0;
277 waiting_for_events_mu =
new SVMutex();
280 "svmain = luajava.bindClass('com.google.scrollview.ScrollView')\n");
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_) {
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);
314 SendRawMessage(message);
320 void* ScrollView::StartEventHandler(
void* a) {
326 sv->semaphore_->Wait();
334 if (sv->event_table_[i] !=
nullptr &&
335 (serial < 0 || sv->event_table_[i]->counter < serial)) {
336 new_event = sv->event_table_[i];
337 serial = sv->event_table_[i]->
counter;
342 if (new_event !=
nullptr) {
343 sv->event_table_[k] =
nullptr;
344 sv->mutex_->Unlock();
345 if (sv->event_handler_ !=
nullptr) { sv->event_handler_->Notify(new_event); }
348 sv->event_handler_ended_ =
true;
352 }
else { sv->mutex_->Unlock(); }
354 }
while (sv !=
nullptr);
357 #endif // GRAPHICS_DISABLED 360 #ifndef GRAPHICS_DISABLED 362 if (svmap[window_id_] !=
nullptr) {
365 SendMsg(
"destroy()");
370 svmap[window_id_] =
nullptr;
375 while (!event_handler_ended_)
383 for (
auto & i : event_table_) {
386 #endif // GRAPHICS_DISABLED 389 #ifndef GRAPHICS_DISABLED 397 va_start(args, format);
398 vsnprintf(message,
sizeof(message), format, args);
402 snprintf(form,
sizeof(form),
"w%u:%s\n", window_id_, message);
415 event_handler_ = listener;
418 void ScrollView::Signal() {
419 semaphore_->Signal();
422 void ScrollView::SetEvent(
SVEvent* svevent) {
431 delete event_table_[specific->
type];
434 event_table_[specific->
type] = specific;
446 std::pair<ScrollView*, SVEventType> ea(
this, type);
447 waiting_for_events_mu->
Lock();
448 waiting_for_events[ea] = std::pair<SVSemaphore*, SVEvent*> (sem, (
SVEvent*)
nullptr);
449 waiting_for_events_mu->
Unlock();
454 waiting_for_events_mu->
Lock();
455 SVEvent* ret = waiting_for_events[ea].second;
456 waiting_for_events.erase(ea);
458 waiting_for_events_mu->
Unlock();
468 waiting_for_events_mu->
Lock();
469 waiting_for_events[ea] = std::pair<SVSemaphore*, SVEvent*> (sem, (
SVEvent*)
nullptr);
470 waiting_for_events_mu->
Unlock();
475 waiting_for_events_mu->
Lock();
476 SVEvent* ret = waiting_for_events[ea].second;
477 waiting_for_events.erase(ea);
478 waiting_for_events_mu->
Unlock();
483 void ScrollView::SendPolygon() {
484 if (!points_->empty) {
485 points_->empty =
true;
486 int length = points_->xcoords.size();
491 SendMsg(
"drawLine(%d,%d,%d,%d)",
492 points_->xcoords[0], points_->ycoords[0],
493 points_->xcoords[1], points_->ycoords[1]);
494 }
else if (length > 2) {
496 SendMsg(
"createPolyline(%d)", length);
498 std::string decimal_coords;
499 for (
int i = 0; i < length; ++i) {
501 points_->xcoords[i], points_->ycoords[i]);
502 decimal_coords += coordpair;
504 decimal_coords +=
'\n';
505 SendRawMessage(decimal_coords.c_str());
506 SendMsg(
"drawPolyline()");
508 points_->xcoords.clear();
509 points_->ycoords.clear();
526 points_->xcoords.push_back(x);
527 points_->ycoords.push_back(TranslateYCoordinate(y));
528 points_->empty =
false;
533 if (!points_->xcoords.empty() && x1 == points_->xcoords.back() &&
534 TranslateYCoordinate(y1) == points_->ycoords.back()) {
537 }
else if (!points_->xcoords.empty() && x2 == points_->xcoords.back() &&
538 TranslateYCoordinate(y2) == points_->ycoords.back()) {
550 if (visible) { SendMsg(
"setVisible(true)");
551 }
else { SendMsg(
"setVisible(false)"); }
556 if (b) { SendMsg(
"setAlwaysOnTop(true)");
557 }
else { SendMsg(
"setAlwaysOnTop(false)"); }
565 va_start(args, format);
566 vsnprintf(message,
sizeof(message), format, args);
570 snprintf(form,
sizeof(form),
"w%u:%s", window_id_, message);
572 char* esc = AddEscapeChars(form);
573 SendMsg(
"addMessage(\"%s\")", esc);
579 SendMsg(
"addMessageBox()");
584 SendRawMessage(
"svmain:exit()");
595 SendMsg(
"setStrokeWidth(%f)", width);
601 if (x1 == x2 && y1 == y2)
603 SendMsg(
"drawRectangle(%d,%d,%d,%d)",
604 x1, TranslateYCoordinate(y1), x2, TranslateYCoordinate(y2));
610 SendMsg(
"drawEllipse(%d,%d,%u,%u)",
611 x1, TranslateYCoordinate(y1), width, height);
616 SendMsg(
"pen(%d,%d,%d)", red, green, blue);
621 SendMsg(
"pen(%d,%d,%d,%d)", red, green, blue, alpha);
626 SendMsg(
"brush(%d,%d,%d)", red, green, blue);
631 SendMsg(
"brush(%d,%d,%d,%d)", red, green, blue, alpha);
636 bool bold,
bool italic,
bool underlined) {
641 if (bold) { b =
"true";
642 }
else { b =
"false"; }
643 if (italic) { i =
"true";
644 }
else { i =
"false"; }
645 if (underlined) { u =
"true";
646 }
else { u =
"false"; }
647 SendMsg(
"textAttributes('%s',%u,%s,%s,%s)", font, pixel_size,
653 SendMsg(
"drawText(%d,%d,'%s')", x, TranslateYCoordinate(y), mystring);
658 SendMsg(
"openImage('%s')", image);
659 SendMsg(
"drawImage('%s',%d,%d)",
660 image, x_pos, TranslateYCoordinate(y_pos));
665 int cmdEvent,
bool flag) {
666 if (parent ==
nullptr) { parent =
""; }
667 if (flag) { SendMsg(
"addMenuBarItem('%s','%s',%d,true)",
668 parent, name, cmdEvent);
669 }
else { SendMsg(
"addMenuBarItem('%s','%s',%d,false)",
670 parent, name, cmdEvent); }
675 if (parent ==
nullptr) { parent =
""; }
676 SendMsg(
"addMenuBarItem('%s','%s',%d)", parent, name, cmdEvent);
681 if (parent ==
nullptr) { parent =
""; }
682 SendMsg(
"addMenuBarItem('%s','%s')", parent, name);
687 if (parent ==
nullptr) { parent =
""; }
688 SendMsg(
"addPopupMenuItem('%s','%s')", parent, name);
693 int cmdEvent,
const char* value,
const char* desc) {
694 if (parent ==
nullptr) { parent =
""; }
695 char* esc = AddEscapeChars(value);
696 char* esc2 = AddEscapeChars(desc);
697 SendMsg(
"addPopupMenuItem('%s','%s',%d,'%s','%s')", parent, name,
698 cmdEvent, esc, esc2);
711 for (
auto & iter : svmap) {
712 if (iter.second !=
nullptr)
713 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);
758 y1 = TranslateYCoordinate(y1);
759 y2 = TranslateYCoordinate(y2);
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;
770 y_pos = TranslateYCoordinate(y_pos);
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];
802 SendRawMessage(base64);
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
void Text(int x, int y, const char *mystring)
void Ellipse(int x, int y, int width, int height)
void SetVisible(bool visible)
void Image(struct Pix *image, int x_pos, int y_pos)
int ShowYesNoDialog(const char *msg)
void Rectangle(int x1, int y1, int x2, int y2)
int TranslateYCoordinate(int y)
void ZoomToRectangle(int x1, int y1, int x2, int y2)
void DrawTo(int x, int y)
char * ShowInputDialog(const char *msg)
void Lock()
Locks on a mutex.
SVEvent * AwaitEvent(SVEventType type)
std::vector< int > ycoords
static void StartThread(void *(*func)(void *), void *arg)
Create new thread.
void TextAttributes(const char *font, int pixel_size, bool bold, bool italic, bool underlined)
void AddEventHandler(SVEventHandler *listener)
Add an Event Listener to this ScrollView Window.
virtual ~SVEventHandler()
static void SendRawMessage(const char *msg)
void SendMsg(const char *msg,...)
Send a message to the server, attaching the window id.
const int kMaxIntPairSize
void Line(int x1, int y1, int x2, int y2)
void AddMessage(const char *format,...)
std::vector< int > xcoords
void Unlock()
Unlocks on a mutex.
SVEvent * AwaitEventAnyWindow()
void SetCursor(int x, int y)
void MenuItem(const char *parent, const char *name)
void PopupItem(const char *parent, const char *name)
ScrollView(const char *name, int x_pos, int y_pos, int x_size, int y_size, int x_canvas_size, int y_canvas_size)
Calls Initialize with default argument for server_name_ & y_axis_reversed.