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