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