blob: 5034af6bf31f0c32fe7c8335d0bb2dcc4a416298 [file] [log] [blame]
Constantin Kaplinsky2844fd52008-04-14 08:02:25 +00001//
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
Constantin Kaplinsky90d8a502008-04-14 09:45:50 +000030package com.tightvnc.vncviewer;
31
Constantin Kaplinsky2844fd52008-04-14 08:02:25 +000032import java.awt.*;
33import java.awt.event.*;
34
35class OptionsFrame extends Frame
36 implements WindowListener, ActionListener, ItemListener {
37
38 static String[] names = {
39 "Encoding",
40 "Compression level",
41 "JPEG image quality",
42 "Cursor shape updates",
43 "Use CopyRect",
44 "Continuous updates",
45 "Restricted colors",
46 "Mouse buttons 2 and 3",
47 "View only",
enikey2659b592008-12-03 06:56:27 +000048 "Scaling factor",
Constantin Kaplinsky2844fd52008-04-14 08:02:25 +000049 "Scale remote cursor",
enikey2659b592008-12-03 06:56:27 +000050 "Share desktop"
Constantin Kaplinsky2844fd52008-04-14 08:02:25 +000051 };
52
53 static String[][] values = {
54 { "Auto", "Raw", "RRE", "CoRRE", "Hextile", "Zlib", "Tight", "ZRLE" },
55 { "Default", "1", "2", "3", "4", "5", "6", "7", "8", "9" },
56 { "JPEG off", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" },
57 { "Enable", "Ignore", "Disable" },
58 { "Yes", "No" },
59 { "Yes", "No" },
60 { "Yes", "No" },
61 { "Normal", "Reversed" },
62 { "Yes", "No" },
enikey2659b592008-12-03 06:56:27 +000063 { "Auto", "1%", "5%", "10%", "20%", "25%", "50%", "75%", "100%"},
Constantin Kaplinsky2844fd52008-04-14 08:02:25 +000064 { "No", "50%", "75%", "125%", "150%" },
enikey2659b592008-12-03 06:56:27 +000065 { "Yes", "No" }
Constantin Kaplinsky2844fd52008-04-14 08:02:25 +000066 };
67
68 final int
69 encodingIndex = 0,
70 compressLevelIndex = 1,
71 jpegQualityIndex = 2,
72 cursorUpdatesIndex = 3,
73 useCopyRectIndex = 4,
74 contUpdatesIndex = 5,
75 eightBitColorsIndex = 6,
76 mouseButtonIndex = 7,
77 viewOnlyIndex = 8,
enikey2659b592008-12-03 06:56:27 +000078 scalingFactorIndex = 9,
79 scaleCursorIndex = 10,
80 shareDesktopIndex = 11;
Constantin Kaplinsky2844fd52008-04-14 08:02:25 +000081
82 Label[] labels = new Label[names.length];
83 Choice[] choices = new Choice[names.length];
84 Button closeButton;
85 VncViewer viewer;
86
87
88 //
89 // The actual data which other classes look at:
90 //
91
92 int preferredEncoding;
93 int compressLevel;
94 int jpegQuality;
95 boolean useCopyRect;
96 boolean continuousUpdates;
97 boolean requestCursorUpdates;
98 boolean ignoreCursorUpdates;
99
100 boolean eightBitColors;
101
102 boolean reverseMouseButtons2And3;
103 boolean shareDesktop;
104 boolean viewOnly;
105 int scaleCursor;
106
107 boolean autoScale;
108 int scalingFactor;
109
110 //
111 // Constructor. Set up the labels and choices from the names and values
112 // arrays.
113 //
114
115 OptionsFrame(VncViewer v) {
116 super("TightVNC Options");
117
118 viewer = v;
119
120 GridBagLayout gridbag = new GridBagLayout();
121 setLayout(gridbag);
122
123 GridBagConstraints gbc = new GridBagConstraints();
124 gbc.fill = GridBagConstraints.BOTH;
125
126 for (int i = 0; i < names.length; i++) {
127 labels[i] = new Label(names[i]);
128 gbc.gridwidth = 1;
129 gridbag.setConstraints(labels[i],gbc);
130 add(labels[i]);
131
132 choices[i] = new Choice();
133 gbc.gridwidth = GridBagConstraints.REMAINDER;
134 gridbag.setConstraints(choices[i],gbc);
135 add(choices[i]);
136 choices[i].addItemListener(this);
137
138 for (int j = 0; j < values[i].length; j++) {
139 choices[i].addItem(values[i][j]);
140 }
141 }
142
143 closeButton = new Button("Close");
144 gbc.gridwidth = GridBagConstraints.REMAINDER;
145 gridbag.setConstraints(closeButton, gbc);
146 add(closeButton);
147 closeButton.addActionListener(this);
148
149 pack();
150
151 addWindowListener(this);
152
153 // Set up defaults
154
155 choices[encodingIndex].select("Auto");
156 choices[compressLevelIndex].select("Default");
157 choices[jpegQualityIndex].select("6");
158 choices[cursorUpdatesIndex].select("Enable");
159 choices[useCopyRectIndex].select("Yes");
160 choices[contUpdatesIndex].select("No");
161 choices[eightBitColorsIndex].select("No");
162 choices[mouseButtonIndex].select("Normal");
163 choices[viewOnlyIndex].select("No");
164 choices[scaleCursorIndex].select("No");
165 choices[shareDesktopIndex].select("Yes");
166
167 // But let them be overridden by parameters
168
169 for (int i = 0; i < names.length; i++) {
170 String s = viewer.readParameter(names[i], false);
171 if (s != null) {
172 for (int j = 0; j < values[i].length; j++) {
173 if (s.equalsIgnoreCase(values[i][j])) {
174 choices[i].select(j);
175 }
176 }
177 }
178 }
179
enikey2659b592008-12-03 06:56:27 +0000180 // Get scaling factor from parameters and set it
181 // to gui and class member scalingFactor
182
183 String s = viewer.readParameter("Scaling Factor", false);
184 if (s == null) s = "100%";
185 setScalingFactor(s);
enikey73683202008-12-03 09:17:25 +0000186 if (autoScale) {
187 choices[scalingFactorIndex].select("Auto");
enikey2659b592008-12-03 06:56:27 +0000188 } else {
189 choices[scalingFactorIndex].select(s);
190 }
Constantin Kaplinsky2844fd52008-04-14 08:02:25 +0000191
enikey2659b592008-12-03 06:56:27 +0000192 // Make the booleans and encodings array correspond to the state of the GUI
193
194 setEncodings();
195 setColorFormat();
196 setContinuousUpdates();
197 setOtherOptions();
198 }
199
200 //
201 // Set scaling factor class member value
202 //
203
204 void setScalingFactor(int sf) {
205 setScalingFactor(((Integer)sf).toString());
206 }
207
208 void setScalingFactor(String s) {
Constantin Kaplinsky2844fd52008-04-14 08:02:25 +0000209 autoScale = false;
210 scalingFactor = 100;
Constantin Kaplinsky2844fd52008-04-14 08:02:25 +0000211 if (s != null) {
212 if (s.equalsIgnoreCase("Auto")) {
213 autoScale = true;
214 } else {
215 // Remove the '%' char at the end of string if present.
216 if (s.charAt(s.length() - 1) == '%') {
217 s = s.substring(0, s.length() - 1);
218 }
219 // Convert to an integer.
220 try {
221 scalingFactor = Integer.parseInt(s);
222 }
223 catch (NumberFormatException e) {
224 scalingFactor = 100;
225 }
226 // Make sure scalingFactor is in the range of [1..1000].
227 if (scalingFactor < 1) {
228 scalingFactor = 1;
229 } else if (scalingFactor > 1000) {
230 scalingFactor = 1000;
231 }
232 }
233 }
Constantin Kaplinsky2844fd52008-04-14 08:02:25 +0000234 }
235
236
237 //
238 // Disable the shareDesktop option
239 //
240
241 void disableShareDesktop() {
242 labels[shareDesktopIndex].setEnabled(false);
243 choices[shareDesktopIndex].setEnabled(false);
244 }
245
246
247 //
248 // Disable the "Continuous updates" option. This method is called
249 // when we figure out that the server does not support corresponding
250 // protocol extensions.
251 //
252
253 void disableContUpdates() {
254 labels[contUpdatesIndex].setEnabled(false);
255 choices[contUpdatesIndex].setEnabled(false);
256 choices[contUpdatesIndex].select("No");
257 continuousUpdates = false;
258 }
259
260
261 //
262 // setEncodings looks at the encoding, compression level, JPEG
263 // quality level, cursor shape updates and copyRect choices and sets
264 // corresponding variables properly. Then it calls the VncViewer's
265 // setEncodings method to send a SetEncodings message to the RFB
266 // server.
267 //
268
269 void setEncodings() {
270 useCopyRect = choices[useCopyRectIndex].getSelectedItem().equals("Yes");
271
272 preferredEncoding = RfbProto.EncodingRaw;
273 boolean enableCompressLevel = false;
274 boolean enableQualityLevel = false;
275
276 if (choices[encodingIndex].getSelectedItem().equals("RRE")) {
277 preferredEncoding = RfbProto.EncodingRRE;
278 } else if (choices[encodingIndex].getSelectedItem().equals("CoRRE")) {
279 preferredEncoding = RfbProto.EncodingCoRRE;
280 } else if (choices[encodingIndex].getSelectedItem().equals("Hextile")) {
281 preferredEncoding = RfbProto.EncodingHextile;
282 } else if (choices[encodingIndex].getSelectedItem().equals("ZRLE")) {
283 preferredEncoding = RfbProto.EncodingZRLE;
284 } else if (choices[encodingIndex].getSelectedItem().equals("Zlib")) {
285 preferredEncoding = RfbProto.EncodingZlib;
286 enableCompressLevel = true;
287 } else if (choices[encodingIndex].getSelectedItem().equals("Tight")) {
288 preferredEncoding = RfbProto.EncodingTight;
289 enableCompressLevel = true;
290 enableQualityLevel = !eightBitColors;
291 } else if (choices[encodingIndex].getSelectedItem().equals("Auto")) {
292 preferredEncoding = -1;
293 enableQualityLevel = !eightBitColors;
294 }
295
296 // Handle compression level setting.
297
298 try {
299 compressLevel =
300 Integer.parseInt(choices[compressLevelIndex].getSelectedItem());
301 }
302 catch (NumberFormatException e) {
303 compressLevel = -1;
304 }
305 if (compressLevel < 1 || compressLevel > 9) {
306 compressLevel = -1;
307 }
308 labels[compressLevelIndex].setEnabled(enableCompressLevel);
309 choices[compressLevelIndex].setEnabled(enableCompressLevel);
310
311 // Handle JPEG quality setting.
312
313 try {
314 jpegQuality =
315 Integer.parseInt(choices[jpegQualityIndex].getSelectedItem());
316 }
317 catch (NumberFormatException e) {
318 jpegQuality = -1;
319 }
320 if (jpegQuality < 0 || jpegQuality > 9) {
321 jpegQuality = -1;
322 }
323 labels[jpegQualityIndex].setEnabled(enableQualityLevel);
324 choices[jpegQualityIndex].setEnabled(enableQualityLevel);
325
326 // Request cursor shape updates if necessary.
327
328 requestCursorUpdates =
329 !choices[cursorUpdatesIndex].getSelectedItem().equals("Disable");
330
331 if (requestCursorUpdates) {
332 ignoreCursorUpdates =
333 choices[cursorUpdatesIndex].getSelectedItem().equals("Ignore");
334 }
335
336 viewer.setEncodings();
337 }
338
339 //
340 // setColorFormat sets eightBitColors variable depending on the GUI
341 // setting, causing switches between 8-bit and 24-bit colors mode if
342 // necessary.
343 //
344
345 void setColorFormat() {
346
347 eightBitColors =
348 choices[eightBitColorsIndex].getSelectedItem().equals("Yes");
349
350 boolean enableJPEG = !eightBitColors &&
351 (choices[encodingIndex].getSelectedItem().equals("Tight") ||
352 choices[encodingIndex].getSelectedItem().equals("Auto"));
353
354 labels[jpegQualityIndex].setEnabled(enableJPEG);
355 choices[jpegQualityIndex].setEnabled(enableJPEG);
356 }
357
358 //
359 // setContinuousUpdates sets continuousUpdates variable depending on
360 // the GUI setting. VncViewer monitors the state of this variable and
361 // send corresponding protocol messages to the server when necessary.
362 //
363
364 void setContinuousUpdates() {
365
366 continuousUpdates =
367 choices[contUpdatesIndex].getSelectedItem().equals("Yes");
368 }
369
370 //
371 // setOtherOptions looks at the "other" choices (ones that do not
372 // cause sending any protocol messages) and sets the boolean flags
373 // appropriately.
374 //
375
376 void setOtherOptions() {
377
378 reverseMouseButtons2And3
379 = choices[mouseButtonIndex].getSelectedItem().equals("Reversed");
380
381 viewOnly
382 = choices[viewOnlyIndex].getSelectedItem().equals("Yes");
383 if (viewer.vc != null)
384 viewer.vc.enableInput(!viewOnly);
385
386 shareDesktop
387 = choices[shareDesktopIndex].getSelectedItem().equals("Yes");
388
389 String scaleString = choices[scaleCursorIndex].getSelectedItem();
390 if (scaleString.endsWith("%"))
391 scaleString = scaleString.substring(0, scaleString.length() - 1);
392 try {
393 scaleCursor = Integer.parseInt(scaleString);
394 }
395 catch (NumberFormatException e) {
396 scaleCursor = 0;
397 }
398 if (scaleCursor < 10 || scaleCursor > 500) {
399 scaleCursor = 0;
400 }
401 if (requestCursorUpdates && !ignoreCursorUpdates && !viewOnly) {
402 labels[scaleCursorIndex].setEnabled(true);
403 choices[scaleCursorIndex].setEnabled(true);
404 } else {
405 labels[scaleCursorIndex].setEnabled(false);
406 choices[scaleCursorIndex].setEnabled(false);
407 }
408 if (viewer.vc != null)
409 viewer.vc.createSoftCursor(); // update cursor scaling
410 }
411
412
413 //
414 // Respond to actions on Choice controls
415 //
416
417 public void itemStateChanged(ItemEvent evt) {
418 Object source = evt.getSource();
419
420 if (source == choices[encodingIndex] ||
421 source == choices[compressLevelIndex] ||
422 source == choices[jpegQualityIndex] ||
423 source == choices[cursorUpdatesIndex] ||
424 source == choices[useCopyRectIndex]) {
425
426 setEncodings();
427
428 if (source == choices[cursorUpdatesIndex]) {
429 setOtherOptions(); // update scaleCursor state
430 }
431
432 } else if (source == choices[eightBitColorsIndex]) {
433
434 setColorFormat();
435
436 } else if (source == choices[contUpdatesIndex]) {
437
438 setContinuousUpdates();
439
440 } else if (source == choices[mouseButtonIndex] ||
441 source == choices[shareDesktopIndex] ||
442 source == choices[viewOnlyIndex] ||
443 source == choices[scaleCursorIndex]) {
444
445 setOtherOptions();
446
enikey2659b592008-12-03 06:56:27 +0000447 } else if (source == choices[scalingFactorIndex]){
448 // Tell VNC canvas that scaling factor has changed
449 setScalingFactor(choices[scalingFactorIndex].getSelectedItem());
enikey73683202008-12-03 09:17:25 +0000450 if (viewer.vc != null)
451 viewer.vc.setScalingFactor(scalingFactor);
Constantin Kaplinsky2844fd52008-04-14 08:02:25 +0000452 }
453 }
454
455 //
456 // Respond to button press
457 //
458
459 public void actionPerformed(ActionEvent evt) {
460 if (evt.getSource() == closeButton)
461 setVisible(false);
462 }
463
464 //
465 // Respond to window events
466 //
467
468 public void windowClosing(WindowEvent evt) {
469 setVisible(false);
470 }
471
472 public void windowActivated(WindowEvent evt) {}
473 public void windowDeactivated(WindowEvent evt) {}
474 public void windowOpened(WindowEvent evt) {}
475 public void windowClosed(WindowEvent evt) {}
476 public void windowIconified(WindowEvent evt) {}
477 public void windowDeiconified(WindowEvent evt) {}
478}