update copyright
[fedora-idea.git] / plugins / ui-designer / src / com / intellij / uiDesigner / snapShooter / SnapShooterDaemon.java
blob1cb9304ea95adb01658fe103a3b70423fb68b6ec
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.intellij.uiDesigner.snapShooter;
19 import com.intellij.openapi.vfs.CharsetToolkit;
20 import com.intellij.uiDesigner.XmlWriter;
21 import com.intellij.uiDesigner.radComponents.RadComponent;
22 import com.intellij.uiDesigner.radComponents.RadRootContainer;
23 import org.jetbrains.annotations.NonNls;
25 import javax.accessibility.AccessibleContext;
26 import javax.swing.*;
27 import java.awt.*;
28 import java.io.BufferedReader;
29 import java.io.IOException;
30 import java.io.InputStreamReader;
31 import java.io.OutputStreamWriter;
32 import java.net.InetAddress;
33 import java.net.ServerSocket;
34 import java.net.Socket;
35 import java.util.*;
36 import java.util.List;
37 import java.util.concurrent.ArrayBlockingQueue;
38 import java.util.concurrent.BlockingQueue;
40 /**
41 * @author yole
43 public class SnapShooterDaemon implements Runnable {
44 private final Map<Integer, Component> myIdMap = new HashMap<Integer, Component>();
45 private int myNextId = 1;
46 private final BlockingQueue<String> myCommandQueue = new ArrayBlockingQueue<String>(20);
47 private final BlockingQueue<String> myResponseQueue = new ArrayBlockingQueue<String>(20);
48 private final int myPort;
50 public SnapShooterDaemon(final int port) {
51 myPort = port;
54 public void run() {
55 ServerSocket serverSocket;
56 try {
57 serverSocket = new ServerSocket(myPort, 50, InetAddress.getLocalHost());
59 catch(IOException ex) {
60 System.out.println("Failed to open server socket: " + ex);
61 return;
64 System.out.println("SnapShooter listening on port " + myPort);
66 //noinspection InfiniteLoopStatement
67 while (true) {
68 processClientConnection(serverSocket);
72 private void processClientConnection(final ServerSocket serverSocket) {
73 Socket clientSocket;
74 try {
75 clientSocket = serverSocket.accept();
76 System.out.println("SnapShooter connection accepted");
77 InputStreamReader reader = new InputStreamReader(clientSocket.getInputStream(), CharsetToolkit.UTF8_CHARSET);
78 BufferedReader bufferedReader = new BufferedReader(reader);
79 OutputStreamWriter writer = new OutputStreamWriter(clientSocket.getOutputStream(), CharsetToolkit.UTF8_CHARSET);
80 while(true) {
81 String command;
82 try {
83 command = bufferedReader.readLine();
85 catch(IOException ex) {
86 break;
88 if (command == null) {
89 System.out.println("End of stream receiving command");
90 break;
92 processCommand(command, writer);
95 catch(IOException ex) {
96 System.out.println("Exception in SnapShooter connection: " + ex);
100 private void processCommand(@NonNls final String command, final OutputStreamWriter writer) throws IOException {
101 if (command.startsWith("S")) {
102 SwingUtilities.invokeLater(new SuspendSwingRunnable());
104 else {
105 myCommandQueue.add(command);
106 if (command.startsWith("L") || command.startsWith("X")) {
107 String response;
108 try {
109 response = myResponseQueue.take();
111 catch (InterruptedException e) {
112 writer.close();
113 return;
115 writer.write(response);
116 writer.flush();
121 private String[] getChildren(final int id) {
122 List<String> result = new ArrayList<String>();
123 List<Component> children = getChildList(id);
124 for(Component child: children) {
125 SnapShotRemoteComponent rc = new SnapShotRemoteComponent(assignId(child),
126 child.getClass().getName(),
127 getLayoutManagerClass(child),
128 getChildText(child));
129 result.add(rc.toProtocolString());
131 return result.toArray(new String[result.size()]);
134 private static String getLayoutManagerClass(final Component component) {
135 if (component instanceof JPanel) {
136 LayoutManager layoutManager = ((Container) component).getLayout();
137 if (layoutManager != null) {
138 Class layoutManagerClass = layoutManager.getClass();
139 while(!layoutManagerClass.getSuperclass().equals(Object.class)) {
140 layoutManagerClass = layoutManagerClass.getSuperclass();
142 return layoutManagerClass.getName();
145 return "";
148 private List<Component> getChildList(final int id) {
149 List<Component> children = new ArrayList<Component>();
150 if (id == 0) {
151 children = getRootWindows();
153 else {
154 Component parent = myIdMap.get(id);
155 if (parent instanceof RootPaneContainer) {
156 RootPaneContainer rpc = (RootPaneContainer) parent;
157 children.add(rpc.getContentPane());
159 else if (parent instanceof JSplitPane) {
160 JSplitPane splitPane = (JSplitPane) parent;
161 if (splitPane.getLeftComponent() != null) {
162 children.add(splitPane.getLeftComponent());
164 if (splitPane.getRightComponent() != null) {
165 children.add(splitPane.getRightComponent());
168 else if (parent instanceof JScrollPane) {
169 JScrollPane scrollPane = (JScrollPane) parent;
170 children.add(scrollPane.getViewport().getView());
172 else if (parent instanceof Container) {
173 Collections.addAll(children, ((Container) parent).getComponents());
176 return children;
179 private static String getChildText(final Component component) {
180 if (component instanceof Frame) {
181 Frame frame = (Frame) component;
182 return frame.getTitle();
185 final AccessibleContext accessibleContext = component.getAccessibleContext();
186 if (accessibleContext != null) {
187 final String text = accessibleContext.getAccessibleName();
188 if (text != null && text.length() > 0) {
189 return text;
193 return "";
196 private int assignId(final Component child) {
197 int result = myNextId;
198 myIdMap.put(result, child);
199 myNextId++;
200 return result;
203 private static List<Component> getRootWindows() {
204 List<Component> result = new ArrayList<Component>();
205 for(Frame frame: Frame.getFrames()) {
206 //noinspection HardCodedStringLiteral
207 if (!frame.getClass().getName().endsWith("SwingUtilities$SharedOwnerFrame")) {
208 result.add(frame);
210 for(Window window: frame.getOwnedWindows()) {
211 if (window.isVisible()) {
212 result.add(window);
216 return result;
219 private class SuspendSwingRunnable implements Runnable {
220 public void run() {
221 while(true) {
222 String command;
223 try {
224 command = myCommandQueue.take();
226 catch (InterruptedException e) {
227 break;
229 if (command.startsWith("R")) {
230 break;
232 String response = "";
233 if (command.startsWith("L")) {
234 response = doListCommand(command);
236 else if (command.startsWith("X")) {
237 response = doSnapshotCommand(command);
239 if (response.length() > 0) {
240 System.out.println("Sending response: " + response);
241 try {
242 myResponseQueue.put(response);
244 catch (InterruptedException e) {
245 break;
251 @NonNls
252 private String doSnapshotCommand(final String command) {
253 int id = Integer.parseInt(command.substring(1));
254 Component component = myIdMap.get(id);
255 XmlWriter xmlWriter = new XmlWriter();
256 RadRootContainer rootContainer = null;
257 try {
258 rootContainer = createFormSnapshot((JComponent) component);
260 catch (Exception ex) {
261 ex.printStackTrace();
262 return "E:" + ex.getMessage() + "\n";
264 rootContainer.write(xmlWriter);
265 return xmlWriter.getText();
268 private RadRootContainer createFormSnapshot(final JComponent component) {
269 SnapshotContext context = new SnapshotContext();
270 final RadComponent radComponent = RadComponent.createSnapshotComponent(context, component);
271 if (radComponent != null) {
272 radComponent.setBounds(new Rectangle(new Point(10, 10), component.getPreferredSize()));
273 context.getRootContainer().addComponent(radComponent);
274 context.postProcess();
276 return context.getRootContainer();
279 @NonNls
280 private String doListCommand(final String command) {
281 int id = Integer.parseInt(command.substring(1));
282 String[] children = getChildren(id);
283 StringBuilder result = new StringBuilder();
284 for(String child: children) {
285 result.append(child).append("\n");
287 result.append(".\n");
288 return result.toString();