1 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
2  * Copyright (C) 2011-2016 Brian P. Hinz
3  *
4  * This is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This software 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 General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this software; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17  * USA.
18  */
19 
20 package com.tigervnc.vncviewer;
21 
22 import java.awt.*;
23 import java.awt.event.*;
24 import java.io.File;
25 import java.nio.CharBuffer;
26 import javax.swing.*;
27 import javax.swing.border.*;
28 import javax.swing.filechooser.*;
29 import javax.swing.WindowConstants.*;
30 import java.util.*;
31 
32 import com.tigervnc.rfb.*;
33 
34 import static java.awt.GridBagConstraints.HORIZONTAL;
35 import static java.awt.GridBagConstraints.LINE_START;
36 import static java.awt.GridBagConstraints.LINE_END;
37 import static java.awt.GridBagConstraints.NONE;
38 import static java.awt.GridBagConstraints.REMAINDER;
39 
40 import static com.tigervnc.vncviewer.Parameters.*;
41 
42 class ServerDialog extends Dialog implements Runnable {
43 
44   @SuppressWarnings({"unchecked","rawtypes"})
ServerDialog(String defaultServerName, CharBuffer vncServerName)45   public ServerDialog(String defaultServerName,
46                       CharBuffer vncServerName) {
47     super(true);
48     this.vncServerName = vncServerName;
49     setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
50     setTitle("VNC Viewer: Connection Details");
51     setResizable(false);
52     addWindowListener(new WindowAdapter() {
53       public void windowClosing(WindowEvent e) {
54         endDialog();
55         System.exit(1);
56       }
57     });
58 
59     JLabel serverLabel = new JLabel("VNC server:", JLabel.RIGHT);
60     String valueStr = new String(defaultServerName);
61     ArrayList<String> servernames = new ArrayList<String>();
62     if (!valueStr.isEmpty())
63       servernames.add(valueStr);
64     String history = UserPreferences.get("ServerDialog", "history");
65     if (history != null) {
66       for (String s : history.split(",")) {
67         if (servernames.indexOf(s) < 0)
68           servernames.add(s);
69       }
70     }
71     serverName = new MyJComboBox(servernames.toArray());
72     serverName.addActionListener(new ActionListener() {
73       public void actionPerformed(ActionEvent e) {
74         JComboBox s = (JComboBox)e.getSource();
75         if (e.getActionCommand().equals("comboBoxEdited")) {
76           s.insertItemAt(editor.getItem(), 0);
77           s.setSelectedIndex(0);
78         }
79       }
80     });
81     if (servernames.size() == 0)
82       serverName.setPrototypeDisplayValue("255.255.255.255:5900");
83 
84     serverName.setEditable(true);
85     editor = serverName.getEditor();
86     editor.getEditorComponent().addKeyListener(new KeyListener() {
87       public void keyTyped(KeyEvent e) {}
88       public void keyReleased(KeyEvent e) {}
89       public void keyPressed(KeyEvent e) {
90         if (KeyMap.get_keycode_fallback_extended(e) == KeyEvent.VK_ENTER) {
91           serverName.insertItemAt(editor.getItem(), 0);
92           serverName.setSelectedIndex(0);
93           handleConnect();
94         }
95       }
96     });
97 
98     Container contentPane = this.getContentPane();
99     contentPane.setLayout(new GridBagLayout());
100 
101     JLabel icon = new JLabel(VncViewer.logoIcon);
102     optionsButton = new JButton("Options...");
103     optionsButton.addActionListener(new ActionListener() {
104       public void actionPerformed(ActionEvent e) {
105         handleOptions();
106       }
107     });
108     JButton loadButton = new JButton("Load...");
109     loadButton.addActionListener(new ActionListener() {
110       public void actionPerformed(ActionEvent e) {
111         handleLoad();
112       }
113     });
114     JButton saveAsButton = new JButton("Save As...");
115     saveAsButton.addActionListener(new ActionListener() {
116       public void actionPerformed(ActionEvent e) {
117         handleSaveAs();
118       }
119     });
120     aboutButton = new JButton("About...");
121     aboutButton.addActionListener(new ActionListener() {
122       public void actionPerformed(ActionEvent e) {
123         handleAbout();
124       }
125     });
126     cancelButton = new JButton("Cancel");
127     cancelButton.addActionListener(new ActionListener() {
128       public void actionPerformed(ActionEvent e) {
129         handleCancel();
130       }
131     });
132     connectButton = new JButton("Connect   \u21B5");
133     connectButton.addActionListener(new ActionListener() {
134       public void actionPerformed(ActionEvent e) {
135         handleConnect();
136       }
137     });
138 
139     contentPane.add(icon,
140                     new GridBagConstraints(0, 0,
141                                            1, 1,
142                                            LIGHT, LIGHT,
143                                            LINE_START, NONE,
144                                            new Insets(5, 5, 5, 5),
145                                            NONE, NONE));
146     contentPane.add(serverLabel,
147                     new GridBagConstraints(1, 0,
148                                            1, 1,
149                                            LIGHT, LIGHT,
150                                            LINE_START, NONE,
151                                            new Insets(5, 10, 5, 5),
152                                            NONE, NONE));
153     contentPane.add(serverName,
154                     new GridBagConstraints(2, 0,
155                                            REMAINDER, 1,
156                                            HEAVY, LIGHT,
157                                            LINE_START, HORIZONTAL,
158                                            new Insets(5, 0, 5, 5),
159                                            NONE, NONE));
160     JPanel buttonPane1 = new JPanel();
161     Box box = Box.createHorizontalBox();
162     JSeparator separator1 = new JSeparator();
163     JSeparator separator2 = new JSeparator();
164     GroupLayout layout = new GroupLayout(buttonPane1);
165     buttonPane1.setLayout(layout);
166     layout.setAutoCreateGaps(false);
167     layout.setAutoCreateContainerGaps(false);
168 		layout.setHorizontalGroup(
169 		  layout.createSequentialGroup()
170 		    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
171 		      .addGroup(layout.createSequentialGroup()
172 		        .addGap(10)
173 		        .addComponent(optionsButton))
174 		      .addComponent(separator1)
175 		      .addGroup(layout.createSequentialGroup()
176 		        .addGap(10)
177 		        .addComponent(aboutButton)))
178 		    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.TRAILING)
179 		      .addGroup(layout.createSequentialGroup()
180 		        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
181 		        .addComponent(loadButton)
182 		        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
183 		        .addComponent(saveAsButton)
184 		        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
185 		        .addComponent(box)
186 		        .addGap(10))
187 		      .addComponent(separator2)
188 		      .addGroup(layout.createSequentialGroup()
189 		        .addComponent(cancelButton)
190 		        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
191 		        .addComponent(connectButton)
192 		        .addGap(10)))
193 		);
194 		layout.setVerticalGroup(
195 		  layout.createSequentialGroup()
196 		    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
197 		      .addComponent(optionsButton)
198 		      .addComponent(loadButton)
199 		      .addComponent(saveAsButton)
200 		      .addComponent(box))
201 		    .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
202 		    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
203 		      .addComponent(separator1)
204 		      .addComponent(separator2))
205 		    .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
206 		    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
207 		      .addComponent(aboutButton)
208 		      .addComponent(cancelButton)
209 		      .addComponent(connectButton))
210 		    .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
211 		);
212 		layout.linkSize(SwingConstants.HORIZONTAL,
213                     optionsButton, loadButton, saveAsButton,
214                     aboutButton, cancelButton, box);
215     contentPane.add(buttonPane1,
216                     new GridBagConstraints(0, 1,
217                                            REMAINDER, 1,
218                                            LIGHT, LIGHT,
219                                            LINE_START, HORIZONTAL,
220                                            new Insets(5, 0, 10, 0),
221                                            NONE, NONE));
222     pack();
223   }
224 
run()225   public void run() {
226     this.showDialog();
227   }
228 
handleOptions()229   private void handleOptions() {
230     // quirk for mac os x
231     if (VncViewer.os.startsWith("mac os x"))
232       this.setAlwaysOnTop(false);
233     OptionsDialog.showDialog(this);
234   }
235 
handleLoad()236   private void handleLoad() {
237     String title = "Select a TigerVNC configuration file";
238     File dflt = new File(FileUtils.getVncHomeDir().concat("default.tigervnc"));
239     FileNameExtensionFilter filter =
240       new FileNameExtensionFilter("TigerVNC configuration (*.tigervnc)", "tigervnc");
241     File f = showChooser(title, dflt, filter);
242     if (f != null && f.exists() && f.canRead())
243       loadViewerParameters(f.getAbsolutePath());
244   }
245 
handleSaveAs()246   private void handleSaveAs() {
247     String title = "Save the TigerVNC configuration to file";
248     File dflt = new File(FileUtils.getVncHomeDir().concat("default.tigervnc"));
249     if (!dflt.exists() || !dflt.isFile())
250       dflt = new File(FileUtils.getVncHomeDir());
251     FileNameExtensionFilter filter =
252       new FileNameExtensionFilter("TigerVNC configuration (*.tigervnc)", "tigervnc");
253     File f = showChooser(title, dflt, filter);
254     while (f != null && f.exists() && f.isFile()) {
255       String msg = f.getAbsolutePath();
256       msg = msg.concat(" already exists. Do you want to overwrite?");
257       Object[] options = {"Overwrite", "No  \u21B5"};
258       JOptionPane op =
259         new JOptionPane(msg, JOptionPane.QUESTION_MESSAGE,
260                         JOptionPane.OK_CANCEL_OPTION, null, options, options[1]);
261       JDialog dlg = op.createDialog(this, "TigerVNC Viewer");
262       dlg.setIconImage(VncViewer.frameIcon);
263       dlg.setAlwaysOnTop(true);
264       dlg.setVisible(true);
265       if (op.getValue() == options[0])
266         break;
267       else
268         f = showChooser(title, f, filter);
269     }
270     if (f != null && (!f.exists() || f.canWrite()))
271       saveViewerParameters(f.getAbsolutePath(), (String)serverName.getSelectedItem());
272   }
273 
handleAbout()274   private void handleAbout() {
275     VncViewer.about_vncviewer(this);
276   }
277 
handleCancel()278   private void handleCancel() {
279     endDialog();
280   }
281 
handleConnect()282   private void handleConnect() {
283     String servername = (String)serverName.getSelectedItem();
284     servername.trim();
285     vncServerName.put(servername).flip();
286     saveViewerParameters(null, servername);
287     endDialog();
288   }
289 
290   @SuppressWarnings("rawtypes")
291   MyJComboBox serverName;
292   ComboBoxEditor editor;
293   JButton aboutButton, optionsButton, connectButton, cancelButton;
294   OptionsDialog options;
295   CharBuffer vncServerName;
296   static LogWriter vlog = new LogWriter("ServerDialog");
297 
298 }
299