Fix UTF8 bug, create first executable JAR file
[jvcard.git] / src / com / googlecode / lanterna / terminal / DefaultTerminalFactory.java
CommitLineData
a3b510ab
NR
1/*
2 * This file is part of lanterna (http://code.google.com/p/lanterna/).
3 *
4 * lanterna is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Copyright (C) 2010-2015 Martin
18 */
19package com.googlecode.lanterna.terminal;
20
21import com.googlecode.lanterna.TerminalSize;
22import com.googlecode.lanterna.terminal.ansi.CygwinTerminal;
23import com.googlecode.lanterna.terminal.ansi.UnixTerminal;
24import com.googlecode.lanterna.terminal.swing.*;
25
26import java.awt.*;
27import java.io.IOException;
28import java.io.InputStream;
29import java.io.OutputStream;
30import java.nio.charset.Charset;
31
32/**
33 * This TerminalFactory implementation uses a simple auto-detection mechanism for figuring out which terminal
34 * implementation to create based on characteristics of the system the program is running on.
35 * <p>
36 * Note that for all systems with a graphical environment present, the SwingTerminalFrame will be chosen. You can
37 * suppress this by calling setForceTextTerminal(true) on this factory.
38 * @author martin
39 */
40public final class DefaultTerminalFactory implements TerminalFactory {
41 private static final OutputStream DEFAULT_OUTPUT_STREAM = System.out;
42 private static final InputStream DEFAULT_INPUT_STREAM = System.in;
43 private static final Charset DEFAULT_CHARSET = Charset.forName(System.getProperty("file.encoding"));
44
45 private final OutputStream outputStream;
46 private final InputStream inputStream;
47 private final Charset charset;
48
49 private TerminalSize initialTerminalSize;
50 private boolean forceTextTerminal;
51 private boolean forceAWTOverSwing;
52 private String title;
53 private boolean autoOpenTerminalFrame;
54 private TerminalEmulatorAutoCloseTrigger autoCloseTrigger;
55 private TerminalEmulatorColorConfiguration colorConfiguration;
56 private TerminalEmulatorDeviceConfiguration deviceConfiguration;
57 private AWTTerminalFontConfiguration fontConfiguration;
58 private MouseCaptureMode mouseCaptureMode;
59
60 /**
61 * Creates a new DefaultTerminalFactory with all properties set to their defaults
62 */
63 public DefaultTerminalFactory() {
64 this(DEFAULT_OUTPUT_STREAM, DEFAULT_INPUT_STREAM, DEFAULT_CHARSET);
65 }
66
67 /**
68 * Creates a new DefaultTerminalFactory with I/O and character set options customisable.
69 * @param outputStream Output stream to use for text-based Terminal implementations
70 * @param inputStream Input stream to use for text-based Terminal implementations
71 * @param charset Character set to assume the client is using
72 */
73 @SuppressWarnings({"SameParameterValue", "WeakerAccess"})
74 public DefaultTerminalFactory(OutputStream outputStream, InputStream inputStream, Charset charset) {
75 this.outputStream = outputStream;
76 this.inputStream = inputStream;
77 this.charset = charset;
78
79 this.forceTextTerminal = false;
80 this.autoOpenTerminalFrame = true;
81 this.title = null;
82 this.autoCloseTrigger = TerminalEmulatorAutoCloseTrigger.CloseOnExitPrivateMode;
83 this.mouseCaptureMode = null;
84
85 //SwingTerminal will replace these null values for the default implementation if they are unchanged
86 this.colorConfiguration = null;
87 this.deviceConfiguration = null;
88 this.fontConfiguration = null;
89 }
90
91 @Override
92 public Terminal createTerminal() throws IOException {
93 if (GraphicsEnvironment.isHeadless() || forceTextTerminal || System.console() != null) {
94 if(isOperatingSystemWindows()) {
95 return createCygwinTerminal(outputStream, inputStream, charset);
96 }
97 else {
98 return createUnixTerminal(outputStream, inputStream, charset);
99 }
100 }
101 else {
102 return createTerminalEmulator();
103 }
104 }
105
106 /**
107 * Creates a new terminal emulator window which will be either Swing-based or AWT-based depending on what is
108 * available on the system
109 * @return New terminal emulator exposed as a {@link Terminal} interface
110 */
111 public Terminal createTerminalEmulator() {
112 Window window;
113 if(!forceAWTOverSwing && hasSwing()) {
114 window = createSwingTerminal();
115 }
116 else {
117 window = createAWTTerminal();
118 }
119
120 if(autoOpenTerminalFrame) {
121 window.setVisible(true);
122 }
123 return (Terminal)window;
124 }
125
126 public AWTTerminalFrame createAWTTerminal() {
127 return new AWTTerminalFrame(
128 title,
129 initialTerminalSize,
130 deviceConfiguration,
131 fontConfiguration,
132 colorConfiguration,
133 autoCloseTrigger);
134 }
135
136 public SwingTerminalFrame createSwingTerminal() {
137 return new SwingTerminalFrame(
138 title,
139 initialTerminalSize,
140 deviceConfiguration,
141 fontConfiguration instanceof SwingTerminalFontConfiguration ? (SwingTerminalFontConfiguration)fontConfiguration : null,
142 colorConfiguration,
143 autoCloseTrigger);
144 }
145
146 private boolean hasSwing() {
147 try {
148 Class.forName("javax.swing.JComponent");
149 return true;
150 }
151 catch(Exception ignore) {
152 return false;
153 }
154 }
155
156 /**
157 * Sets a hint to the TerminalFactory of what size to use when creating the terminal. Most terminals are not created
158 * on request but for example the SwingTerminal and SwingTerminalFrame are and this value will be passed down on
159 * creation.
160 * @param initialTerminalSize Size (in rows and columns) of the newly created terminal
161 * @return Reference to itself, so multiple .set-calls can be chained
162 */
163 public DefaultTerminalFactory setInitialTerminalSize(TerminalSize initialTerminalSize) {
164 this.initialTerminalSize = initialTerminalSize;
165 return this;
166 }
167
168 /**
169 * Controls whether a SwingTerminalFrame shall always be created if the system is one with a graphical environment
170 * @param forceTextTerminal If true, will always create a text-based Terminal
171 * @return Reference to itself, so multiple .set-calls can be chained
172 */
173 public DefaultTerminalFactory setForceTextTerminal(boolean forceTextTerminal) {
174 this.forceTextTerminal = forceTextTerminal;
175 return this;
176 }
177
178 /**
179 * Normally when a graphical terminal emulator is created by the factory, it will create a
180 * {@link SwingTerminalFrame} unless Swing is not present in the system. Setting this property to {@code true} will
181 * make it create an {@link AWTTerminalFrame} even if Swing is present
182 * @param forceAWTOverSwing If {@code true}, will always create an {@link AWTTerminalFrame} over a
183 * {@link SwingTerminalFrame} if asked to create a graphical terminal emulator
184 * @return Reference to itself, so multiple .set-calls can be chained
185 */
186 public DefaultTerminalFactory setForceAWTOverSwing(boolean forceAWTOverSwing) {
187 this.forceAWTOverSwing = forceAWTOverSwing;
188 return this;
189 }
190
191 /**
192 * Controls whether a SwingTerminalFrame shall be automatically shown (.setVisible(true)) immediately after
193 * creation. If {@code false}, you will manually need to call {@code .setVisible(true)} on the JFrame to actually
194 * see the terminal window. Default for this value is {@code true}.
195 * @param autoOpenTerminalFrame Automatically open SwingTerminalFrame after creation
196 */
197 public void setAutoOpenTerminalEmulatorWindow(boolean autoOpenTerminalFrame) {
198 this.autoOpenTerminalFrame = autoOpenTerminalFrame;
199 }
200
201 /**
202 * Sets the title to use on created SwingTerminalFrames created by this factory
203 * @param title Title to use on created SwingTerminalFrames created by this factory
204 * @return Reference to itself, so multiple .set-calls can be chained
205 */
206 public DefaultTerminalFactory setTerminalEmulatorTitle(String title) {
207 this.title = title;
208 return this;
209 }
210
211 /**
212 * Sets the auto-close trigger to use on created SwingTerminalFrames created by this factory
213 * @param autoCloseTrigger Auto-close trigger to use on created SwingTerminalFrames created by this factory
214 * @return Reference to itself, so multiple .set-calls can be chained
215 */
216 public DefaultTerminalFactory setTerminalEmulatorFrameAutoCloseTrigger(TerminalEmulatorAutoCloseTrigger autoCloseTrigger) {
217 this.autoCloseTrigger = autoCloseTrigger;
218 return this;
219 }
220
221 /**
222 * Sets the color configuration to use on created SwingTerminalFrames created by this factory
223 * @param colorConfiguration Color configuration to use on created SwingTerminalFrames created by this factory
224 * @return Reference to itself, so multiple .set-calls can be chained
225 */
226 public DefaultTerminalFactory setTerminalEmulatorColorConfiguration(TerminalEmulatorColorConfiguration colorConfiguration) {
227 this.colorConfiguration = colorConfiguration;
228 return this;
229 }
230
231 /**
232 * Sets the device configuration to use on created SwingTerminalFrames created by this factory
233 * @param deviceConfiguration Device configuration to use on created SwingTerminalFrames created by this factory
234 * @return Reference to itself, so multiple .set-calls can be chained
235 */
236 public DefaultTerminalFactory setTerminalEmulatorDeviceConfiguration(TerminalEmulatorDeviceConfiguration deviceConfiguration) {
237 this.deviceConfiguration = deviceConfiguration;
238 return this;
239 }
240
241 /**
242 * Sets the font configuration to use on created SwingTerminalFrames created by this factory
243 * @param fontConfiguration Font configuration to use on created SwingTerminalFrames created by this factory
244 * @return Reference to itself, so multiple .set-calls can be chained
245 */
246 public DefaultTerminalFactory setTerminalEmulatorFontConfiguration(AWTTerminalFontConfiguration fontConfiguration) {
247 this.fontConfiguration = fontConfiguration;
248 return this;
249 }
250
251 /**
252 * Sets the mouse capture mode the terminal should use. Please note that this is an extension which isn't widely
253 * supported!
254 * @param mouseCaptureMode Capture mode for mouse interactions
255 * @return Itself
256 */
257 public DefaultTerminalFactory setMouseCaptureMode(MouseCaptureMode mouseCaptureMode) {
258 this.mouseCaptureMode = mouseCaptureMode;
259 return this;
260 }
261
262 private Terminal createCygwinTerminal(OutputStream outputStream, InputStream inputStream, Charset charset) throws IOException {
263 return new CygwinTerminal(inputStream, outputStream, charset);
264 }
265
266 private Terminal createUnixTerminal(OutputStream outputStream, InputStream inputStream, Charset charset) throws IOException {
267 UnixTerminal unixTerminal = new UnixTerminal(inputStream, outputStream, charset);
268 if(mouseCaptureMode != null) {
269 unixTerminal.setMouseCaptureMode(mouseCaptureMode);
270 }
271 return unixTerminal;
272 }
273
274 /**
275 * Detects whether the running platform is Windows* by looking at the
276 * operating system name system property
277 */
278 private static boolean isOperatingSystemWindows() {
279 return System.getProperty("os.name", "").toLowerCase().startsWith("windows");
280 }
281}