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;
63 any->parameter =
new char[strlen(
parameter) + 1];
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);
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;
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) {
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() {
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)",
494 }
else if (length > 2) {
496 SendMsg(
"createPolyline(%d)", length);
498 std::string decimal_coords;
499 for (
int i = 0; i < length; ++i) {
502 decimal_coords += coordpair;
504 decimal_coords +=
'\n';
528 points_->
empty =
false;
537 }
else if (!points_->
xcoords.empty() && x2 == points_->
xcoords.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);
595 SendMsg(
"setStrokeWidth(%f)", width);
601 if (x1 == x2 && y1 == y2)
603 SendMsg(
"drawRectangle(%d,%d,%d,%d)",
610 SendMsg(
"drawEllipse(%d,%d,%u,%u)",
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,
658 SendMsg(
"openImage('%s')", image);
659 SendMsg(
"drawImage('%s',%d,%d)",
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);
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 void PopupItem(const char *parent, const char *name)
void Rectangle(int x1, int y1, int x2, int y2)
void Lock()
Locks on a mutex.
void Unlock()
Unlocks on a mutex.
void ZoomToRectangle(int x1, int y1, int x2, int y2)
SVEvent * AwaitEvent(SVEventType type)
char * ShowInputDialog(const char *msg)
SVEvent * AwaitEventAnyWindow()
void SetVisible(bool visible)
static void SendRawMessage(const char *msg)
void Signal()
Signal a semaphore.
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.
void DrawTo(int x, int y)
int ShowYesNoDialog(const char *msg)
std::vector< int > ycoords
void MenuItem(const char *parent, const char *name)
void Flush()
Flush the buffer.
void Line(int x1, int y1, int x2, int y2)
static void StartThread(void *(*func)(void *), void *arg)
Create new thread.
void Image(struct Pix *image, int x_pos, int y_pos)
void Ellipse(int x, int y, int width, int height)
void AddMessage(const char *format,...)
void Wait()
Wait on a semaphore.
virtual void Notify(const SVEvent *sve)
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.
const int kMaxIntPairSize
virtual ~SVEventHandler()
void SendMsg(const char *msg,...)
Send a message to the server, attaching the window id.
int TranslateYCoordinate(int y)
void Text(int x, int y, const char *mystring)
std::vector< int > xcoords
void SetCursor(int x, int y)
void Send(const char *msg)
Put a message in the messagebuffer to the server and try to send it.