Tesseract 3.02

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ScrollView.java
Go to the documentation of this file.
1 // Copyright 2007 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); You may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
6 // applicable law or agreed to in writing, software distributed under the
7 // License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
8 // OF ANY KIND, either express or implied. See the License for the specific
9 // language governing permissions and limitations under the License.
10
11 package com.google.scrollview;
12
13 import com.google.scrollview.events.SVEvent;
14 import com.google.scrollview.ui.SVImageHandler;
15 import com.google.scrollview.ui.SVWindow;
16
17 import java.io.BufferedReader;
18 import java.io.IOException;
19 import java.io.InputStreamReader;
20 import java.io.PrintStream;
21 import java.net.ServerSocket;
22 import java.net.Socket;
23 import java.util.ArrayList;
24 import java.util.regex.Pattern;
25
26
32 public class ScrollView {
33
35 public static int SERVER_PORT = 8461;
36
42 private static Socket socket;
43 private static PrintStream out;
44 public static BufferedReader in;
45 public static float polylineXCoords[]; // The coords being received.
46 public static float polylineYCoords[]; // The coords being received.
47 public static int polylineSize; // The size of the coords arrays.
48 public static int polylineScanned; // The size read so far.
49 private static ArrayList<SVWindow> windows; // The id to SVWindow map.
50 private static Pattern intPattern; // For checking integer arguments.
51 private static Pattern floatPattern; // For checking float arguments.
52
54 static int nrInputLines = 0;
55
57 static boolean debugViewNetworkTraffic = false;
58
60 public static void addMessage(SVEvent e) {
61 if (debugViewNetworkTraffic) {
62 System.out.println("(S->c) " + e.toString());
63 }
64 String str = e.toString();
65 // Send the whole thing as UTF8.
66 try {
67 byte [] utf8 = str.getBytes("UTF8");
68 out.write(utf8, 0, utf8.length);
69 } catch (java.io.UnsupportedEncodingException ex) {
70 System.out.println("Oops... can't encode to UTF8... Exiting");
71 System.exit(0);
72 }
73 out.println();
74 // Flush the output and check for errors.
75 boolean error = out.checkError();
76 if (error) {
77 System.out.println("Connection error. Quitting ScrollView Server...");
78 System.exit(0);
79 }
80 }
81
83 public static String receiveMessage() throws IOException {
84 return in.readLine();
85 }
86
91 private static void IOLoop() {
92 String inputLine;
93
94 try {
95 while (!socket.isClosed() && !socket.isInputShutdown() &&
96 !socket.isOutputShutdown() &&
97 socket.isConnected() && socket.isBound()) {
98 inputLine = receiveMessage();
99 nrInputLines++;
100 if (debugViewNetworkTraffic) {
101 System.out.println("(c->S," + nrInputLines + ")" + inputLine);
102 }
103
104 if (polylineSize > polylineScanned) {
105 // We are processing a polyline.
106 // Read pairs of coordinates separated by commas.
107 boolean first = true;
108 for (String coordStr : inputLine.split(",")) {
109 int coord = Integer.parseInt(coordStr);
110 if (first) {
111 polylineXCoords[polylineScanned] = coord;
112 } else {
113 polylineYCoords[polylineScanned++] = coord;
114 }
115 first = !first;
116 }
117 assert first;
118 } else if (SVImageHandler.getReadImageData() == false) {
119 // If we are currently not transmitting an image, process this
120 // normally.
121 processInput(inputLine);
122 }
123 // We are still transmitting image data, but there seems to be some
124 // command at the
125 // end of the message attached as well. Thus, we have to split it
126 // accordingly and
127 // first generate the image and afterwards process the remaining
128 // message.
129 else if (inputLine.length() >
130 SVImageHandler.getMissingRemainingBytes()) {
131 String luaCmd = inputLine.substring(
132 SVImageHandler.getMissingRemainingBytes());
133 String imgData = inputLine.substring(0,
134 SVImageHandler.getMissingRemainingBytes());
135 SVImageHandler.parseData(imgData);
136 processInput(luaCmd);
137 } else { // We are still in the middle of image data and have not
138 // reached the end yet.
139 SVImageHandler.parseData(inputLine);
140 }
141 }
142 }
143 // Some connection error
144 catch (IOException e) {
145 System.out.println("Connection error. Quitting ScrollView Server...");
146 }
147 System.exit(0);
148 }
149
150 // Parse a comma-separated list of arguments into ArrayLists of the
151 // possible types. Each type is stored in order, but the order
152 // distinction between types is lost.
153 // Note that the format is highly constrained to what the client used
154 // to send to LUA:
155 // Quoted string -> String.
156 // true or false -> Boolean.
157 // %f format number -> Float (no %e allowed)
158 // Sequence of digits -> Integer
159 // Nothing else allowed.
160 private static void parseArguments(String argList,
161 ArrayList<Integer> intList,
162 ArrayList<Float> floatList,
163 ArrayList<String> stringList,
164 ArrayList<Boolean> boolList) {
165 // str is only non-null if an argument starts with a single or double
166 // quote. str is set back to null on completion of the string with a
167 // matching quote. If the string contains a comma then str will stay
168 // non-null across multiple argStr values until a matching closing quote.
169 // Backslash escaped quotes do not count as terminating the string.
170 String str = null;
171 for (String argStr : argList.split(",")) {
172 if (str != null) {
173 // Last string was incomplete. Append argStr to it and restore comma.
174 // Execute str += "," + argStr in Java.
175 int length = str.length() + 1 + argStr.length();
176 StringBuilder appended = new StringBuilder(length);
177 appended.append(str);
178 appended.append(",");
179 appended.append(argStr);
180 str = appended.toString();
181 } else if (argStr.length() == 0) {
182 continue;
183 } else {
184 char quote = argStr.charAt(0);
185 // If it begins with a quote then it is a string, but may not
186 // end this time if it contained a comma.
187 if (quote == '\'' || quote == '"') {
188 str = argStr;
189 }
190 }
191 if (str != null) {
192 // It began with a quote. Check that it still does.
193 assert str.charAt(0) == '\'' || str.charAt(0) == '"';
194 int len = str.length();
195 if (len > 1 && str.charAt(len - 1) == str.charAt(0)) {
196 // We have an ending quote of the right type. Now check that
197 // it is not escaped. Must have an even number of slashes before.
198 int slash = len - 1;
199 while (slash > 0 && str.charAt(slash - 1) == '\\')
200 --slash;
201 if ((len - 1 - slash) % 2 == 0) {
202 // It is now complete. Chop off the quotes and save.
203 // TODO(rays) remove the first backslash of each pair.
204 stringList.add(str.substring(1, len - 1));
205 str = null;
206 }
207 }
208 // If str is not null here, then we have a string with a comma in it.
209 // Append , and the next argument at the next iteration, but check
210 // that str is null after the loop terminates in case it was an
211 // unterminated string.
212 } else if (floatPattern.matcher(argStr).matches()) {
213 // It is a float.
214 floatList.add(Float.parseFloat(argStr));
215 } else if (argStr.equals("true")) {
216 boolList.add(true);
217 } else if (argStr.equals("false")) {
218 boolList.add(false);
219 } else if (intPattern.matcher(argStr).matches()) {
220 // Only contains digits so must be an int.
221 intList.add(Integer.parseInt(argStr));
222 }
223 // else ignore all incompatible arguments for forward compatibility.
224 }
225 // All strings must have been terminated.
226 assert str == null;
227 }
228
230 private static void processInput(String inputLine) {
231 // Execute a function encoded as a LUA statement! Yuk!
232 if (inputLine.charAt(0) == 'w') {
233 // This is a method call on a window. Parse it.
234 String noWLine = inputLine.substring(1);
235 String[] idStrs = noWLine.split("[ :]", 2);
236 int windowID = Integer.parseInt(idStrs[0]);
237 // Find the parentheses.
238 int start = inputLine.indexOf('(');
239 int end = inputLine.lastIndexOf(')');
240 // Parse the args.
241 ArrayList<Integer> intList = new ArrayList<Integer>(4);
242 ArrayList<Float> floatList = new ArrayList<Float>(2);
243 ArrayList<String> stringList = new ArrayList<String>(4);
244 ArrayList<Boolean> boolList = new ArrayList<Boolean>(3);
245 parseArguments(inputLine.substring(start + 1, end),
246 intList, floatList, stringList, boolList);
247 int colon = inputLine.indexOf(':');
248 if (colon > 1 && colon < start) {
249 // This is a regular function call. Look for the name and call it.
250 String func = inputLine.substring(colon + 1, start);
251 if (func.equals("drawLine")) {
252 windows.get(windowID).drawLine(intList.get(0), intList.get(1),
253 intList.get(2), intList.get(3));
254 } else if (func.equals("createPolyline")) {
255 windows.get(windowID).createPolyline(intList.get(0));
256 } else if (func.equals("drawPolyline")) {
257 windows.get(windowID).drawPolyline();
258 } else if (func.equals("drawRectangle")) {
259 windows.get(windowID).drawRectangle(intList.get(0), intList.get(1),
260 intList.get(2), intList.get(3));
261 } else if (func.equals("setVisible")) {
262 windows.get(windowID).setVisible(boolList.get(0));
263 } else if (func.equals("setAlwaysOnTop")) {
264 windows.get(windowID).setAlwaysOnTop(boolList.get(0));
265 } else if (func.equals("addMessage")) {
266 windows.get(windowID).addMessage(stringList.get(0));
267 } else if (func.equals("addMessageBox")) {
268 windows.get(windowID).addMessageBox();
269 } else if (func.equals("clear")) {
270 windows.get(windowID).clear();
271 } else if (func.equals("setStrokeWidth")) {
272 windows.get(windowID).setStrokeWidth(floatList.get(0));
273 } else if (func.equals("drawEllipse")) {
274 windows.get(windowID).drawEllipse(intList.get(0), intList.get(1),
275 intList.get(2), intList.get(3));
276 } else if (func.equals("pen")) {
277 if (intList.size() == 4) {
278 windows.get(windowID).pen(intList.get(0), intList.get(1),
279 intList.get(2), intList.get(3));
280 } else {
281 windows.get(windowID).pen(intList.get(0), intList.get(1),
282 intList.get(2));
283 }
284 } else if (func.equals("brush")) {
285 if (intList.size() == 4) {
286 windows.get(windowID).brush(intList.get(0), intList.get(1),
287 intList.get(2), intList.get(3));
288 } else {
289 windows.get(windowID).brush(intList.get(0), intList.get(1),
290 intList.get(2));
291 }
292 } else if (func.equals("textAttributes")) {
293 windows.get(windowID).textAttributes(stringList.get(0),
294 intList.get(0),
295 boolList.get(0),
296 boolList.get(1),
297 boolList.get(2));
298 } else if (func.equals("drawText")) {
299 windows.get(windowID).drawText(intList.get(0), intList.get(1),
300 stringList.get(0));
301 } else if (func.equals("openImage")) {
302 windows.get(windowID).openImage(stringList.get(0));
303 } else if (func.equals("drawImage")) {
304 windows.get(windowID).drawImage(stringList.get(0),
305 intList.get(0), intList.get(1));
306 } else if (func.equals("addMenuBarItem")) {
307 if (boolList.size() > 0) {
308 windows.get(windowID).addMenuBarItem(stringList.get(0),
309 stringList.get(1),
310 intList.get(0),
311 boolList.get(0));
312 } else if (intList.size() > 0) {
313 windows.get(windowID).addMenuBarItem(stringList.get(0),
314 stringList.get(1),
315 intList.get(0));
316 } else {
317 windows.get(windowID).addMenuBarItem(stringList.get(0),
318 stringList.get(1));
319 }
320 } else if (func.equals("addPopupMenuItem")) {
321 if (stringList.size() == 4) {
322 windows.get(windowID).addPopupMenuItem(stringList.get(0),
323 stringList.get(1),
324 intList.get(0),
325 stringList.get(2),
326 stringList.get(3));
327 } else {
328 windows.get(windowID).addPopupMenuItem(stringList.get(0),
329 stringList.get(1));
330 }
331 } else if (func.equals("update")) {
332 windows.get(windowID).update();
333 } else if (func.equals("showInputDialog")) {
334 windows.get(windowID).showInputDialog(stringList.get(0));
335 } else if (func.equals("showYesNoDialog")) {
336 windows.get(windowID).showYesNoDialog(stringList.get(0));
337 } else if (func.equals("zoomRectangle")) {
338 windows.get(windowID).zoomRectangle(intList.get(0), intList.get(1),
339 intList.get(2), intList.get(3));
340 } else if (func.equals("createImage")) {
341 windows.get(windowID).createImage(stringList.get(0), intList.get(0),
342 intList.get(1), intList.get(2));
343 } else if (func.equals("drawImage")) {
344 windows.get(windowID).drawImage(stringList.get(0),
345 intList.get(0), intList.get(1));
346 } else if (func.equals("destroy")) {
347 windows.get(windowID).destroy();
348 }
349 // else for forward compatibility purposes, silently ignore any
350 // unrecognized function call.
351 } else {
352 // No colon. Check for create window.
353 if (idStrs[1].startsWith("= luajava.newInstance")) {
354 while (windows.size() <= windowID) {
355 windows.add(null);
356 }
357 windows.set(windowID, new SVWindow(stringList.get(1),
358 intList.get(0), intList.get(1),
359 intList.get(2), intList.get(3),
360 intList.get(4), intList.get(5),
361 intList.get(6)));
362 }
363 // else for forward compatibility purposes, silently ignore any
364 // unrecognized function call.
365 }
366 } else if (inputLine.startsWith("svmain")) {
367 // Startup or end. Startup is a lua bind, which is now a no-op.
368 if (inputLine.startsWith("svmain:exit")) {
369 exit();
370 }
371 // else for forward compatibility purposes, silently ignore any
372 // unrecognized function call.
373 }
374 // else for forward compatibility purposes, silently ignore any
375 // unrecognized function call.
376 }
377
379 public static void exit() {
380 System.exit(0);
381 }
382
387 public static void main(String[] args) {
388 if (args.length > 0) {
389 SERVER_PORT = Integer.parseInt(args[0]);
390 }
391 windows = new ArrayList<SVWindow>(100);
392 intPattern = Pattern.compile("[0-9-][0-9]*");
393 floatPattern = Pattern.compile("[0-9-][0-9]*\\.[0-9]*");
394
395 try {
396 // Open a socket to listen on.
397 ServerSocket serverSocket = new ServerSocket(SERVER_PORT);
398 System.out.println("Socket started on port " + SERVER_PORT);
399
400 // Wait (blocking) for an incoming connection
401 socket = serverSocket.accept();
402 System.out.println("Client connected");
403
404 // Setup the streams
405 out = new PrintStream(socket.getOutputStream(), true);
406 in =
407 new BufferedReader(new InputStreamReader(socket.getInputStream(),
408 "UTF8"));
409 } catch (IOException e) {
410 // Something went wrong and we were unable to set up a connection. This is
411 // pretty
412 // much a fatal error.
413 // Note: The server does not get restarted automatically if this happens.
414 e.printStackTrace();
415 System.exit(1);
416 }
417
418 // Enter the main program loop.
419 IOLoop();
420 }
421 }