1 | // |
---|
2 | // Copyright (C) 2001 HorizonLive.com, Inc. All Rights Reserved. |
---|
3 | // Copyright (C) 2001 Constantin Kaplinsky. All Rights Reserved. |
---|
4 | // Copyright (C) 2000 Tridia Corporation. All Rights Reserved. |
---|
5 | // Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. |
---|
6 | // |
---|
7 | // This is free software; you can redistribute it and/or modify |
---|
8 | // it under the terms of the GNU General Public License as published by |
---|
9 | // the Free Software Foundation; either version 2 of the License, or |
---|
10 | // (at your option) any later version. |
---|
11 | // |
---|
12 | // This software is distributed in the hope that it will be useful, |
---|
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
15 | // GNU General Public License for more details. |
---|
16 | // |
---|
17 | // You should have received a copy of the GNU General Public License |
---|
18 | // along with this software; if not, write to the Free Software |
---|
19 | // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
---|
20 | // USA. |
---|
21 | // |
---|
22 | |
---|
23 | // |
---|
24 | // Options frame. |
---|
25 | // |
---|
26 | // This deals with all the options the user can play with. |
---|
27 | // It sets the encodings array and some booleans. |
---|
28 | // |
---|
29 | |
---|
30 | import java.awt.*; |
---|
31 | import java.awt.event.*; |
---|
32 | |
---|
33 | class OptionsFrame extends Frame |
---|
34 | implements WindowListener, ActionListener, ItemListener { |
---|
35 | |
---|
36 | static String[] names = { |
---|
37 | "Encoding", |
---|
38 | "Compression level", |
---|
39 | "JPEG image quality", |
---|
40 | "Cursor shape updates", |
---|
41 | "Use CopyRect", |
---|
42 | "Restricted colors", |
---|
43 | "Mouse buttons 2 and 3", |
---|
44 | "View only", |
---|
45 | "Scale remote cursor", |
---|
46 | "Share desktop", |
---|
47 | }; |
---|
48 | |
---|
49 | static String[][] values = { |
---|
50 | { "Auto", "Raw", "RRE", "CoRRE", "Hextile", "Zlib", "Tight", "ZRLE" }, |
---|
51 | { "Default", "1", "2", "3", "4", "5", "6", "7", "8", "9" }, |
---|
52 | { "JPEG off", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }, |
---|
53 | { "Enable", "Ignore", "Disable" }, |
---|
54 | { "Yes", "No" }, |
---|
55 | { "Yes", "No" }, |
---|
56 | { "Normal", "Reversed" }, |
---|
57 | { "Yes", "No" }, |
---|
58 | { "No", "50%", "75%", "125%", "150%" }, |
---|
59 | { "Yes", "No" }, |
---|
60 | }; |
---|
61 | |
---|
62 | final int |
---|
63 | encodingIndex = 0, |
---|
64 | compressLevelIndex = 1, |
---|
65 | jpegQualityIndex = 2, |
---|
66 | cursorUpdatesIndex = 3, |
---|
67 | useCopyRectIndex = 4, |
---|
68 | eightBitColorsIndex = 5, |
---|
69 | mouseButtonIndex = 6, |
---|
70 | viewOnlyIndex = 7, |
---|
71 | scaleCursorIndex = 8, |
---|
72 | shareDesktopIndex = 9; |
---|
73 | |
---|
74 | Label[] labels = new Label[names.length]; |
---|
75 | Choice[] choices = new Choice[names.length]; |
---|
76 | Button closeButton; |
---|
77 | VncViewer viewer; |
---|
78 | |
---|
79 | |
---|
80 | // |
---|
81 | // The actual data which other classes look at: |
---|
82 | // |
---|
83 | |
---|
84 | int preferredEncoding; |
---|
85 | int compressLevel; |
---|
86 | int jpegQuality; |
---|
87 | boolean useCopyRect; |
---|
88 | boolean requestCursorUpdates; |
---|
89 | boolean ignoreCursorUpdates; |
---|
90 | |
---|
91 | boolean eightBitColors; |
---|
92 | |
---|
93 | boolean reverseMouseButtons2And3; |
---|
94 | boolean shareDesktop; |
---|
95 | boolean viewOnly; |
---|
96 | int scaleCursor; |
---|
97 | |
---|
98 | boolean autoScale; |
---|
99 | int scalingFactor; |
---|
100 | |
---|
101 | // |
---|
102 | // Constructor. Set up the labels and choices from the names and values |
---|
103 | // arrays. |
---|
104 | // |
---|
105 | |
---|
106 | OptionsFrame(VncViewer v) { |
---|
107 | super("TightVNC Options"); |
---|
108 | |
---|
109 | viewer = v; |
---|
110 | |
---|
111 | GridBagLayout gridbag = new GridBagLayout(); |
---|
112 | setLayout(gridbag); |
---|
113 | |
---|
114 | GridBagConstraints gbc = new GridBagConstraints(); |
---|
115 | gbc.fill = GridBagConstraints.BOTH; |
---|
116 | |
---|
117 | for (int i = 0; i < names.length; i++) { |
---|
118 | labels[i] = new Label(names[i]); |
---|
119 | gbc.gridwidth = 1; |
---|
120 | gridbag.setConstraints(labels[i],gbc); |
---|
121 | add(labels[i]); |
---|
122 | |
---|
123 | choices[i] = new Choice(); |
---|
124 | gbc.gridwidth = GridBagConstraints.REMAINDER; |
---|
125 | gridbag.setConstraints(choices[i],gbc); |
---|
126 | add(choices[i]); |
---|
127 | choices[i].addItemListener(this); |
---|
128 | |
---|
129 | for (int j = 0; j < values[i].length; j++) { |
---|
130 | choices[i].addItem(values[i][j]); |
---|
131 | } |
---|
132 | } |
---|
133 | |
---|
134 | closeButton = new Button("Close"); |
---|
135 | gbc.gridwidth = GridBagConstraints.REMAINDER; |
---|
136 | gridbag.setConstraints(closeButton, gbc); |
---|
137 | add(closeButton); |
---|
138 | closeButton.addActionListener(this); |
---|
139 | |
---|
140 | pack(); |
---|
141 | |
---|
142 | addWindowListener(this); |
---|
143 | |
---|
144 | // Set up defaults |
---|
145 | |
---|
146 | choices[encodingIndex].select("Auto"); |
---|
147 | choices[compressLevelIndex].select("Default"); |
---|
148 | choices[jpegQualityIndex].select("6"); |
---|
149 | choices[cursorUpdatesIndex].select("Enable"); |
---|
150 | choices[useCopyRectIndex].select("Yes"); |
---|
151 | choices[eightBitColorsIndex].select("No"); |
---|
152 | choices[mouseButtonIndex].select("Normal"); |
---|
153 | choices[viewOnlyIndex].select("No"); |
---|
154 | choices[scaleCursorIndex].select("No"); |
---|
155 | choices[shareDesktopIndex].select("Yes"); |
---|
156 | |
---|
157 | // But let them be overridden by parameters |
---|
158 | |
---|
159 | for (int i = 0; i < names.length; i++) { |
---|
160 | String s = viewer.readParameter(names[i], false); |
---|
161 | if (s != null) { |
---|
162 | for (int j = 0; j < values[i].length; j++) { |
---|
163 | if (s.equalsIgnoreCase(values[i][j])) { |
---|
164 | choices[i].select(j); |
---|
165 | } |
---|
166 | } |
---|
167 | } |
---|
168 | } |
---|
169 | |
---|
170 | // FIXME: Provide some sort of GUI for "Scaling Factor". |
---|
171 | |
---|
172 | autoScale = false; |
---|
173 | scalingFactor = 100; |
---|
174 | String s = viewer.readParameter("Scaling Factor", false); |
---|
175 | if (s != null) { |
---|
176 | if (s.equalsIgnoreCase("Auto")) { |
---|
177 | autoScale = true; |
---|
178 | } else { |
---|
179 | // Remove the '%' char at the end of string if present. |
---|
180 | if (s.charAt(s.length() - 1) == '%') { |
---|
181 | s = s.substring(0, s.length() - 1); |
---|
182 | } |
---|
183 | // Convert to an integer. |
---|
184 | try { |
---|
185 | scalingFactor = Integer.parseInt(s); |
---|
186 | } |
---|
187 | catch (NumberFormatException e) { |
---|
188 | scalingFactor = 100; |
---|
189 | } |
---|
190 | // Make sure scalingFactor is in the range of [1..1000]. |
---|
191 | if (scalingFactor < 1) { |
---|
192 | scalingFactor = 1; |
---|
193 | } else if (scalingFactor > 1000) { |
---|
194 | scalingFactor = 1000; |
---|
195 | } |
---|
196 | } |
---|
197 | } |
---|
198 | |
---|
199 | // Make the booleans and encodings array correspond to the state of the GUI |
---|
200 | |
---|
201 | setEncodings(); |
---|
202 | setColorFormat(); |
---|
203 | setOtherOptions(); |
---|
204 | } |
---|
205 | |
---|
206 | |
---|
207 | // |
---|
208 | // Disable the shareDesktop option |
---|
209 | // |
---|
210 | |
---|
211 | void disableShareDesktop() { |
---|
212 | labels[shareDesktopIndex].setEnabled(false); |
---|
213 | choices[shareDesktopIndex].setEnabled(false); |
---|
214 | } |
---|
215 | |
---|
216 | |
---|
217 | // |
---|
218 | // setEncodings looks at the encoding, compression level, JPEG |
---|
219 | // quality level, cursor shape updates and copyRect choices and sets |
---|
220 | // corresponding variables properly. Then it calls the VncViewer's |
---|
221 | // setEncodings method to send a SetEncodings message to the RFB |
---|
222 | // server. |
---|
223 | // |
---|
224 | |
---|
225 | void setEncodings() { |
---|
226 | useCopyRect = choices[useCopyRectIndex].getSelectedItem().equals("Yes"); |
---|
227 | |
---|
228 | preferredEncoding = RfbProto.EncodingRaw; |
---|
229 | boolean enableCompressLevel = false; |
---|
230 | boolean enableQualityLevel = false; |
---|
231 | |
---|
232 | if (choices[encodingIndex].getSelectedItem().equals("RRE")) { |
---|
233 | preferredEncoding = RfbProto.EncodingRRE; |
---|
234 | } else if (choices[encodingIndex].getSelectedItem().equals("CoRRE")) { |
---|
235 | preferredEncoding = RfbProto.EncodingCoRRE; |
---|
236 | } else if (choices[encodingIndex].getSelectedItem().equals("Hextile")) { |
---|
237 | preferredEncoding = RfbProto.EncodingHextile; |
---|
238 | } else if (choices[encodingIndex].getSelectedItem().equals("ZRLE")) { |
---|
239 | preferredEncoding = RfbProto.EncodingZRLE; |
---|
240 | } else if (choices[encodingIndex].getSelectedItem().equals("Zlib")) { |
---|
241 | preferredEncoding = RfbProto.EncodingZlib; |
---|
242 | enableCompressLevel = true; |
---|
243 | } else if (choices[encodingIndex].getSelectedItem().equals("Tight")) { |
---|
244 | preferredEncoding = RfbProto.EncodingTight; |
---|
245 | enableCompressLevel = true; |
---|
246 | enableQualityLevel = !eightBitColors; |
---|
247 | } else if (choices[encodingIndex].getSelectedItem().equals("Auto")) { |
---|
248 | preferredEncoding = -1; |
---|
249 | enableQualityLevel = !eightBitColors; |
---|
250 | } |
---|
251 | |
---|
252 | // Handle compression level setting. |
---|
253 | |
---|
254 | try { |
---|
255 | compressLevel = |
---|
256 | Integer.parseInt(choices[compressLevelIndex].getSelectedItem()); |
---|
257 | } |
---|
258 | catch (NumberFormatException e) { |
---|
259 | compressLevel = -1; |
---|
260 | } |
---|
261 | if (compressLevel < 1 || compressLevel > 9) { |
---|
262 | compressLevel = -1; |
---|
263 | } |
---|
264 | labels[compressLevelIndex].setEnabled(enableCompressLevel); |
---|
265 | choices[compressLevelIndex].setEnabled(enableCompressLevel); |
---|
266 | |
---|
267 | // Handle JPEG quality setting. |
---|
268 | |
---|
269 | try { |
---|
270 | jpegQuality = |
---|
271 | Integer.parseInt(choices[jpegQualityIndex].getSelectedItem()); |
---|
272 | } |
---|
273 | catch (NumberFormatException e) { |
---|
274 | jpegQuality = -1; |
---|
275 | } |
---|
276 | if (jpegQuality < 0 || jpegQuality > 9) { |
---|
277 | jpegQuality = -1; |
---|
278 | } |
---|
279 | labels[jpegQualityIndex].setEnabled(enableQualityLevel); |
---|
280 | choices[jpegQualityIndex].setEnabled(enableQualityLevel); |
---|
281 | |
---|
282 | // Request cursor shape updates if necessary. |
---|
283 | |
---|
284 | requestCursorUpdates = |
---|
285 | !choices[cursorUpdatesIndex].getSelectedItem().equals("Disable"); |
---|
286 | |
---|
287 | if (requestCursorUpdates) { |
---|
288 | ignoreCursorUpdates = |
---|
289 | choices[cursorUpdatesIndex].getSelectedItem().equals("Ignore"); |
---|
290 | } |
---|
291 | |
---|
292 | viewer.setEncodings(); |
---|
293 | } |
---|
294 | |
---|
295 | // |
---|
296 | // setColorFormat sets eightBitColors variable depending on the GUI |
---|
297 | // setting, causing switches between 8-bit and 24-bit colors mode if |
---|
298 | // necessary. |
---|
299 | // |
---|
300 | |
---|
301 | void setColorFormat() { |
---|
302 | |
---|
303 | eightBitColors = |
---|
304 | choices[eightBitColorsIndex].getSelectedItem().equals("Yes"); |
---|
305 | |
---|
306 | boolean enableJPEG = !eightBitColors && |
---|
307 | (choices[encodingIndex].getSelectedItem().equals("Tight") || |
---|
308 | choices[encodingIndex].getSelectedItem().equals("Auto")); |
---|
309 | |
---|
310 | labels[jpegQualityIndex].setEnabled(enableJPEG); |
---|
311 | choices[jpegQualityIndex].setEnabled(enableJPEG); |
---|
312 | } |
---|
313 | |
---|
314 | // |
---|
315 | // setOtherOptions looks at the "other" choices (ones which don't set the |
---|
316 | // encoding or the color format) and sets the boolean flags appropriately. |
---|
317 | // |
---|
318 | |
---|
319 | void setOtherOptions() { |
---|
320 | |
---|
321 | reverseMouseButtons2And3 |
---|
322 | = choices[mouseButtonIndex].getSelectedItem().equals("Reversed"); |
---|
323 | |
---|
324 | viewOnly |
---|
325 | = choices[viewOnlyIndex].getSelectedItem().equals("Yes"); |
---|
326 | if (viewer.vc != null) |
---|
327 | viewer.vc.enableInput(!viewOnly); |
---|
328 | |
---|
329 | shareDesktop |
---|
330 | = choices[shareDesktopIndex].getSelectedItem().equals("Yes"); |
---|
331 | |
---|
332 | String scaleString = choices[scaleCursorIndex].getSelectedItem(); |
---|
333 | if (scaleString.endsWith("%")) |
---|
334 | scaleString = scaleString.substring(0, scaleString.length() - 1); |
---|
335 | try { |
---|
336 | scaleCursor = Integer.parseInt(scaleString); |
---|
337 | } |
---|
338 | catch (NumberFormatException e) { |
---|
339 | scaleCursor = 0; |
---|
340 | } |
---|
341 | if (scaleCursor < 10 || scaleCursor > 500) { |
---|
342 | scaleCursor = 0; |
---|
343 | } |
---|
344 | if (requestCursorUpdates && !ignoreCursorUpdates && !viewOnly) { |
---|
345 | labels[scaleCursorIndex].setEnabled(true); |
---|
346 | choices[scaleCursorIndex].setEnabled(true); |
---|
347 | } else { |
---|
348 | labels[scaleCursorIndex].setEnabled(false); |
---|
349 | choices[scaleCursorIndex].setEnabled(false); |
---|
350 | } |
---|
351 | if (viewer.vc != null) |
---|
352 | viewer.vc.createSoftCursor(); // update cursor scaling |
---|
353 | } |
---|
354 | |
---|
355 | |
---|
356 | // |
---|
357 | // Respond to actions on Choice controls |
---|
358 | // |
---|
359 | |
---|
360 | public void itemStateChanged(ItemEvent evt) { |
---|
361 | Object source = evt.getSource(); |
---|
362 | |
---|
363 | if (source == choices[encodingIndex] || |
---|
364 | source == choices[compressLevelIndex] || |
---|
365 | source == choices[jpegQualityIndex] || |
---|
366 | source == choices[cursorUpdatesIndex] || |
---|
367 | source == choices[useCopyRectIndex]) { |
---|
368 | |
---|
369 | setEncodings(); |
---|
370 | |
---|
371 | if (source == choices[cursorUpdatesIndex]) { |
---|
372 | setOtherOptions(); // update scaleCursor state |
---|
373 | } |
---|
374 | |
---|
375 | } else if (source == choices[eightBitColorsIndex]) { |
---|
376 | |
---|
377 | setColorFormat(); |
---|
378 | |
---|
379 | } else if (source == choices[mouseButtonIndex] || |
---|
380 | source == choices[shareDesktopIndex] || |
---|
381 | source == choices[viewOnlyIndex] || |
---|
382 | source == choices[scaleCursorIndex]) { |
---|
383 | |
---|
384 | setOtherOptions(); |
---|
385 | } |
---|
386 | } |
---|
387 | |
---|
388 | // |
---|
389 | // Respond to button press |
---|
390 | // |
---|
391 | |
---|
392 | public void actionPerformed(ActionEvent evt) { |
---|
393 | if (evt.getSource() == closeButton) |
---|
394 | setVisible(false); |
---|
395 | } |
---|
396 | |
---|
397 | // |
---|
398 | // Respond to window events |
---|
399 | // |
---|
400 | |
---|
401 | public void windowClosing(WindowEvent evt) { |
---|
402 | setVisible(false); |
---|
403 | } |
---|
404 | |
---|
405 | public void windowActivated(WindowEvent evt) {} |
---|
406 | public void windowDeactivated(WindowEvent evt) {} |
---|
407 | public void windowOpened(WindowEvent evt) {} |
---|
408 | public void windowClosed(WindowEvent evt) {} |
---|
409 | public void windowIconified(WindowEvent evt) {} |
---|
410 | public void windowDeiconified(WindowEvent evt) {} |
---|
411 | } |
---|