/src/tesseract/src/viewer/scrollview.h
Line | Count | Source |
1 | | /////////////////////////////////////////////////////////////////////// |
2 | | // File: scrollview.h |
3 | | // Description: ScrollView |
4 | | // Author: Joern Wanke |
5 | | // |
6 | | // (C) Copyright 2007, Google Inc. |
7 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
8 | | // you may not use this file except in compliance with the License. |
9 | | // You may obtain a copy of the License at |
10 | | // http://www.apache.org/licenses/LICENSE-2.0 |
11 | | // Unless required by applicable law or agreed to in writing, software |
12 | | // distributed under the License is distributed on an "AS IS" BASIS, |
13 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | | // See the License for the specific language governing permissions and |
15 | | // limitations under the License. |
16 | | // |
17 | | /////////////////////////////////////////////////////////////////////// |
18 | | // |
19 | | // ScrollView is designed as an UI which can be run remotely. This is the |
20 | | // client code for it, the server part is written in java. The client consists |
21 | | // mainly of 2 parts: |
22 | | // The "core" ScrollView which sets up the remote connection, |
23 | | // takes care of event handling etc. |
24 | | // The other part of ScrollView consists of predefined API calls through LUA, |
25 | | // which can basically be used to get a zoomable canvas in which it is possible |
26 | | // to draw lines, text etc. |
27 | | // Technically, thanks to LUA, its even possible to bypass the here defined LUA |
28 | | // API calls at all and generate a java user interface from scratch (or |
29 | | // basically generate any kind of java program, possibly even dangerous ones). |
30 | | |
31 | | #ifndef TESSERACT_VIEWER_SCROLLVIEW_H_ |
32 | | #define TESSERACT_VIEWER_SCROLLVIEW_H_ |
33 | | |
34 | | #include "image.h" |
35 | | |
36 | | #include <tesseract/export.h> |
37 | | |
38 | | #include <cstdio> |
39 | | #include <memory> |
40 | | #include <mutex> |
41 | | #include <string> |
42 | | |
43 | | namespace tesseract { |
44 | | |
45 | | #if !defined(__GNUC__) && !defined(__attribute__) |
46 | | # define __attribute__(attr) // compiler without support for __attribute__ |
47 | | #endif |
48 | | |
49 | | class ScrollView; |
50 | | class SVNetwork; |
51 | | class SVSemaphore; |
52 | | struct SVPolyLineBuffer; |
53 | | |
54 | | enum SVEventType { |
55 | | SVET_DESTROY, // Window has been destroyed by user. |
56 | | SVET_EXIT, // User has destroyed the last window by clicking on the 'X'. |
57 | | SVET_CLICK, // Left button pressed. |
58 | | SVET_SELECTION, // Left button selection. |
59 | | SVET_INPUT, // There is some input (single key or a whole string). |
60 | | SVET_MOUSE, // The mouse has moved with a button pressed. |
61 | | SVET_MOTION, // The mouse has moved with no button pressed. |
62 | | SVET_HOVER, // The mouse has stayed still for a second. |
63 | | SVET_POPUP, // A command selected through a popup menu. |
64 | | SVET_MENU, // A command selected through the menubar. |
65 | | SVET_ANY, // Any of the above. |
66 | | |
67 | | SVET_COUNT // Array sizing. |
68 | | }; |
69 | | |
70 | | struct SVEvent { |
71 | | std::unique_ptr<SVEvent> copy() const; |
72 | | SVEventType type = SVET_DESTROY; // What kind of event. |
73 | | ScrollView *window = nullptr; // Window event relates to. |
74 | | std::string parameter; // Any string that might have been passed as argument. |
75 | | int x = 0; // Coords of click or selection. |
76 | | int y = 0; |
77 | | int x_size = 0; // Size of selection. |
78 | | int y_size = 0; |
79 | | int command_id = 0; // The ID of the possibly associated event (e.g. MENU) |
80 | | int counter = 0; // Used to detect which kind of event to process next. |
81 | | |
82 | | SVEvent() = default; |
83 | | SVEvent(const SVEvent &); |
84 | | SVEvent &operator=(const SVEvent &); |
85 | | }; |
86 | | |
87 | | // The SVEventHandler class is used for Event handling: If you register your |
88 | | // class as SVEventHandler to a ScrollView Window, the SVEventHandler will be |
89 | | // called whenever an appropriate event occurs. |
90 | | class TESS_API SVEventHandler { |
91 | | public: |
92 | | virtual ~SVEventHandler(); |
93 | | |
94 | | // Gets called by the SV Window. Does nothing on default, overwrite this |
95 | | // to implement the desired behaviour |
96 | 0 | virtual void Notify([[maybe_unused]] const SVEvent *sve) { |
97 | 0 | } |
98 | | }; |
99 | | |
100 | | // The ScrollView class provides the external API to the scrollviewer process. |
101 | | // The scrollviewer process manages windows and displays images, graphics and |
102 | | // text while allowing the user to zoom and scroll the windows arbitrarily. |
103 | | // Each ScrollView class instance represents one window, and stuff is drawn in |
104 | | // the window through method calls on the class. The constructor is used to |
105 | | // create the class instance (and the window). |
106 | | class TESS_API ScrollView { |
107 | | public: |
108 | | // Color enum for pens and brushes. |
109 | | enum Color { |
110 | | NONE, |
111 | | BLACK, |
112 | | WHITE, |
113 | | RED, |
114 | | YELLOW, |
115 | | GREEN, |
116 | | CYAN, |
117 | | BLUE, |
118 | | MAGENTA, |
119 | | AQUAMARINE, |
120 | | DARK_SLATE_BLUE, |
121 | | LIGHT_BLUE, |
122 | | MEDIUM_BLUE, |
123 | | MIDNIGHT_BLUE, |
124 | | NAVY_BLUE, |
125 | | SKY_BLUE, |
126 | | SLATE_BLUE, |
127 | | STEEL_BLUE, |
128 | | CORAL, |
129 | | BROWN, |
130 | | SANDY_BROWN, |
131 | | GOLD, |
132 | | GOLDENROD, |
133 | | DARK_GREEN, |
134 | | DARK_OLIVE_GREEN, |
135 | | FOREST_GREEN, |
136 | | LIME_GREEN, |
137 | | PALE_GREEN, |
138 | | YELLOW_GREEN, |
139 | | LIGHT_GREY, |
140 | | DARK_SLATE_GREY, |
141 | | DIM_GREY, |
142 | | GREY, |
143 | | KHAKI, |
144 | | MAROON, |
145 | | ORANGE, |
146 | | ORCHID, |
147 | | PINK, |
148 | | PLUM, |
149 | | INDIAN_RED, |
150 | | ORANGE_RED, |
151 | | VIOLET_RED, |
152 | | SALMON, |
153 | | TAN, |
154 | | TURQUOISE, |
155 | | DARK_TURQUOISE, |
156 | | VIOLET, |
157 | | WHEAT, |
158 | | GREEN_YELLOW // Make sure this one is last. |
159 | | }; |
160 | | |
161 | | ~ScrollView(); |
162 | | |
163 | | #ifndef GRAPHICS_DISABLED |
164 | | |
165 | | // Create a window. The pixel size of the window may be 0,0, in which case |
166 | | // a default size is selected based on the size of your canvas. |
167 | | // The canvas may not be 0,0 in size! |
168 | | ScrollView(const char *name, int x_pos, int y_pos, int x_size, int y_size, int x_canvas_size, |
169 | | int y_canvas_size); |
170 | | // With a flag whether the x axis is reversed. |
171 | | ScrollView(const char *name, int x_pos, int y_pos, int x_size, int y_size, int x_canvas_size, |
172 | | int y_canvas_size, bool y_axis_reversed); |
173 | | // Connect to a server other than localhost. |
174 | | ScrollView(const char *name, int x_pos, int y_pos, int x_size, int y_size, int x_canvas_size, |
175 | | int y_canvas_size, bool y_axis_reversed, const char *server_name); |
176 | | /******************************************************************************* |
177 | | * Event handling |
178 | | * To register as listener, the class has to derive from the SVEventHandler |
179 | | * class, which consists of a notifyMe(SVEvent*) function that should be |
180 | | * overwritten to process the event the way you want. |
181 | | *******************************************************************************/ |
182 | | |
183 | | // Add an Event Listener to this ScrollView Window. |
184 | | void AddEventHandler(SVEventHandler *listener); |
185 | | |
186 | | // Block until an event of the given type is received. |
187 | | std::unique_ptr<SVEvent> AwaitEvent(SVEventType type); |
188 | | |
189 | | /******************************************************************************* |
190 | | * Getters and Setters |
191 | | *******************************************************************************/ |
192 | | |
193 | | // Returns the title of the window. |
194 | | const char *GetName() { |
195 | | return window_name_; |
196 | | } |
197 | | |
198 | | // Returns the unique ID of the window. |
199 | | int GetId() { |
200 | | return window_id_; |
201 | | } |
202 | | |
203 | | /******************************************************************************* |
204 | | * API functions for LUA calls |
205 | | * the implementations for these can be found in svapi.cc |
206 | | * (keep in mind that the window is actually created through the ScrollView |
207 | | * constructor, so this is not listed here) |
208 | | *******************************************************************************/ |
209 | | |
210 | | // Draw an image on (x,y). |
211 | | void Draw(Image image, int x_pos, int y_pos); |
212 | | |
213 | | // Flush buffers and update display. |
214 | | static void Update(); |
215 | | |
216 | | // Exit the program. |
217 | | static void Exit(); |
218 | | |
219 | | // Update the contents of a specific window. |
220 | | void UpdateWindow(); |
221 | | |
222 | | // Erase all content from the window, but do not destroy it. |
223 | | void Clear(); |
224 | | |
225 | | // Set pen color with an enum. |
226 | | void Pen(Color color); |
227 | | |
228 | | // Set pen color to RGB (0-255). |
229 | | void Pen(int red, int green, int blue); |
230 | | |
231 | | // Set pen color to RGBA (0-255). |
232 | | void Pen(int red, int green, int blue, int alpha); |
233 | | |
234 | | // Set brush color with an enum. |
235 | | void Brush(Color color); |
236 | | |
237 | | // Set brush color to RGB (0-255). |
238 | | void Brush(int red, int green, int blue); |
239 | | |
240 | | // Set brush color to RGBA (0-255). |
241 | | void Brush(int red, int green, int blue, int alpha); |
242 | | |
243 | | // Set attributes for future text, like font name (e.g. |
244 | | // "Times New Roman"), font size etc.. |
245 | | // Note: The underlined flag is currently not supported |
246 | | void TextAttributes(const char *font, int pixel_size, bool bold, bool italic, bool underlined); |
247 | | |
248 | | // Draw line from (x1,y1) to (x2,y2) with the current pencolor. |
249 | | void Line(int x1, int y1, int x2, int y2); |
250 | | |
251 | | // Set the stroke width of the pen. |
252 | | void Stroke(float width); |
253 | | |
254 | | // Draw a rectangle given upper left corner and lower right corner. |
255 | | // The current pencolor is used as outline, the brushcolor to fill the shape. |
256 | | void Rectangle(int x1, int y1, int x2, int y2); |
257 | | |
258 | | // Draw an ellipse centered on (x,y). |
259 | | // The current pencolor is used as outline, the brushcolor to fill the shape. |
260 | | void Ellipse(int x, int y, int width, int height); |
261 | | |
262 | | // Draw text with the current pencolor |
263 | | void Text(int x, int y, const char *mystring); |
264 | | |
265 | | // Draw an image from a local filename. This should be faster than |
266 | | // createImage. WARNING: This only works on a local machine. This also only |
267 | | // works image types supported by java (like bmp,jpeg,gif,png) since the image |
268 | | // is opened by the server. |
269 | | void Draw(const char *image, int x_pos, int y_pos); |
270 | | |
271 | | // Set the current position to draw from (x,y). In conjunction with... |
272 | | void SetCursor(int x, int y); |
273 | | |
274 | | // ...this function, which draws a line from the current to (x,y) and then |
275 | | // sets the new position to the new (x,y), this can be used to easily draw |
276 | | // polygons using vertices |
277 | | void DrawTo(int x, int y); |
278 | | |
279 | | // Set the SVWindow visible/invisible. |
280 | | void SetVisible(bool visible); |
281 | | |
282 | | // Set the SVWindow always on top or not always on top. |
283 | | void AlwaysOnTop(bool b); |
284 | | |
285 | | // Shows a modal dialog with "msg" as question and returns 'y' or 'n'. |
286 | | int ShowYesNoDialog(const char *msg); |
287 | | |
288 | | // Shows a modal dialog with "msg" as question and returns a char* string. |
289 | | // Constraint: As return, only words (e.g. no whitespaces etc.) are allowed. |
290 | | char *ShowInputDialog(const char *msg); |
291 | | |
292 | | // Adds a messagebox to the SVWindow. This way, it can show the messages... |
293 | | void AddMessageBox(); |
294 | | |
295 | | // ...which can be added by this command. |
296 | | // This is intended as an "debug" output window. |
297 | | void AddMessage(const char *message); |
298 | | void AddMessageF(const char *format, ...) __attribute__((format(printf, 2, 3))); |
299 | | |
300 | | // Zoom the window to the rectangle given upper left corner and |
301 | | // lower right corner. |
302 | | void ZoomToRectangle(int x1, int y1, int x2, int y2); |
303 | | |
304 | | // Custom messages (manipulating java code directly) can be send through this. |
305 | | // Send a message to the server and attach the Id of the corresponding window. |
306 | | // Note: This should only be called if you are know what you are doing, since |
307 | | // you are fiddling with the Java objects on the server directly. Calling |
308 | | // this just for fun will likely break your application! |
309 | | // It is public so you can actually take use of the LUA functionalities, but |
310 | | // be careful! |
311 | | void SendMsg(const char* msg, ...) __attribute__((format(printf, 2, 3))); |
312 | | |
313 | | // Custom messages (manipulating java code directly) can be send through this. |
314 | | // Send a message to the server without adding the |
315 | | // window id. Used for global events like Exit(). |
316 | | // Note: This should only be called if you are know what you are doing, since |
317 | | // you are fiddling with the Java objects on the server directly. Calling |
318 | | // this just for fun will likely break your application! |
319 | | // It is public so you can actually take use of the LUA functionalities, but |
320 | | // be careful! |
321 | | static void SendRawMessage(const char *msg); |
322 | | |
323 | | /******************************************************************************* |
324 | | * Add new menu entries to parent. If parent is "", the entry gets added to |
325 | | *the main menubar (toplevel). |
326 | | *******************************************************************************/ |
327 | | // This adds a new submenu to the menubar. |
328 | | void MenuItem(const char *parent, const char *name); |
329 | | |
330 | | // This adds a new (normal) menu entry with an associated eventID, which |
331 | | // should be unique among menubar eventIDs. |
332 | | void MenuItem(const char *parent, const char *name, int cmdEvent); |
333 | | |
334 | | // This adds a new checkbox entry, which might initially be flagged. |
335 | | void MenuItem(const char *parent, const char *name, int cmdEvent, bool flagged); |
336 | | |
337 | | // This adds a new popup submenu to the popup menu. If parent is "", the entry |
338 | | // gets added at "toplevel" popupmenu. |
339 | | void PopupItem(const char *parent, const char *name); |
340 | | |
341 | | // This adds a new popup entry with the associated eventID, which should be |
342 | | // unique among popup eventIDs. |
343 | | // If value and desc are given, on a click the server will ask you to modify |
344 | | // the value and return the new value. |
345 | | void PopupItem(const char *parent, const char *name, int cmdEvent, const char *value, |
346 | | const char *desc); |
347 | | |
348 | | // Returns the correct Y coordinate for a window, depending on whether it |
349 | | // might have to be flipped (by ySize). |
350 | | int TranslateYCoordinate(int y); |
351 | | |
352 | | char Wait(); |
353 | | |
354 | | private: |
355 | | // Transfers a binary Image. |
356 | | void TransferBinaryImage(Image image); |
357 | | // Transfers a gray scale Image. |
358 | | void TransferGrayImage(Image image); |
359 | | // Transfers a 32-Bit Image. |
360 | | void Transfer32bppImage(Image image); |
361 | | |
362 | | // Sets up ScrollView, depending on the variables from the constructor. |
363 | | void Initialize(const char *name, int x_pos, int y_pos, int x_size, int y_size, int x_canvas_size, |
364 | | int y_canvas_size, bool y_axis_reversed, const char *server_name); |
365 | | |
366 | | // Send the current buffered polygon (if any) and clear it. |
367 | | void SendPolygon(); |
368 | | |
369 | | // Start the message receiving thread. |
370 | | static void MessageReceiver(); |
371 | | |
372 | | // Place an event into the event_table (synchronized). |
373 | | void SetEvent(const SVEvent *svevent); |
374 | | |
375 | | // Wake up the semaphore. |
376 | | void Signal(); |
377 | | |
378 | | // Returns the unique, shared network stream. |
379 | | static SVNetwork &GetStream() { |
380 | | return *stream_; |
381 | | } |
382 | | |
383 | | // Starts a new event handler. |
384 | | // Called asynchronously whenever a new window is created. |
385 | | void StartEventHandler(); |
386 | | |
387 | | // Escapes the ' character with a \, so it can be processed by LUA. |
388 | | char *AddEscapeChars(const char *input); |
389 | | |
390 | | // The event handler for this window. |
391 | | SVEventHandler *event_handler_; |
392 | | // The name of the window. |
393 | | const char *window_name_; |
394 | | // The id of the window. |
395 | | int window_id_; |
396 | | // The points of the currently under-construction polyline. |
397 | | std::unique_ptr<SVPolyLineBuffer> points_; |
398 | | // Whether the axis is reversed. |
399 | | bool y_axis_is_reversed_; |
400 | | // Set to true only after the event handler has terminated. |
401 | | bool event_handler_ended_; |
402 | | // If the y axis is reversed, flip all y values by ySize. |
403 | | int y_size_; |
404 | | // # of created windows (used to assign an id to each ScrollView* for svmap). |
405 | | static int nr_created_windows_; |
406 | | // Serial number of sent images to ensure that the viewer knows they |
407 | | // are distinct. |
408 | | static int image_index_; |
409 | | |
410 | | // The stream through which the c++ client is connected to the server. |
411 | | static std::unique_ptr<SVNetwork> stream_; |
412 | | |
413 | | // Table of all the currently queued events. |
414 | | std::unique_ptr<SVEvent> event_table_[SVET_COUNT]; |
415 | | |
416 | | // Mutex to access the event_table_ in a synchronized fashion. |
417 | | std::mutex mutex_; |
418 | | |
419 | | // Semaphore to the thread belonging to this window. |
420 | | std::unique_ptr<SVSemaphore> semaphore_; |
421 | | #endif // !GRAPHICS_DISABLED |
422 | | }; |
423 | | |
424 | | } // namespace tesseract |
425 | | |
426 | | #endif // TESSERACT_VIEWER_SCROLLVIEW_H_ |