34 #include "config_auto.h" 45 #include "allheaders.h" 54 static std::map<int, ScrollView*> svmap;
57 static std::map<std::pair<ScrollView*, SVEventType>,
58 std::pair<SVSemaphore*, SVEvent*> > waiting_for_events;
59 static SVMutex* waiting_for_events_mu;
81 #ifndef GRAPHICS_DISABLED 82 void* ScrollView::MessageReceiver(
void* a) {
87 int counter_event_id = 0;
88 char* message =
nullptr;
91 message = ScrollView::GetStream()->
Receive();
92 }
while (message ==
nullptr);
107 sscanf(message,
"%d,%d,%d,%d,%d,%d,%d,%n", &window_id, &ev_type, &cur->
x,
109 char* p = (message + n);
112 cur->
window = svmap[window_id];
114 if (cur->
window !=
nullptr) {
115 cur->
parameter =
new char[strlen(p) + 1];
131 if (cur->
window->y_axis_is_reversed_)
133 cur->
counter = counter_event_id;
137 counter_event_id += 2;
143 cur->
window->SetEvent(cur);
146 std::pair<ScrollView*, SVEventType> awaiting_list(cur->
window,
148 std::pair<ScrollView*, SVEventType> awaiting_list_any(cur->
window,
150 std::pair<ScrollView*, SVEventType> awaiting_list_any_window((
ScrollView*)
nullptr,
152 waiting_for_events_mu->
Lock();
153 if (waiting_for_events.count(awaiting_list) > 0) {
154 waiting_for_events[awaiting_list].second = cur;
155 waiting_for_events[awaiting_list].first->Signal();
156 }
else if (waiting_for_events.count(awaiting_list_any) > 0) {
157 waiting_for_events[awaiting_list_any].second = cur;
158 waiting_for_events[awaiting_list_any].first->Signal();
159 }
else if (waiting_for_events.count(awaiting_list_any_window) > 0) {
160 waiting_for_events[awaiting_list_any_window].second = cur;
161 waiting_for_events[awaiting_list_any_window].first->Signal();
166 waiting_for_events_mu->
Unlock();
180 message = ScrollView::GetStream()->
Receive();
181 }
while (message ==
nullptr);
190 {255, 255, 255, 255},
199 {128, 128, 255, 255},
203 {192, 192, 255, 255},
206 {255, 128, 128, 255},
210 {192, 192, 128, 255},
215 {192, 255, 192, 255},
217 {192, 192, 192, 255},
220 {128, 128, 128, 255},
225 {255, 192, 192, 255},
230 {255, 192, 128, 255},
244 SVNetwork* ScrollView::stream_ =
nullptr;
245 int ScrollView::nr_created_windows_ = 0;
246 int ScrollView::image_index_ = 0;
250 int y_size,
int x_canvas_size,
int y_canvas_size,
251 bool y_axis_reversed,
const char* server_name) {
252 Initialize(name, x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size,
253 y_axis_reversed, server_name);}
257 int y_size,
int x_canvas_size,
int y_canvas_size,
258 bool y_axis_reversed) {
259 Initialize(name, x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size,
260 y_axis_reversed,
"localhost");
265 int y_size,
int x_canvas_size,
int y_canvas_size) {
266 Initialize(name, x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size,
271 void ScrollView::Initialize(
const char* name,
int x_pos,
int y_pos,
int x_size,
272 int y_size,
int x_canvas_size,
int y_canvas_size,
273 bool y_axis_reversed,
const char* server_name) {
276 if (stream_ ==
nullptr) {
277 nr_created_windows_ = 0;
279 waiting_for_events_mu =
new SVMutex();
282 "svmain = luajava.bindClass('com.google.scrollview.ScrollView')\n");
287 nr_created_windows_++;
288 event_handler_ =
nullptr;
289 event_handler_ended_ =
false;
290 y_axis_is_reversed_ = y_axis_reversed;
291 y_size_ = y_canvas_size;
293 window_id_ = nr_created_windows_;
296 points_->
empty =
true;
299 svmap[window_id_] =
this;
303 event_table_[i] =
nullptr;
311 snprintf(message,
sizeof(message),
312 "w%u = luajava.newInstance('com.google.scrollview.ui" 313 ".SVWindow','%s',%u,%u,%u,%u,%u,%u,%u)\n",
314 window_id_, window_name_, window_id_,
315 x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size);
322 void* ScrollView::StartEventHandler(
void* a) {
328 sv->semaphore_->
Wait();
336 if (sv->event_table_[i] !=
nullptr &&
337 (serial < 0 || sv->event_table_[i]->counter < serial)) {
338 new_event = sv->event_table_[i];
339 serial = sv->event_table_[i]->
counter;
344 if (new_event !=
nullptr) {
345 sv->event_table_[k] =
nullptr;
347 if (sv->event_handler_ !=
nullptr) { sv->event_handler_->
Notify(new_event); }
350 sv->event_handler_ended_ =
true;
354 }
else { sv->mutex_->
Unlock(); }
356 }
while (sv !=
nullptr);
359 #endif // GRAPHICS_DISABLED 362 #ifndef GRAPHICS_DISABLED 364 if (svmap[window_id_] !=
nullptr) {
372 svmap[window_id_] =
nullptr;
377 while (!event_handler_ended_)
386 delete event_table_[i];
388 #endif // GRAPHICS_DISABLED 391 #ifndef GRAPHICS_DISABLED 399 va_start(args, format);
404 snprintf(form,
kMaxMsgSize,
"w%u:%s\n", window_id_, message);
417 event_handler_ = listener;
420 void ScrollView::Signal() {
424 void ScrollView::SetEvent(
SVEvent* svevent) {
433 delete event_table_[specific->
type];
436 event_table_[specific->
type] = specific;
448 std::pair<ScrollView*, SVEventType> ea(
this, type);
449 waiting_for_events_mu->
Lock();
450 waiting_for_events[ea] = std::pair<SVSemaphore*, SVEvent*> (sem, (
SVEvent*)
nullptr);
451 waiting_for_events_mu->
Unlock();
456 waiting_for_events_mu->
Lock();
457 SVEvent* ret = waiting_for_events[ea].second;
458 waiting_for_events.erase(ea);
460 waiting_for_events_mu->
Unlock();
470 waiting_for_events_mu->
Lock();
471 waiting_for_events[ea] = std::pair<SVSemaphore*, SVEvent*> (sem, (
SVEvent*)
nullptr);
472 waiting_for_events_mu->
Unlock();
477 waiting_for_events_mu->
Lock();
478 SVEvent* ret = waiting_for_events[ea].second;
479 waiting_for_events.erase(ea);
480 waiting_for_events_mu->
Unlock();
485 void ScrollView::SendPolygon() {
486 if (!points_->
empty) {
487 points_->
empty =
true;
488 int length = points_->
xcoords.size();
493 SendMsg(
"drawLine(%d,%d,%d,%d)",
496 }
else if (length > 2) {
498 SendMsg(
"createPolyline(%d)", length);
500 std::string decimal_coords;
501 for (
int i = 0; i < length; ++i) {
504 decimal_coords += coordpair;
506 decimal_coords +=
'\n';
530 points_->
empty =
false;
539 }
else if (!points_->
xcoords.empty() && x2 == points_->
xcoords.back() &&
552 if (visible) {
SendMsg(
"setVisible(true)");
553 }
else {
SendMsg(
"setVisible(false)"); }
558 if (b) {
SendMsg(
"setAlwaysOnTop(true)");
559 }
else {
SendMsg(
"setAlwaysOnTop(false)"); }
568 va_start(args, format);
572 snprintf(form,
kMaxMsgSize,
"w%u:%s", window_id_, message);
574 char* esc = AddEscapeChars(form);
575 SendMsg(
"addMessage(\"%s\")", esc);
597 SendMsg(
"setStrokeWidth(%f)", width);
603 if (x1 == x2 && y1 == y2)
605 SendMsg(
"drawRectangle(%d,%d,%d,%d)",
612 SendMsg(
"drawEllipse(%d,%d,%u,%u)",
618 SendMsg(
"pen(%d,%d,%d)", red, green, blue);
623 SendMsg(
"pen(%d,%d,%d,%d)", red, green, blue, alpha);
628 SendMsg(
"brush(%d,%d,%d)", red, green, blue);
633 SendMsg(
"brush(%d,%d,%d,%d)", red, green, blue, alpha);
638 bool bold,
bool italic,
bool underlined) {
643 if (bold) { b =
"true";
644 }
else { b =
"false"; }
645 if (italic) { i =
"true";
646 }
else { i =
"false"; }
647 if (underlined) { u =
"true";
648 }
else { u =
"false"; }
649 SendMsg(
"textAttributes('%s',%u,%s,%s,%s)", font, pixel_size,
660 SendMsg(
"openImage('%s')", image);
661 SendMsg(
"drawImage('%s',%d,%d)",
667 int cmdEvent,
bool flag) {
668 if (parent ==
nullptr) { parent =
""; }
669 if (flag) {
SendMsg(
"addMenuBarItem('%s','%s',%d,true)",
670 parent, name, cmdEvent);
671 }
else {
SendMsg(
"addMenuBarItem('%s','%s',%d,false)",
672 parent, name, cmdEvent); }
677 if (parent ==
nullptr) { parent =
""; }
678 SendMsg(
"addMenuBarItem('%s','%s',%d)", parent, name, cmdEvent);
683 if (parent ==
nullptr) { parent =
""; }
684 SendMsg(
"addMenuBarItem('%s','%s')", parent, name);
689 if (parent ==
nullptr) { parent =
""; }
690 SendMsg(
"addPopupMenuItem('%s','%s')", parent, name);
695 int cmdEvent,
const char* value,
const char* desc) {
696 if (parent ==
nullptr) { parent =
""; }
697 char* esc = AddEscapeChars(value);
698 char* esc2 = AddEscapeChars(desc);
699 SendMsg(
"addPopupMenuItem('%s','%s',%d,'%s','%s')", parent, name,
700 cmdEvent, esc, esc2);
713 for (std::map<int, ScrollView*>::iterator iter = svmap.begin();
714 iter != svmap.end(); ++iter) {
715 if (iter->second !=
nullptr)
716 iter->second->UpdateWindow();
723 Pen(table_colors[color][0], table_colors[color][1],
724 table_colors[color][2], table_colors[color][3]);
729 Brush(table_colors[color][0],
730 table_colors[color][1],
731 table_colors[color][2],
732 table_colors[color][3]);
737 SendMsg(
"showInputDialog(\"%s\")", msg);
741 char* p =
new char[strlen(ev->
parameter) + 1];
749 SendMsg(
"showYesNoDialog(\"%s\")", msg);
763 SendMsg(
"zoomRectangle(%d,%d,%d,%d)",
764 std::min(x1, x2), std::min(y1, y2), std::max(x1, x2), std::max(y1, y2));
771 pixWriteMem(&data, &size, image, IFF_PNG);
772 int base64_len = (size + 2) / 3 * 4;
774 SendMsg(
"readImage(%d,%d,%d)", x_pos, y_pos, base64_len);
776 const char kBase64Table[64] = {
777 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
778 'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
779 'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
780 'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
781 'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
782 'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
783 'w',
'x',
'y',
'z',
'0',
'1',
'2',
'3',
784 '4',
'5',
'6',
'7',
'8',
'9',
'+',
'/',
786 char* base64 =
new char[base64_len + 1];
787 memset(base64,
'=', base64_len);
788 base64[base64_len] =
'\0';
792 for (
size_t i = 0; i < size; ++i) {
793 int code = (data[i] >> (bits_left + 2)) | remainder;
794 base64[code_len++] = kBase64Table[code & 63];
796 remainder = data[i] << (6 - bits_left);
797 if (bits_left == 6) {
798 base64[code_len++] = kBase64Table[remainder & 63];
804 base64[code_len++] = kBase64Table[remainder & 63];
812 char* ScrollView::AddEscapeChars(
const char* input) {
813 const char* nextptr = strchr(input,
'\'');
814 const char* lastptr = input;
817 while (nextptr !=
nullptr) {
818 strncpy(message+pos, lastptr, nextptr-lastptr);
819 pos += nextptr - lastptr;
823 nextptr = strchr(nextptr+1,
'\'');
825 strcpy(message+pos, lastptr);
831 if (!y_axis_is_reversed_) {
return y;
832 }
else {
return y_size_ - y; }
835 #endif // GRAPHICS_DISABLED virtual void Notify(const SVEvent *sve)
virtual ~SVEventHandler()
void DrawTo(int x, int y)
void Unlock()
Unlocks on a mutex.
int ShowYesNoDialog(const char *msg)
void TextAttributes(const char *font, int pixel_size, bool bold, bool italic, bool underlined)
void Send(const char *msg)
Put a message in the messagebuffer to the server and try to send it.
SVEvent * AwaitEventAnyWindow()
static void StartThread(void *(*func)(void *), void *arg)
Create new thread.
void SetVisible(bool visible)
void Lock()
Locks on a mutex.
void ZoomToRectangle(int x1, int y1, int x2, int y2)
void Wait()
Wait on a semaphore.
void MenuItem(const char *parent, const char *name)
int TranslateYCoordinate(int y)
void Signal()
Signal a semaphore.
static void SendRawMessage(const char *msg)
void SetCursor(int x, int y)
void SendMsg(const char *msg,...)
Send a message to the server, attaching the window id.
const int kMaxIntPairSize
void Ellipse(int x, int y, int width, int height)
void PopupItem(const char *parent, const char *name)
SVEvent * AwaitEvent(SVEventType type)
char * ShowInputDialog(const char *msg)
void Text(int x, int y, const char *mystring)
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 AddEventHandler(SVEventHandler *listener)
Add an Event Listener to this ScrollView Window.
void Image(struct Pix *image, int x_pos, int y_pos)
std::vector< int > ycoords
std::vector< int > xcoords
void Rectangle(int x1, int y1, int x2, int y2)
void Flush()
Flush the buffer.
void Line(int x1, int y1, int x2, int y2)
void AddMessage(const char *format,...)