• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  * Copyright 2014 See AUTHORS file.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  ******************************************************************************/
16 
17 package com.badlogic.gdx.setup;
18 
19 import static java.awt.GridBagConstraints.*;
20 
21 import com.badlogic.gdx.setup.DependencyBank.ProjectDependency;
22 import com.badlogic.gdx.setup.DependencyBank.ProjectType;
23 import com.badlogic.gdx.setup.Executor.CharCallback;
24 
25 import java.awt.BorderLayout;
26 import java.awt.Color;
27 import java.awt.Component;
28 import java.awt.Desktop;
29 import java.awt.Dimension;
30 import java.awt.EventQueue;
31 import java.awt.FileDialog;
32 import java.awt.Graphics;
33 import java.awt.GridBagConstraints;
34 import java.awt.GridBagLayout;
35 import java.awt.GridLayout;
36 import java.awt.Insets;
37 import java.awt.Point;
38 import java.awt.event.ActionEvent;
39 import java.awt.event.ActionListener;
40 import java.awt.event.ItemEvent;
41 import java.awt.event.ItemListener;
42 import java.awt.event.MouseAdapter;
43 import java.awt.event.MouseEvent;
44 import java.awt.event.MouseMotionAdapter;
45 import java.awt.image.BufferedImage;
46 import java.io.File;
47 import java.io.IOException;
48 import java.net.URI;
49 import java.net.URISyntaxException;
50 import java.util.ArrayList;
51 import java.util.List;
52 import java.util.regex.Matcher;
53 import java.util.regex.Pattern;
54 
55 import javax.imageio.ImageIO;
56 import javax.swing.BorderFactory;
57 import javax.swing.Box;
58 import javax.swing.BoxLayout;
59 import javax.swing.Icon;
60 import javax.swing.ImageIcon;
61 import javax.swing.JButton;
62 import javax.swing.JCheckBox;
63 import javax.swing.JComboBox;
64 import javax.swing.JComponent;
65 import javax.swing.JEditorPane;
66 import javax.swing.JFileChooser;
67 import javax.swing.JFrame;
68 import javax.swing.JLabel;
69 import javax.swing.JOptionPane;
70 import javax.swing.JPanel;
71 import javax.swing.JScrollPane;
72 import javax.swing.JTextArea;
73 import javax.swing.JTextField;
74 import javax.swing.SwingUtilities;
75 import javax.swing.UIManager;
76 import javax.swing.border.Border;
77 import javax.swing.border.CompoundBorder;
78 import javax.swing.border.EmptyBorder;
79 import javax.swing.event.HyperlinkEvent;
80 import javax.swing.event.HyperlinkListener;
81 import javax.swing.plaf.ColorUIResource;
82 import javax.swing.plaf.basic.BasicArrowButton;
83 import javax.swing.plaf.basic.BasicComboBoxUI;
84 
85 @SuppressWarnings("serial")
86 public class GdxSetupUI extends JFrame {
87 
88 	//DependencyBank dependencyBank;
89 	ProjectBuilder builder;
90 	List<ProjectType> modules = new ArrayList<ProjectType>();
91 	List<Dependency> dependencies = new ArrayList<Dependency>();
92 
93 	UI ui = new UI();
94 	static Point point = new Point();
95 
GdxSetupUI()96 	public GdxSetupUI () {
97 		setTitle("LibGDX Project Generator");
98 		setLayout(new BorderLayout());
99 		add(ui, BorderLayout.CENTER);
100 		setSize(620, 720);
101 		setLocationRelativeTo(null);
102 		setUndecorated(true);
103 		pack();
104 		setDefaultCloseOperation(EXIT_ON_CLOSE);
105 
106 		addMouseListener(new MouseAdapter() {
107 			public void mousePressed(MouseEvent e) {
108 				point.x = e.getX();
109 				point.y = e.getY();
110 			}
111 		});
112 		addMouseMotionListener(new MouseMotionAdapter() {
113 			public void mouseDragged(MouseEvent e) {
114 				Point p = getLocation();
115 				setLocation(p.x + e.getX() - point.x, p.y + e.getY() - point.y);
116 			}
117 		});
118 		setVisible(true);
119 
120 		builder = new ProjectBuilder(new DependencyBank());
121 		modules.add(ProjectType.CORE);
122 		dependencies.add(builder.bank.getDependency(ProjectDependency.GDX));
123 		dependencies.add(builder.bank.getDependency(ProjectDependency.BOX2D));
124 	}
125 
generate()126 	void generate () {
127 		final String name = ui.form.nameText.getText().trim();
128 		if (name.length() == 0) {
129 			JOptionPane.showMessageDialog(this, "Please enter a project name.");
130 			return;
131 		}
132 
133 		final String pack = ui.form.packageText.getText().trim();
134 		if (pack.length() == 0) {
135 			JOptionPane.showMessageDialog(this, "Please enter a package name.");
136 			return;
137 		}
138 		Pattern pattern = Pattern.compile("[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+[0-9a-z_]");
139 		Matcher matcher = pattern.matcher(pack);
140 		boolean matches = matcher.matches();
141 
142 		if (!matches) {
143 			JOptionPane.showMessageDialog(this, "Invalid package name");
144 			return;
145 		}
146 
147 		final String clazz = ui.form.gameClassText.getText().trim();
148 		if (clazz.length() == 0) {
149 			JOptionPane.showMessageDialog(this, "Please enter a game class name.");
150 			return;
151 		}
152 
153 		final String destination = ui.form.destinationText.getText().trim();
154 		if (destination.length() == 0) {
155 			JOptionPane.showMessageDialog(this, "Please enter a destination directory.");
156 			return;
157 		}
158 
159 		final String sdkLocation = ui.form.sdkLocationText.getText().trim();
160 		if (sdkLocation.length() == 0 && modules.contains(ProjectType.ANDROID)) {
161 			JOptionPane.showMessageDialog(this, "Please enter your Android SDK's path");
162 			return;
163 		}
164 		if (!GdxSetup.isSdkLocationValid(sdkLocation) && modules.contains(ProjectType.ANDROID)) {
165 			JOptionPane
166 					.showMessageDialog(this,
167 							"Your Android SDK path doesn't contain an SDK! Please install the Android SDK, including all platforms and build tools!");
168 			return;
169 		}
170 
171 		if (modules.contains(ProjectType.ANDROID)) {
172 			if (!GdxSetup.isSdkUpToDate(sdkLocation)) {
173 				File sdkLocationFile = new File(sdkLocation);
174 				try {  //give them a poke in the right direction
175 					if (System.getProperty("os.name").contains("Windows")) {
176 						String replaced = sdkLocation.replace("\\", "\\\\");
177 						Runtime.getRuntime().exec("\"" + replaced + "\\SDK Manager.exe\"");
178 					} else {
179 						File sdkManager = new File(sdkLocation, "tools/android");
180 						Runtime.getRuntime().exec(new String[] {sdkManager.getAbsolutePath(), "sdk"});
181 					}
182 				} catch (IOException e) {
183 					e.printStackTrace();
184 				}
185 				return;
186 			}
187 		}
188 
189 		if (modules.contains(ProjectType.IOSMOE)) {
190 			if (System.getenv("INTEL_MULTI_OS_ENGINE_HOME") == null) {
191 				JOptionPane.showMessageDialog(this, "Please install Intel Multi OS engine to use the ios-moe backend.");
192 				return;
193 			}
194 		}
195 
196 		if (!GdxSetup.isEmptyDirectory(destination)) {
197 			int value = JOptionPane.showConfirmDialog(this, "The destination is not empty, do you want to overwrite?", "Warning!", JOptionPane.YES_NO_OPTION);
198 			if (value != 0) {
199 				return;
200 			}
201 		}
202 
203 		List<String> incompatList = builder.buildProject(modules, dependencies);
204 		if (incompatList.size() == 0) {
205 			try {
206 				builder.build();
207 			} catch (IOException e) {
208 				e.printStackTrace();
209 			}
210 		} else {
211 			JPanel panel = new JPanel();
212 			panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
213 			for (String subIncompat : incompatList) {
214 				JLabel label = new JLabel(subIncompat);
215 				label.setAlignmentX(Component.CENTER_ALIGNMENT);
216 				panel.add(label);
217 			}
218 
219 			JLabel infoLabel = new JLabel("<html><br><br>The project can be generated, but you wont be able to use these extensions in the respective sub modules<br>Please see the link to learn about extensions</html>");
220 			infoLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
221 			panel.add(infoLabel);
222 			JEditorPane pane = new JEditorPane("text/html", "<a href=\"https://github.com/libgdx/libgdx/wiki/Dependency-management-with-Gradle\">Dependency Management</a>");
223 			pane.addHyperlinkListener(new HyperlinkListener() {
224 				@Override
225 				public void hyperlinkUpdate(HyperlinkEvent e) {
226 					if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED))
227 						try {
228 							Desktop.getDesktop().browse(new URI(e.getURL().toString()));
229 						} catch (IOException e1) {
230 							e1.printStackTrace();
231 						} catch (URISyntaxException e1) {
232 							e1.printStackTrace();
233 						}
234 				}
235 			});
236 			pane.setEditable(false);
237 			pane.setOpaque(false);
238 			pane.setAlignmentX(Component.CENTER_ALIGNMENT);
239 			panel.add(pane);
240 
241 			Object[] options = {"Yes, build it!", "No, I'll change my extensions"};
242 			int value = JOptionPane.showOptionDialog(null, panel, "Extension Incompatibilities", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, null);
243 			if (value != 0) {
244 				return;
245 			} else {
246 				try {
247 					builder.build();
248 				} catch (IOException e) {
249 					e.printStackTrace();
250 				}
251 			}
252 		}
253 
254 		ui.generateButton.setEnabled(false);
255 		new Thread() {
256 			public void run () {
257 				log("Generating app in " + destination);
258 				new GdxSetup().build(builder, destination, name, pack, clazz, sdkLocation, new CharCallback() {
259 					@Override
260 					public void character (char c) {
261 						log(c);
262 					}
263 				}, ui.settings.getGradleArgs());
264 				log("Done!");
265 				if (ui.settings.getGradleArgs().contains("eclipse") || ui.settings.getGradleArgs().contains("idea")) {
266 					log("To import in Eclipse: File -> Import -> General -> Existing Projects into Workspace");
267 					log("To import to Intellij IDEA: File -> Open -> YourProject.ipr");
268 				} else {
269 					log("To import in Eclipse: File -> Import -> Gradle -> Gradle Project");
270 					log("To import to Intellij IDEA: File -> Open -> build.gradle");
271 					log("To import to NetBeans: File -> Open Project...");
272 				}
273 				SwingUtilities.invokeLater(new Runnable() {
274 					@Override
275 					public void run() {
276 						ui.generateButton.setEnabled(true);
277 					}
278 				});
279 			}
280 		}.start();
281 	}
282 
log(final char c)283 	void log (final char c) {
284 		EventQueue.invokeLater(new Runnable() {
285 			public void run () {
286 				ui.textArea.append("" + c);
287 				ui.textArea.setCaretPosition(ui.textArea.getDocument().getLength());
288 			}
289 		});
290 	}
291 
log(final String text)292 	void log (final String text) {
293 		EventQueue.invokeLater(new Runnable() {
294 			public void run () {
295 				ui.textArea.append(text + "\n");
296 				ui.textArea.setCaretPosition(ui.textArea.getDocument().getLength());
297 			}
298 		});
299 	}
300 
301 	class UI extends JPanel {
302 		Form form = new Form();
303 		SettingsDialog settings = new SettingsDialog();
304 		SetupButton generateButton = new SetupButton("Generate");
305 		SetupButton advancedButton = new SetupButton("Advanced");
306 		JPanel buttonPanel = new JPanel();
307 		JTextArea textArea = new JTextArea(8, 40);
308 		JScrollPane scrollPane = new JScrollPane(textArea);
309 		JPanel title = new JPanel();
310 		JPanel topBar = new JPanel();
311 		JLabel windowLabel = new JLabel("    Libgdx Project Generator");
312 		JButton exit;
313 		JButton minimize;
314 		JLabel logo;
315 
316 		{
setBackground(new Color(36, 36, 36))317 			setBackground(new Color(36, 36, 36));
topBar.setBackground(new Color(64, 67, 69))318 			topBar.setBackground(new Color(64, 67, 69));
title.setBackground(new Color(94, 97, 99))319 			title.setBackground(new Color(94, 97, 99));
windowLabel.setForeground(new Color(255, 255, 255))320 			windowLabel.setForeground(new Color(255, 255, 255));
form.setBackground(new Color(36, 36, 36))321 			form.setBackground(new Color(36, 36, 36));
322 			for (int i = 0; i < form.getComponents().length; i++) {
323 				Component component = form.getComponents()[i];
324 				if (component instanceof JTextField) {
component.setBackground(new Color(46, 46, 46))325 					component.setBackground(new Color(46, 46, 46));
component.setForeground(new Color(255, 255, 255))326 					component.setForeground(new Color(255, 255, 255));
327 					Border line = BorderFactory.createEtchedBorder();
328 					Border pad = new EmptyBorder(0, 5, 0, 0);
329 					CompoundBorder compoundBorder = new CompoundBorder(line, pad);
setBorder(compoundBorder)330 					((JComponent) component).setBorder(compoundBorder);
331 					continue;
332 				}
333 			}
buttonPanel.setBackground(new Color(46, 46, 46))334 			buttonPanel.setBackground(new Color(46, 46, 46));
textArea.setBackground(new Color(46, 46, 46))335 			textArea.setBackground(new Color(46, 46, 46));
textArea.setForeground(new Color(255, 255, 255))336 			textArea.setForeground(new Color(255, 255, 255));
337 
338 			Border line = BorderFactory.createLineBorder(Color.DARK_GRAY);
339 			scrollPane.setBorder(line);
340 
341 			try {
342 				BufferedImage exitimg = ImageIO.read(GdxSetupUI.class.getResourceAsStream("/com/badlogic/gdx/setup/data/exitup.png"));
343 				BufferedImage minimg = ImageIO.read(GdxSetupUI.class.getResourceAsStream("/com/badlogic/gdx/setup/data/minimizeup.png"));
344 				BufferedImage exitimgdown = ImageIO.read(GdxSetupUI.class.getResourceAsStream("/com/badlogic/gdx/setup/data/exitdown.png"));
345 				BufferedImage minimgdown = ImageIO.read(GdxSetupUI.class.getResourceAsStream("/com/badlogic/gdx/setup/data/minimizedown.png"));
346 				BufferedImage exithover = ImageIO.read(GdxSetupUI.class.getResourceAsStream("/com/badlogic/gdx/setup/data/exithover.png"));
347 				BufferedImage minimghover = ImageIO.read(GdxSetupUI.class.getResourceAsStream("/com/badlogic/gdx/setup/data/minimizehover.png"));
348 
349 				BufferedImage img = ImageIO.read(GdxSetupUI.class.getResourceAsStream("/com/badlogic/gdx/setup/data/logo.png"));
350 				ImageIcon icon = new ImageIcon(img);
351 				ImageIcon exitIcon = new ImageIcon(exitimg);
352 				ImageIcon minIcon = new ImageIcon(minimg);
353 				ImageIcon exitIconDown = new ImageIcon(exitimgdown);
354 				ImageIcon minIconDown = new ImageIcon(minimgdown);
355 				ImageIcon exitIconHover = new ImageIcon(exithover);
356 				ImageIcon minIconHover = new ImageIcon(minimghover);
357 				logo = new JLabel(icon);
358 				exit = new JButton(exitIcon);
359 				minimize = new JButton(minIcon);
360 
361 				exit.setOpaque(false);
362 				exit.setContentAreaFilled(false);
363 				exit.setFocusPainted(false);
364 				exit.setBorderPainted(false);
365 				exit.setPressedIcon(exitIconDown);
366 				exit.setRolloverIcon(exitIconHover);
367 
368 				minimize.setOpaque(false);
369 				minimize.setContentAreaFilled(false);
370 				minimize.setFocusPainted(false);
371 				minimize.setBorderPainted(false);
372 				minimize.setPressedIcon(minIconDown);
373 				minimize.setRolloverIcon(minIconHover);
374 			} catch (IOException e) {
375 				e.printStackTrace();
376 			}
377 
378 			buttonPanel.add(advancedButton);
379 			buttonPanel.add(generateButton);
380 			textArea.setEditable(false);
381 			textArea.setLineWrap(true);
uiLayout()382 			uiLayout();
uiEvents()383 			uiEvents();
titleEvents(minimize, exit)384 			titleEvents(minimize, exit);
385 		}
386 
titleEvents(JButton minimize, JButton exit)387 		private void titleEvents(JButton minimize, JButton exit) {
388 			minimize.addActionListener(new ActionListener() {
389 				@Override
390 				public void actionPerformed(ActionEvent e) {
391 					setState(ICONIFIED);
392 				}
393 			});
394 			exit.addActionListener(new ActionListener() {
395 				@Override
396 				public void actionPerformed(ActionEvent e) {
397 					dispose();
398 					System.exit(0);
399 				}
400 			});
401 		}
402 
uiLayout()403 		private void uiLayout () {
404 			title.setLayout(new GridLayout(1, 2));
405 
406 			minimize.setPreferredSize(new Dimension(50, 26));
407 			exit.setPreferredSize(new Dimension(50, 26));
408 
409 			title.add(minimize);
410 			title.add(exit);
411 
412 			topBar.setLayout(new GridLayout(1, 1));
413 			topBar.add(windowLabel, new GridBagConstraints(0, 0, 0, 0, 0, 0, NORTHWEST, VERTICAL, new Insets(0, 0, 0, 0), 0, 0));
414 
415 			setLayout(new GridBagLayout());
416 			add(topBar, new GridBagConstraints(0, 0, 0, 0, 0, 0, NORTH, HORIZONTAL, new Insets(0, 0, 0, 100), 0, 10));
417 			add(title, new GridBagConstraints(0, 0, 0, 0, 0, 0, NORTHEAST, NONE, new Insets(0, 0, 0, 0), 0, 0));
418 			add(logo, new GridBagConstraints(0, 0, 1, 1, 1, 0, CENTER, HORIZONTAL, new Insets(40, 6, 6, 6), 0, 0));
419 			add(form, new GridBagConstraints(0, 1, 1, 1, 1, 0, CENTER, HORIZONTAL, new Insets(6, 6, 0, 6), 0, 0));
420 			add(buttonPanel, new GridBagConstraints(0, 2, 1, 1, 0, 0, CENTER, NONE, new Insets(0, 0, 0, 0), 0, 0));
421 			add(scrollPane, new GridBagConstraints(0, 3, 1, 1, 1, 1, CENTER, BOTH, new Insets(6, 6, 6, 6), 0, 0));
422 		}
423 
uiEvents()424 		private void uiEvents () {
425 			advancedButton.addActionListener(new ActionListener() {
426 				public void actionPerformed (ActionEvent e) {
427 					settings.showDialog();
428 				}
429 			});
430 			generateButton.addActionListener(new ActionListener() {
431 				public void actionPerformed (ActionEvent e) {
432 					generate();
433 				}
434 			});
435 		}
436 	}
437 
438 	class Form extends JPanel {
439 		ExternalExtensionsDialog externalExtensionsDialog = new ExternalExtensionsDialog(dependencies);
440 		JLabel nameLabel = new JLabel("Name:");
441 		JTextField nameText = new JTextField("my-gdx-game");
442 		JLabel packageLabel = new JLabel("Package:");
443 		JTextField packageText = new JTextField("com.mygdx.game");
444 		JLabel gameClassLabel = new JLabel("Game class:");
445 		JTextField gameClassText = new JTextField("MyGdxGame");
446 		JLabel destinationLabel = new JLabel("Destination:");
447 		JTextField destinationText = new JTextField(new File("test").getAbsolutePath());
448 		SetupButton destinationButton = new SetupButton("Browse");
449 		JLabel sdkLocationLabel = new JLabel("Android SDK");
450 		JTextField sdkLocationText = new JTextField(
451 				System.getProperty("os.name").contains("Windows")
452 				? "C:\\Path\\To\\Your\\Sdk"
453 				: "/path/to/your/sdk"
454 		);
455 		SetupButton sdkLocationButton = new SetupButton("Browse");
456 
457 		JPanel subProjectsPanel = new JPanel(new GridLayout());
458 		JLabel projectsLabel = new JLabel("Sub Projects");
459 		JLabel extensionsLabel = new JLabel("Extensions");
460 		List<JPanel> extensionsPanels = new ArrayList<JPanel>();
461 		SetupButton showMoreExtensionsButton = new SetupButton("Show Third Party Extensions");
462 
463 		{
uiLayout()464 			uiLayout();
uiEvents()465 			uiEvents();
uiStyle()466 			uiStyle();
467 		}
468 
uiStyle()469 		private void uiStyle() {
470 			nameText.setCaretColor(Color.WHITE);
471 			packageText.setCaretColor(Color.WHITE);
472 			gameClassText.setCaretColor(Color.WHITE);
473 			destinationText.setCaretColor(Color.WHITE);
474 			sdkLocationText.setCaretColor(Color.WHITE);
475 
476 			nameLabel.setForeground(Color.WHITE);
477 			packageLabel.setForeground(Color.WHITE);
478 			gameClassLabel.setForeground(Color.WHITE);
479 			destinationLabel.setForeground(Color.WHITE);
480 			sdkLocationLabel.setForeground(Color.WHITE);
481 			sdkLocationText.setDisabledTextColor(Color.GRAY);
482 
483 			projectsLabel.setForeground(new Color(255, 20, 20));
484 			extensionsLabel.setForeground(new Color(255, 20, 20));
485 
486 			subProjectsPanel.setOpaque(true);
487 			subProjectsPanel.setBackground(new Color(46, 46, 46));
488 
489 			for (JPanel extensionPanel : extensionsPanels) {
490 				extensionPanel.setOpaque(true);
491 				extensionPanel.setBackground(new Color(46, 46, 46));
492 			}
493 		}
494 
uiLayout()495 		private void uiLayout () {
496 			setLayout(new GridBagLayout());
497 
498 			add(nameLabel, new GridBagConstraints(0, 0, 1, 1, 0, 0, EAST, NONE, new Insets(0, 0, 6, 6), 0, 0));
499 			add(nameText, new GridBagConstraints(1, 0, 2, 1, 1, 0, CENTER, HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));
500 
501 			add(packageLabel, new GridBagConstraints(0, 1, 1, 1, 0, 0, EAST, NONE, new Insets(0, 0, 6, 6), 0, 0));
502 			add(packageText, new GridBagConstraints(1, 1, 2, 1, 1, 0, CENTER, HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));
503 
504 			add(gameClassLabel, new GridBagConstraints(0, 2, 1, 1, 0, 0, EAST, NONE, new Insets(0, 0, 6, 6), 0, 0));
505 			add(gameClassText, new GridBagConstraints(1, 2, 2, 1, 1, 0, CENTER, HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));
506 
507 			add(destinationLabel, new GridBagConstraints(0, 3, 1, 1, 0, 0, EAST, NONE, new Insets(0, 0, 0, 6), 0, 0));
508 			add(destinationText, new GridBagConstraints(1, 3, 1, 1, 1, 0, CENTER, HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
509 			add(destinationButton, new GridBagConstraints(2, 3, 1, 1, 0, 0, CENTER, NONE, new Insets(0, 6, 0, 0), 0, 0));
510 
511 			if (System.getenv("ANDROID_HOME") != null) {
512 				sdkLocationText.setText(System.getenv("ANDROID_HOME"));
513 			}
514 			add(sdkLocationLabel, new GridBagConstraints(0, 4, 1, 1, 0, 0, EAST, NONE, new Insets(0, 0, 0, 6), 0, 0));
515 			add(sdkLocationText, new GridBagConstraints(1, 4, 1, 1, 1, 0, CENTER, HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
516 			add(sdkLocationButton, new GridBagConstraints(2, 4, 1, 1, 0, 0, CENTER, NONE, new Insets(0, 6, 0, 0), 0, 0));
517 
518 
519 			for (final ProjectType projectType : ProjectType.values()) {
520 				if (projectType.equals(ProjectType.CORE)) {
521 					continue;
522 				}
523 				SetupCheckBox checkBox = new SetupCheckBox(projectType.getName().substring(0, 1).toUpperCase() + projectType.getName().substring(1, projectType.getName().length()));
524 				if (projectType != ProjectType.IOSMOE) {
525 					modules.add(projectType);
526 					checkBox.setSelected(true);
527 				}
528 				subProjectsPanel.add(checkBox);
529 				checkBox.addItemListener(new ItemListener() {
530 					@Override
531 					public void itemStateChanged(ItemEvent e) {
532 						SetupCheckBox box = (SetupCheckBox) e.getSource();
533 						if (projectType.equals(ProjectType.ANDROID)) {
534 							sdkLocationText.setEnabled(box.isSelected());
535 						}
536 						if (box.isSelected()) {
537 							modules.add(projectType);
538 						} else {
539 							if (modules.contains(projectType)) {
540 								modules.remove(projectType);
541 							}
542 						}
543 					}
544 				});
545 			}
546 
547 			add(projectsLabel, new GridBagConstraints(0, 6, 1, 1, 0, 0, WEST, WEST, new Insets(20, 0, 0, 0), 0, 0));
548 			add(subProjectsPanel, new GridBagConstraints(0, 7, 3, 1, 0, 0, CENTER, HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
549 
550 			int depCounter = 0;
551 
552 			for (int row = 0; row <= (ProjectDependency.values().length / 5); row++) {
553 				JPanel extensionPanel = new JPanel(new GridLayout(1, 5));
554 				while (depCounter < ProjectDependency.values().length) {
555 					if (ProjectDependency.values()[depCounter] != null) {
556 						final ProjectDependency projDep = ProjectDependency.values()[depCounter];
557 						if (projDep.equals(ProjectDependency.GDX)) {
558 							depCounter++;
559 							continue;
560 						}
561 						SetupCheckBox depCheckBox = new SetupCheckBox(projDep.name().substring(0, 1) + projDep.name().substring(1, projDep.name().length()).toLowerCase());
562 						depCheckBox.setToolTipText(projDep.getDescription());
563 						if (projDep.equals(ProjectDependency.BOX2D)) {
564 							depCheckBox.setSelected(true);
565 						}
566 						extensionPanel.add(depCheckBox);
567 						depCheckBox.addItemListener(new ItemListener() {
568 							@Override
569 							public void itemStateChanged(ItemEvent e) {
570 								SetupCheckBox box = (SetupCheckBox) e.getSource();
571 								if (box.isSelected()) {
572 									dependencies.add(builder.bank.getDependency(projDep));
573 								} else {
574 									if (dependencies.contains(builder.bank.getDependency(projDep))) {
575 										dependencies.remove(builder.bank.getDependency(projDep));
576 									}
577 								}
578 							}
579 						});
580 						if (depCounter % 5 == 0) {
581 							depCounter++;
582 							break;
583 						}
584 						depCounter++;
585 					}
586 				}
587 
588 				for (int left = ((depCounter - 1) % 5); left > 1; left--) {
589 					extensionPanel.add(Box.createHorizontalBox());
590 				}
591 
592 				extensionsPanels.add(extensionPanel);
593 			}
594 
595 			add(extensionsLabel, new GridBagConstraints(0, 8, 1, 1, 0, 0, WEST, WEST, new Insets(10, 0, 0, 0), 0, 0));
596 			int rowCounter = 9;
597 			for (JPanel extensionsPanel : extensionsPanels) {
598 				add(extensionsPanel, new GridBagConstraints(0, rowCounter, 3, 1, 0, 0, CENTER, HORIZONTAL, new Insets(5, 0, 0, 0), 0, 0));
599 				rowCounter++;
600 			}
601 			add(showMoreExtensionsButton, new GridBagConstraints(0, 12, 0, 1, 0, 0, CENTER, WEST, new Insets(10, 0, 10, 0), 0, 0));
602 		}
603 
getDirectory()604 		File getDirectory () {
605 			if (System.getProperty("os.name").contains("Mac")) {
606 				System.setProperty("apple.awt.fileDialogForDirectories", "true");
607 				FileDialog dialog = new FileDialog(GdxSetupUI.this, "Choose destination", FileDialog.LOAD);
608 				dialog.setVisible(true);
609 				String name = dialog.getFile();
610 				String dir = dialog.getDirectory();
611 				if (name == null || dir == null) return null;
612 				return new File(dialog.getDirectory(), dialog.getFile());
613 			} else {
614 				JFileChooser chooser = new JFileChooser();
615 				chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
616 				chooser.setDialogTitle("Choose destination");
617 				int result = chooser.showOpenDialog(null);
618 				if (result == JFileChooser.APPROVE_OPTION) {
619 					File dir = chooser.getSelectedFile();
620 					if (dir == null) return null;
621 					if (dir.getAbsolutePath().trim().length() == 0) return null;
622 					return dir;
623 				} else {
624 					return null;
625 				}
626 			}
627 		}
628 
uiEvents()629 		private void uiEvents () {
630 			destinationButton.addActionListener(new ActionListener() {
631 				public void actionPerformed (ActionEvent e) {
632 					File path = getDirectory();
633 					if (path != null) {
634 						destinationText.setText(path.getAbsolutePath());
635 					}
636 				}
637 			});
638 			sdkLocationButton.addActionListener(new ActionListener() {
639 				@Override
640 				public void actionPerformed (ActionEvent e) {
641 					File path = getDirectory();
642 					if (path != null) {
643 						sdkLocationText.setText(path.getAbsolutePath());
644 					}
645 				}
646 			});
647 			showMoreExtensionsButton.addActionListener(new ActionListener() {
648 				 public void actionPerformed (ActionEvent e) {
649 					  externalExtensionsDialog.showDialog();
650 				 }
651 			});
652 		}
653 	}
654 
655 	public static class SetupCheckBox extends JCheckBox {
656 
657 		static Icon icon;
658 		static Icon iconOver;
659 		static Icon iconPressed;
660 		static Icon iconPressedSelected;
661 		static Icon iconSelected;
662 		static Icon iconOverSelected;
663 
664 		static {
665 			try {
666 				BufferedImage iconImg = getCheckboxImage("checkbox");
667 				BufferedImage iconOverImg = getCheckboxImage("checkboxover");
668 				BufferedImage iconPressedImg = getCheckboxImage("checkboxpressed");
669 				BufferedImage iconPressedSelectedImg = getCheckboxImage("checkboxpressedselected");
670 				BufferedImage iconSelectedImg = getCheckboxImage("checkboxselected");
671 				BufferedImage iconOverSelectedImg = getCheckboxImage("checkboxoverselected");
672 
673 				icon = new ImageIcon(iconImg);
674 				iconOver = new ImageIcon(iconOverImg);
675 				iconPressed = new ImageIcon(iconPressedImg);
676 				iconPressedSelected = new ImageIcon(iconPressedSelectedImg);
677 				iconSelected = new ImageIcon(iconSelectedImg);
678 				iconOverSelected = new ImageIcon(iconOverSelectedImg);
679 			} catch (IOException e) {
680 				e.printStackTrace();
681 			}
682 		}
683 
getCheckboxImage(String imageName)684 		private static BufferedImage getCheckboxImage (String imageName) throws IOException {
685 			return ImageIO.read(GdxSetupUI.class.getResourceAsStream("/com/badlogic/gdx/setup/data/" + imageName + ".png"));
686 		}
687 
SetupCheckBox()688 		SetupCheckBox () {
689 			super();
690 			initUI();
691 		}
692 
SetupCheckBox(String selectName)693 		SetupCheckBox (String selectName) {
694 			super(selectName);
695 			initUI();
696 		}
697 
initUI()698 		private void initUI() {
699 			setOpaque(false);
700 			setBackground(new Color(0, 0, 0));
701 			setForeground(new Color(255, 255, 255));
702 			setFocusPainted(false);
703 
704 			setIcon(icon);
705 			setRolloverIcon(iconOver);
706 			setPressedIcon(iconPressed);
707 			setSelectedIcon(iconSelected);
708 			setRolloverSelectedIcon(iconOverSelected);
709 		}
710 
getPressedIcon()711 		public Icon getPressedIcon () {
712 			//checkbox is missing 'pressed selected' icon, this allows us to add it
713 			if (isSelected())
714 				return iconPressedSelected;
715 			else
716 				return super.getPressedIcon();
717 		}
718 
719 	}
720 
721 	public static class SetupButton extends JButton {
722 		private Color textColor = Color.WHITE;
723 		private Color backgroundColor = new Color(18, 18, 18);
724 		private Color overColor = new Color(120, 20, 20);
725 		private Color pressedColor = new Color(240, 40, 40);
726 
SetupButton(String buttonTag)727 		SetupButton (String buttonTag) {
728 			super(buttonTag);
729 			setBackground(backgroundColor);
730 			setForeground(textColor);
731 			setContentAreaFilled(false);
732 			setFocusPainted(false);
733 
734 			Border line = BorderFactory.createLineBorder(new Color(80, 80, 80));
735 			Border empty = new EmptyBorder(4, 4, 4, 4);
736 			CompoundBorder border = new CompoundBorder(line, empty);
737 			setBorder(border);
738 		}
739 
740 		@Override
paintComponent(Graphics g)741 		protected void paintComponent (Graphics g) {
742 			if (getModel().isPressed()) {
743 				g.setColor(pressedColor);
744 			} else if (getModel().isRollover()) {
745 				g.setColor(overColor);
746 			} else {
747 				g.setColor(getBackground());
748 			}
749 			g.fillRect(0, 0, getWidth(), getHeight());
750 			super.paintComponent(g);
751 		}
752 	}
753 
main(String[] args)754 	public static void main (String[] args) throws Exception {
755 		SwingUtilities.invokeLater(new Runnable() {
756 			@Override
757 			public void run() {
758 				new GdxSetupUI();
759 			}
760 		});
761 	}
762 }
763