Commit | Line | Data |
---|---|---|
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 | */ | |
19 | package com.googlecode.lanterna.gui2; | |
20 | ||
21 | import com.googlecode.lanterna.TerminalPosition; | |
22 | import com.googlecode.lanterna.input.KeyStroke; | |
23 | import com.googlecode.lanterna.TerminalSize; | |
24 | import com.googlecode.lanterna.input.KeyType; | |
25 | ||
26 | import java.util.*; | |
27 | ||
28 | /** | |
29 | * Abstract Window has most of the code requiring for a window to function, all concrete window implementations extends | |
30 | * from this in one way or another. You can define your own window by extending from this, as an alternative to building | |
31 | * up the GUI externally by constructing a {@code BasicWindow} and adding components to it. | |
32 | * @author Martin | |
33 | */ | |
34 | public abstract class AbstractWindow extends AbstractBasePane implements Window { | |
35 | private String title; | |
36 | private WindowBasedTextGUI textGUI; | |
37 | private boolean visible; | |
38 | private TerminalSize lastKnownSize; | |
39 | private TerminalSize lastKnownDecoratedSize; | |
40 | private TerminalPosition lastKnownPosition; | |
41 | private TerminalPosition contentOffset; | |
42 | private Set<Hint> hints; | |
43 | private boolean closeWindowWithEscape; | |
44 | ||
45 | /** | |
46 | * Default constructor, this creates a window with no title | |
47 | */ | |
48 | public AbstractWindow() { | |
49 | this(""); | |
50 | } | |
51 | ||
52 | /** | |
53 | * Creates a window with a specific title that will (probably) be drawn in the window decorations | |
54 | * @param title Title of this window | |
55 | */ | |
56 | public AbstractWindow(String title) { | |
57 | super(); | |
58 | this.title = title; | |
59 | this.textGUI = null; | |
60 | this.visible = true; | |
61 | this.lastKnownPosition = null; | |
62 | this.lastKnownSize = null; | |
63 | this.lastKnownDecoratedSize = null; | |
64 | this.closeWindowWithEscape = false; | |
65 | ||
66 | this.hints = new HashSet<Hint>(); | |
67 | } | |
68 | ||
69 | /** | |
70 | * Setting this property to {@code true} will cause pressing the ESC key to close the window. This used to be the | |
71 | * default behaviour of lanterna 3 during the development cycle but is not longer the case. You are encouraged to | |
72 | * put proper buttons or other kind of components to clearly mark to the user how to close the window instead of | |
73 | * magically taking ESC, but sometimes it can be useful (when doing testing, for example) to enable this mode. | |
74 | * @param closeWindowWithEscape If {@code true}, this window will self-close if you press ESC key | |
75 | */ | |
76 | public void setCloseWindowWithEscape(boolean closeWindowWithEscape) { | |
77 | this.closeWindowWithEscape = closeWindowWithEscape; | |
78 | } | |
79 | ||
80 | @Override | |
81 | public void setTextGUI(WindowBasedTextGUI textGUI) { | |
82 | //This is kind of stupid check, but might cause it to blow up on people using the library incorrectly instead of | |
83 | //just causing weird behaviour | |
84 | if(this.textGUI != null && textGUI != null) { | |
85 | throw new UnsupportedOperationException("Are you calling setTextGUI yourself? Please read the documentation" | |
86 | + " in that case (this could also be a bug in Lanterna, please report it if you are sure you are " | |
87 | + "not calling Window.setTextGUI(..) from your code)"); | |
88 | } | |
89 | this.textGUI = textGUI; | |
90 | } | |
91 | ||
92 | @Override | |
93 | public WindowBasedTextGUI getTextGUI() { | |
94 | return textGUI; | |
95 | } | |
96 | ||
97 | /** | |
98 | * Alters the title of the window to the supplied string | |
99 | * @param title New title of the window | |
100 | */ | |
101 | public void setTitle(String title) { | |
102 | this.title = title; | |
103 | invalidate(); | |
104 | } | |
105 | ||
106 | @Override | |
107 | public String getTitle() { | |
108 | return title; | |
109 | } | |
110 | ||
111 | @Override | |
112 | public boolean isVisible() { | |
113 | return visible; | |
114 | } | |
115 | ||
116 | @Override | |
117 | public void setVisible(boolean visible) { | |
118 | this.visible = visible; | |
119 | } | |
120 | @Override | |
121 | public void draw(TextGUIGraphics graphics) { | |
122 | if(!graphics.getSize().equals(lastKnownSize)) { | |
123 | getComponent().invalidate(); | |
124 | } | |
125 | setSize(graphics.getSize(), false); | |
b71d1368 | 126 | super.draw(graphics); |
a3b510ab NR |
127 | } |
128 | ||
129 | @Override | |
130 | public boolean handleInput(KeyStroke key) { | |
131 | boolean handled = super.handleInput(key); | |
132 | if(!handled && closeWindowWithEscape && key.getKeyType() == KeyType.Escape) { | |
133 | close(); | |
134 | return true; | |
135 | } | |
136 | return handled; | |
137 | } | |
138 | ||
139 | @Override | |
140 | public TerminalPosition toGlobal(TerminalPosition localPosition) { | |
141 | if(localPosition == null) { | |
142 | return null; | |
143 | } | |
144 | return lastKnownPosition.withRelative(contentOffset.withRelative(localPosition)); | |
145 | } | |
146 | ||
147 | @Override | |
148 | public TerminalPosition fromGlobal(TerminalPosition globalPosition) { | |
149 | if(globalPosition == null) { | |
150 | return null; | |
151 | } | |
152 | return globalPosition.withRelative( | |
153 | -lastKnownPosition.getColumn() - contentOffset.getColumn(), | |
154 | -lastKnownPosition.getRow() - contentOffset.getRow()); | |
155 | } | |
156 | ||
157 | @Override | |
158 | public TerminalSize getPreferredSize() { | |
159 | return contentHolder.getPreferredSize(); | |
160 | } | |
161 | ||
162 | @Override | |
163 | public void setHints(Collection<Hint> hints) { | |
164 | this.hints = new HashSet<Hint>(hints); | |
165 | invalidate(); | |
166 | } | |
167 | ||
168 | @Override | |
169 | public Set<Hint> getHints() { | |
170 | return Collections.unmodifiableSet(hints); | |
171 | } | |
172 | ||
173 | @Override | |
174 | public final TerminalPosition getPosition() { | |
175 | return lastKnownPosition; | |
176 | } | |
177 | ||
178 | @Override | |
179 | public final void setPosition(TerminalPosition topLeft) { | |
180 | this.lastKnownPosition = topLeft; | |
181 | } | |
182 | ||
183 | @Override | |
184 | public final TerminalSize getSize() { | |
185 | return lastKnownSize; | |
186 | } | |
187 | ||
188 | @Override | |
189 | public void setSize(TerminalSize size) { | |
190 | setSize(size, true); | |
191 | } | |
192 | ||
193 | private void setSize(TerminalSize size, boolean invalidate) { | |
194 | this.lastKnownSize = size; | |
195 | if(invalidate) { | |
196 | invalidate(); | |
197 | } | |
198 | } | |
199 | ||
200 | @Override | |
201 | public final TerminalSize getDecoratedSize() { | |
202 | return lastKnownDecoratedSize; | |
203 | } | |
204 | ||
205 | @Override | |
206 | public final void setDecoratedSize(TerminalSize decoratedSize) { | |
207 | this.lastKnownDecoratedSize = decoratedSize; | |
208 | } | |
209 | ||
210 | @Override | |
211 | public void setContentOffset(TerminalPosition offset) { | |
212 | this.contentOffset = offset; | |
213 | } | |
214 | ||
215 | @Override | |
216 | public void close() { | |
217 | if(textGUI != null) { | |
218 | textGUI.removeWindow(this); | |
219 | } | |
220 | setComponent(null); | |
221 | } | |
222 | ||
223 | @Override | |
224 | public void waitUntilClosed() { | |
225 | WindowBasedTextGUI textGUI = getTextGUI(); | |
226 | if(textGUI != null) { | |
227 | textGUI.waitForWindowToClose(this); | |
228 | } | |
229 | } | |
230 | } |