2 * This file is part of lanterna (http://code.google.com/p/lanterna/).
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.
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.
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/>.
17 * Copyright (C) 2010-2015 Martin
19 package com
.googlecode
.lanterna
.gui2
;
21 import java
.io
.EOFException
;
22 import java
.io
.IOException
;
23 import java
.util
.concurrent
.CountDownLatch
;
26 * Default implementation of TextGUIThread, this class runs the GUI event processing on a dedicated thread. The GUI
27 * needs to be explicitly started in order for the event processing loop to begin, so you must call {@code start()}
28 * for this. The GUI thread will stop if {@code stop()} is called, the input stream returns EOF or an exception is
29 * thrown from inside the event handling loop.
31 * Here is an example of how to use this {@code TextGUIThread}:
34 * MultiWindowTextGUI textGUI = new MultiWindowTextGUI(new SeparateTextGUIThread.Factory(), screen);
35 * // ... add components ...
36 * ((AsynchronousTextGUIThread)textGUI.getGUIThread()).start();
37 * // ... this thread will continue while the GUI runs on a separate thread ...
41 * @see SameTextGUIThread
44 public class SeparateTextGUIThread
extends AbstractTextGUIThread
implements AsynchronousTextGUIThread
{
45 private volatile State state
;
46 private final Thread textGUIThread
;
47 private final CountDownLatch waitLatch
;
49 private SeparateTextGUIThread(TextGUI textGUI
) {
51 this.waitLatch
= new CountDownLatch(1);
52 this.textGUIThread
= new Thread("LanternaGUI") {
58 state
= State
.CREATED
;
63 textGUIThread
.start();
64 state
= State
.STARTED
;
69 if(state
!= State
.STARTED
) {
73 state
= State
.STOPPING
;
77 public void waitForStop() throws InterruptedException
{
82 public State
getState() {
87 public Thread
getThread() {
92 public void invokeLater(Runnable runnable
) throws IllegalStateException
{
93 if(state
!= State
.STARTED
) {
94 throw new IllegalStateException("Cannot schedule " + runnable
+ " for execution on the TextGUIThread " +
95 "because the thread is in " + state
+ " state");
97 super.invokeLater(runnable
);
100 private void mainGUILoop() {
102 //Draw initial screen, after this only draw when the GUI is marked as invalid
104 textGUI
.updateScreen();
106 catch(IOException e
) {
107 exceptionHandler
.onIOException(e
);
109 catch(RuntimeException e
) {
110 exceptionHandler
.onRuntimeException(e
);
112 while(state
== State
.STARTED
) {
114 if (!processEventsAndUpdate()) {
118 catch(InterruptedException ignored
) {}
121 catch(EOFException e
) {
123 break; //Break out quickly from the main loop
125 catch(IOException e
) {
126 if(exceptionHandler
.onIOException(e
)) {
131 catch(RuntimeException e
) {
132 if(exceptionHandler
.onRuntimeException(e
)) {
140 state
= State
.STOPPED
;
141 waitLatch
.countDown();
147 * Factory class for creating SeparateTextGUIThread objects
149 public static class Factory
implements TextGUIThreadFactory
{
151 public TextGUIThread
createTextGUIThread(TextGUI textGUI
) {
152 return new SeparateTextGUIThread(textGUI
);