1 package org.lsst.ccs.demo.shell;
2
3 import com.wittams.gritty.Questioner;
4 import com.wittams.gritty.RequestOrigin;
5 import com.wittams.gritty.ResizePanelDelegate;
6 import com.wittams.gritty.Tty;
7 import com.wittams.gritty.swing.GrittyTerminal;
8 import com.wittams.gritty.swing.TermPanel;
9 import java.awt.Dimension;
10 import java.io.IOException;
11 import java.io.InputStream;
12 import java.io.InterruptedIOException;
13 import java.io.OutputStream;
14 import java.util.concurrent.BlockingQueue;
15 import java.util.concurrent.LinkedBlockingQueue;
16 import javax.swing.JFrame;
17 import jline.Terminal;
18 import jline.console.ConsoleReader;
19 import org.lsst.ccs.command.CommandSet;
20 import org.lsst.ccs.command.CommandSetBuilder;
21 import org.lsst.ccs.command.demo.DemoCommands;
22 import org.lsst.ccs.shell.JLineShell;
23 import org.lsst.ccs.shell.JLineShell;
24
25
26
27
28
29
30
31
32
33
34
35
36 public class SwingShell {
37
38 private GrittyTerminal terminal;
39 private final JLineShell shell;
40 private final JFrame frame;
41
42 public SwingShell(CommandSet userCommands, String title) throws IOException {
43 frame = new JFrame(title);
44 terminal = new GrittyTerminal();
45 TermPanel termPanel = terminal.getTermPanel();
46 frame.setContentPane(terminal);
47 frame.pack();
48 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
49 frame.setLocationByPlatform(true);
50 termPanel.setVisible(true);
51 frame.setVisible(true);
52 frame.setResizable(true);
53
54 termPanel.setResizePanelDelegate(new ResizePanelDelegate() {
55 @Override
56 public void resizedPanel(final Dimension pixelDimension, final RequestOrigin origin) {
57 if (origin == RequestOrigin.Remote) {
58 sizeFrameForTerm(frame);
59 }
60 }
61 });
62 final TtyImpl tty = new TtyImpl();
63
64 terminal.setTty(tty);
65 ConsoleReader reader = new ConsoleReader(tty.getInputStream(), tty.getOutputStream(), new SwingTerminal());
66 shell = new JLineShell(userCommands, reader);
67 }
68
69 public void run() throws IOException {
70 terminal.start();
71 try {
72 shell.run();
73 } finally {
74 terminal.stop();
75 frame.setVisible(false);
76 }
77 }
78
79 public static void main(String[] args) throws IOException {
80 CommandSetBuilder builder = new CommandSetBuilder();
81 SwingShell swingShell = new SwingShell(builder.buildCommandSet(new DemoCommands()),"Swing Shell");
82 swingShell.run();
83 }
84
85 private void sizeFrameForTerm(final JFrame frame) {
86 Dimension d = terminal.getPreferredSize();
87
88 d.width += frame.getWidth() - frame.getContentPane().getWidth();
89 d.height += frame.getHeight() - frame.getContentPane().getHeight();
90 frame.setSize(d);
91 }
92
93 private static class SwingTerminal implements Terminal {
94
95 @Override
96 public void init() throws Exception {
97 }
98
99 @Override
100 public void restore() throws Exception {
101 }
102
103 @Override
104 public void reset() throws Exception {
105 }
106
107 @Override
108 public boolean isSupported() {
109 return true;
110 }
111
112 @Override
113 public int getWidth() {
114
115 return 80;
116 }
117
118 @Override
119 public int getHeight() {
120
121 return 100;
122 }
123
124 @Override
125 public boolean isAnsiSupported() {
126 return false;
127 }
128
129 @Override
130 public OutputStream wrapOutIfNeeded(OutputStream out) {
131 return out;
132 }
133
134 @Override
135 public InputStream wrapInIfNeeded(InputStream in) throws IOException {
136 return in;
137 }
138
139 @Override
140 public boolean hasWeirdWrap() {
141 return false;
142 }
143
144 @Override
145 public boolean isEchoEnabled() {
146 return false;
147 }
148
149 @Override
150 public void setEchoEnabled(boolean bln) {
151 }
152 }
153
154 private class TtyImpl implements Tty {
155
156 private final BlockingQueue<byte[]> inputQueue = new LinkedBlockingQueue<>();
157 private final BlockingQueue<byte[]> outputQueue = new LinkedBlockingQueue<>();
158 private final TtyInputStream inputStream;
159 private final TtyOutputStream outputStream;
160
161 public TtyImpl() {
162 inputStream = new TtyInputStream();
163 outputStream = new TtyOutputStream();
164 }
165
166 @Override
167 public boolean init(Questioner qstnr) {
168 return true;
169 }
170
171 @Override
172 public void close() {
173 }
174
175 @Override
176 public void resize(Dimension dmnsn, Dimension dmnsn1) {
177 }
178
179 @Override
180 public String getName() {
181 return "Test";
182 }
183
184 @Override
185 public int read(byte[] bytes, int i, int i1) throws IOException {
186 try {
187 byte[] src = outputQueue.take();
188
189 System.arraycopy(src, 0, bytes, i, src.length);
190 return src.length;
191 } catch (InterruptedException ex) {
192 throw new InterruptedIOException();
193 }
194 }
195
196 @Override
197 public void write(byte[] bytes) throws IOException {
198 try {
199 inputQueue.put(bytes);
200 } catch (InterruptedException ex) {
201 throw new InterruptedIOException();
202 }
203 }
204
205 public TtyInputStream getInputStream() {
206 return inputStream;
207 }
208
209 public TtyOutputStream getOutputStream() {
210 return outputStream;
211 }
212
213 private class TtyInputStream extends InputStream {
214
215 private byte[] currentBuffer;
216 private int pos;
217
218 @Override
219 public int read() throws IOException {
220 try {
221 while (currentBuffer == null || currentBuffer.length <= pos) {
222 currentBuffer = inputQueue.take();
223 pos = 0;
224 }
225 return currentBuffer[pos++];
226 } catch (InterruptedException interruptedException) {
227 throw new InterruptedIOException();
228 }
229 }
230
231 @Override
232 public int read(byte[] b, int off, int len) throws IOException {
233 try {
234 if (currentBuffer == null || currentBuffer.length <= pos) {
235 currentBuffer = inputQueue.take();
236 pos = 0;
237 }
238 int actual = Math.min(len, currentBuffer.length - pos);
239 System.arraycopy(currentBuffer, pos, b, off, actual);
240 pos += actual;
241 return actual;
242 } catch (InterruptedException interruptedException) {
243 throw new InterruptedIOException();
244 }
245 }
246 }
247
248 private class TtyOutputStream extends OutputStream {
249
250 @Override
251 public void write(int b) throws IOException {
252 try {
253 byte[] buffer = new byte[1];
254 buffer[0] = (byte) b;
255 outputQueue.put(buffer);
256 if (b == 0xa) {
257 byte[] buffer2 = new byte[1];
258 buffer2[0] = 0xd;
259 outputQueue.put(buffer2);
260 }
261 } catch (InterruptedException interruptedException) {
262 throw new InterruptedIOException();
263 }
264 }
265 }
266 }
267 }