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