📄 scrollview.cpp
字号:
SVEvent* ret = waiting_for_events[ea].second; waiting_for_events.erase(ea); mutex_waiting->Unlock(); return ret;}// Block until any event on any window is received.// No event is returned here!SVEvent* ScrollView::AwaitEventAnyWindow() { // Initialize the waiting semaphore. SVSemaphore* sem = new SVSemaphore(); std::pair<ScrollView*, SVEventType> ea(NULL, SVET_ANY); mutex_waiting->Lock(); waiting_for_events[ea] = std::pair<SVSemaphore*, SVEvent*> (sem, NULL); mutex_waiting->Unlock(); // Wait on it. stream_->Flush(); sem->Wait(); // Process the event we got woken up for (its in waiting_for_events pair). mutex_waiting->Lock(); SVEvent* ret = waiting_for_events[ea].second; waiting_for_events.erase(ea); mutex_waiting->Unlock(); return ret;}// Send the current buffered polygon (if any) and clear it.void ScrollView::SendPolygon() { if (!points_->empty) { points_->empty = true; // Allows us to use SendMsg. int length = points_->xcoords.size(); // length == 1 corresponds to 2 SetCursors in a row and only the // last setCursor has any effect. if (length == 2) { // An isolated line! SendMsg("drawLine(%d,%d,%d,%d)", points_->xcoords[0], points_->ycoords[0], points_->xcoords[1], points_->ycoords[1]); } else if (length > 2) { // A polyline. SendMsg("createPolyline(%d)", length); char coordpair[kMaxIntPairSize]; std::string decimal_coords; for (int i = 0; i < length; ++i) { snprintf(coordpair, kMaxIntPairSize, "%d,%d,", points_->xcoords[i], points_->ycoords[i]); decimal_coords += coordpair; } decimal_coords += '\n'; SendRawMessage(decimal_coords.c_str()); SendMsg("drawPolyline()"); } points_->xcoords.clear(); points_->ycoords.clear(); }}/******************************************************************************** LUA "API" functions.*******************************************************************************/// Sets the position from which to draw to (x,y).void ScrollView::SetCursor(int x, int y) { SendPolygon(); DrawTo(x, y);}// Draws from the current position to (x,y) and sets the new position to it.void ScrollView::DrawTo(int x, int y) { points_->xcoords.push_back(x); points_->ycoords.push_back(TranslateYCoordinate(y)); points_->empty = false;}// Draw a line using the current pen color.void ScrollView::Line(int x1, int y1, int x2, int y2) { if (!points_->xcoords.empty() && x1 == points_->xcoords.back() && TranslateYCoordinate(y1) == points_->ycoords.back()) { // We are already at x1, y1, so just draw to x2, y2. DrawTo(x2, y2); } else if (!points_->xcoords.empty() && x2 == points_->xcoords.back() && TranslateYCoordinate(y2) == points_->ycoords.back()) { // We are already at x2, y2, so just draw to x1, y1. DrawTo(x1, y1); } else { // This is a new line. SetCursor(x1, y1); DrawTo(x2, y2); }}// Set the visibility of the window.void ScrollView::SetVisible(bool visible) { if (visible) { SendMsg("setVisible(true)"); } else { SendMsg("setVisible(false)"); }}// Set the alwaysOnTop flag.void ScrollView::AlwaysOnTop(bool b) { if (b) { SendMsg("setAlwaysOnTop(true)"); } else { SendMsg("setAlwaysOnTop(false)"); }}// Adds a message entry to the message box.void ScrollView::AddMessage(const char* format, ...) { va_list args; char message[kMaxMsgSize]; char form[kMaxMsgSize]; va_start(args, format); // variable list vsnprintf(message, kMaxMsgSize, format, args); va_end(args); snprintf(form, kMaxMsgSize, "w%u:%s", window_id_, message); char* esc = AddEscapeChars(form); SendMsg("addMessage(\"%s\")", esc); delete[] esc;}// Set a messagebox.void ScrollView::AddMessageBox() { SendMsg("addMessageBox()");}// Exit the client completely (and notify the server of it).void ScrollView::Exit() { SendRawMessage("svmain:exit()"); exit(0);}// Clear the canvas.void ScrollView::Clear() { SendMsg("clear()");}// Set the stroke width.void ScrollView::Stroke(float width) { SendMsg("setStrokeWidth(%f)", width);}// Draw a rectangle using the current pen color.// The rectangle is filled with the current brush color.void ScrollView::Rectangle(int x1, int y1, int x2, int y2) { SendMsg("drawRectangle(%d,%d,%d,%d)", x1, TranslateYCoordinate(y1), x2, TranslateYCoordinate(y2));}// Draw an ellipse using the current pen color.// The ellipse is filled with the current brush color.void ScrollView::Ellipse(int x1, int y1, int width, int height) { SendMsg("drawEllipse(%d,%d,%u,%u)", x1, TranslateYCoordinate(y1), width, height);}// Set the pen color to the given RGB values.void ScrollView::Pen(int red, int green, int blue) { SendMsg("pen(%d,%d,%d)", red, green, blue);}// Set the pen color to the given RGB values.void ScrollView::Pen(int red, int green, int blue, int alpha) { SendMsg("pen(%d,%d,%d,%d)", red, green, blue, alpha);}// Set the brush color to the given RGB values.void ScrollView::Brush(int red, int green, int blue) { SendMsg("brush(%d,%d,%d)", red, green, blue);}// Set the brush color to the given RGB values.void ScrollView::Brush(int red, int green, int blue, int alpha) { SendMsg("brush(%d,%d,%d,%d)", red, green, blue, alpha);}// Set the attributes for future Text(..) calls.void ScrollView::TextAttributes(const char* font, int pixel_size, bool bold, bool italic, bool underlined) { const char* b; const char* i; const char* u; if (bold) { b = "true"; } else { b = "false"; } if (italic) { i = "true"; } else { i = "false"; } if (underlined) { u = "true"; } else { u = "false"; } SendMsg("textAttributes('%s',%u,%s,%s,%s)", font, pixel_size, b, i, u);}// Draw text at the given coordinates.void ScrollView::Text(int x, int y, const char* mystring) { SendMsg("drawText(%d,%d,'%s')", x, TranslateYCoordinate(y), mystring);}// Open and draw an image given a name at (x,y).void ScrollView::Image(const char* image, int x_pos, int y_pos) { SendMsg("openImage('%s')", image); SendMsg("drawImage('%s',%d,%d)", image, x_pos, TranslateYCoordinate(y_pos));}// Add new checkboxmenuentry to menubar.void ScrollView::MenuItem(const char* parent, const char* name, int cmdEvent, bool flag) { if (parent == NULL) { parent = ""; } if (flag) { SendMsg("addMenuBarItem('%s','%s',%d,true)", parent, name, cmdEvent); } else { SendMsg("addMenuBarItem('%s','%s',%d,false)", parent, name, cmdEvent); }}// Add new menuentry to menubar.void ScrollView::MenuItem(const char* parent, const char* name, int cmdEvent) { if (parent == NULL) { parent = ""; } SendMsg("addMenuBarItem('%s','%s',%d)", parent, name, cmdEvent);}// Add new submenu to menubar.void ScrollView::MenuItem(const char* parent, const char* name) { if (parent == NULL) { parent = ""; } SendMsg("addMenuBarItem('%s','%s')", parent, name);}// Add new submenu to popupmenu.void ScrollView::PopupItem(const char* parent, const char* name) { if (parent == NULL) { parent = ""; } SendMsg("addPopupMenuItem('%s','%s')", parent, name);}// Add new submenuentry to popupmenu.void ScrollView::PopupItem(const char* parent, const char* name, int cmdEvent, const char* value, const char* desc) { if (parent == NULL) { parent = ""; } char* esc = AddEscapeChars(value); char* esc2 = AddEscapeChars(desc); SendMsg("addPopupMenuItem('%s','%s',%d,'%s','%s')", parent, name, cmdEvent, esc, esc2); delete[] esc; delete[] esc2;}// Send an update message for a single window.void ScrollView::UpdateWindow() { SendMsg("update()");}// Note: this is an update to all windowsvoid ScrollView::Update() { for (std::map<int, ScrollView*>::iterator iter = svmap.begin(); iter != svmap.end(); ++iter) { if (iter->second != NULL) iter->second->UpdateWindow(); }}// Set the pen color, using an enum value (e.g. ScrollView::ORANGE)void ScrollView::Pen(Color color) { Pen(table_colors[color][0], table_colors[color][1], table_colors[color][2], table_colors[color][3]);}// Set the brush color, using an enum value (e.g. ScrollView::ORANGE)void ScrollView::Brush(Color color) { Brush(table_colors[color][0], table_colors[color][1], table_colors[color][2], table_colors[color][3]);}// Shows a modal Input Dialog which can return any kind of Stringchar* ScrollView::ShowInputDialog(const char* msg) { SendMsg("showInputDialog(\"%s\")", msg); SVEvent* ev; // wait till an input event (all others are thrown away) ev = AwaitEvent(SVET_INPUT); char* p = new char[strlen(ev->parameter) + 1]; strncpy(p, ev->parameter, strlen(ev->parameter)); p[strlen(ev->parameter)] = '\0'; delete ev; return p;}// Shows a modal Yes/No Dialog which will return 'y' or 'n'int ScrollView::ShowYesNoDialog(const char* msg) { SendMsg("showYesNoDialog(\"%s\")", msg); SVEvent* ev; // Wait till an input event (all others are thrown away) ev = AwaitEvent(SVET_INPUT); int a = ev->parameter[0]; delete ev; return a;}// Zoom the window to the rectangle given upper left corner and// lower right corner.void ScrollView::ZoomToRectangle(int x1, int y1, int x2, int y2) { y1 = TranslateYCoordinate(y1); y2 = TranslateYCoordinate(y2); SendMsg("zoomRectangle(%d,%d,%d,%d)", MIN(x1, x2), MIN(y1, y2), MAX(x1, x2), MAX(y1, y2));}#ifdef HAVE_LIBLEPT// Send an image of type PIX.void ScrollView::Image(PIX* image, int x_pos, int y_pos) { int width = image->w; int height = image->h; l_uint32 bpp = image->d; // PIX* do not have a unique identifier/name associated, so name them "lept". SendMsg("createImage('%s',%d,%d,%d)", "lept", width, height, bpp); if (bpp == 32) { Transfer32bppImage(image); } else if (bpp == 8) { TransferGrayImage(image); } else if (bpp == 1) { TransferBinaryImage(image); } // PIX* do not have a unique identifier/name associated, so name them "lept". SendMsg("drawImage('%s',%d,%d)", "lept", x_pos, y_pos);}// Sends each pixel as hex value like html, e.g. #00FF00 for green.void ScrollView::Transfer32bppImage(PIX* image) { int ppL = pixGetWidth(image); int h = pixGetHeight(image); int wpl = pixGetWpl(image); int transfer_size= ppL * 7 + 2; char* pixel_data = new char[transfer_size]; for (int y = 0; y < h; ++y) { l_uint32* data = pixGetData(image) + y*wpl; for (int x = 0; x < ppL; ++x, ++data) { snprintf(&pixel_data[x*7], 7, "#%.2x%.2x%.2x", GET_DATA_BYTE(data, COLOR_RED), GET_DATA_BYTE(data, COLOR_GREEN), GET_DATA_BYTE(data, COLOR_BLUE)); } pixel_data[transfer_size - 2] = '\n'; pixel_data[transfer_size - 1] = '\0'; SendRawMessage(pixel_data); } delete[] pixel_data;}// Sends for each pixel either '1' or '0'.void ScrollView::TransferGrayImage(PIX* image) { char* pixel_data = new char[image->w * 2 + 2]; for (int y = 0; y < image->h; y++) { l_uint32* data = pixGetData(image) + y * pixGetWpl(image); for (int x = 0; x < image->w; x++) { snprintf(&pixel_data[x*2], 2, "%.2x", (GET_DATA_BYTE(data, x))); pixel_data[image->w * 2] = '\n'; pixel_data[image->w * 2 + 1] = '\0'; SendRawMessage(pixel_data); } } delete [] pixel_data;}// Sends for each pixel either '1' or '0'.void ScrollView::TransferBinaryImage(PIX* image) { char* pixel_data = new char[image->w + 2]; for (int y = 0; y < image->h; y++) { l_uint32* data = pixGetData(image) + y * pixGetWpl(image); for (int x = 0; x < image->w; x++) { if (GET_DATA_BIT(data, x)) pixel_data[x] = '1'; else pixel_data[x] = '0'; } pixel_data[image->w] = '\n'; pixel_data[image->w + 1] = '\0'; SendRawMessage(pixel_data); } delete [] pixel_data;}#endif// Escapes the ' character with a \, so it can be processed by LUA.// Note: The caller will have to make sure he deletes the newly allocated item.char* ScrollView::AddEscapeChars(const char* input) { const char* nextptr = strchr(input, '\''); const char* lastptr = input; char* message = new char[kMaxMsgSize]; int pos = 0; while (nextptr != NULL) { strncpy(message+pos, lastptr, nextptr-lastptr); pos += nextptr - lastptr; message[pos] = '\\'; pos += 1; lastptr = nextptr; nextptr = strchr(nextptr+1, '\''); } strncpy(message+pos, lastptr, strlen(lastptr)); message[pos+strlen(lastptr)] = '\0'; return message;}// Inverse the Y axis if the coordinates are actually inversed.int ScrollView::TranslateYCoordinate(int y) { if (!y_axis_is_reversed_) { return y; } else { return y_size_ - y; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -