Updated to openjdk
[invirt/packages/invirt-vnc-client.git] / OptionsFrame.java
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 }