1 /******************************************************************************* 2 * Copyright 2011 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.BOTH; 20 import static java.awt.GridBagConstraints.CENTER; 21 import static java.awt.GridBagConstraints.HORIZONTAL; 22 import static java.awt.GridBagConstraints.NONE; 23 import static java.awt.GridBagConstraints.NORTH; 24 import static java.awt.GridBagConstraints.SOUTH; 25 import static java.awt.GridBagConstraints.SOUTHEAST; 26 27 import java.awt.Color; 28 import java.awt.Desktop; 29 import java.awt.GridBagConstraints; 30 import java.awt.GridBagLayout; 31 import java.awt.Insets; 32 import java.awt.event.ActionEvent; 33 import java.awt.event.ActionListener; 34 import java.awt.event.MouseAdapter; 35 import java.awt.event.MouseEvent; 36 import java.io.IOException; 37 import java.net.URI; 38 import java.net.URISyntaxException; 39 import java.util.ArrayList; 40 import java.util.HashMap; 41 import java.util.List; 42 import java.util.Map; 43 44 import javax.swing.BorderFactory; 45 import javax.swing.JDialog; 46 import javax.swing.JLabel; 47 import javax.swing.JPanel; 48 import javax.swing.JScrollPane; 49 import javax.swing.JSeparator; 50 import javax.swing.JTable; 51 import javax.swing.event.TableModelEvent; 52 import javax.swing.event.TableModelListener; 53 import javax.swing.table.DefaultTableModel; 54 import javax.xml.parsers.DocumentBuilder; 55 import javax.xml.parsers.DocumentBuilderFactory; 56 import javax.xml.parsers.ParserConfigurationException; 57 58 import org.w3c.dom.Document; 59 import org.w3c.dom.Element; 60 import org.w3c.dom.Node; 61 import org.w3c.dom.NodeList; 62 import org.xml.sax.SAXException; 63 64 import com.badlogic.gdx.setup.GdxSetupUI.SetupButton; 65 66 public class ExternalExtensionsDialog extends JDialog implements TableModelListener { 67 68 private JPanel contentPane; 69 private SetupButton buttonOK; 70 private SetupButton buttonCancel; 71 private JPanel topPanel; 72 private ExtensionTableModel tableModel; 73 JTable table; 74 private JPanel bottomPanel; 75 private JPanel buttonPanel; 76 private JScrollPane scrollPane; 77 78 private JLabel warningNotice; 79 private JLabel warningNotice2; 80 81 private List<Dependency> mainDependenciesSnapshot = new ArrayList<Dependency>(); 82 List<Dependency> mainDependencies; 83 84 public ExternalExtensionsDialog (List<Dependency> mainDependencies) { 85 this.mainDependencies = mainDependencies; 86 87 contentPane = new JPanel(new GridBagLayout()); 88 setContentPane(contentPane); 89 setModal(true); 90 getRootPane().setDefaultButton(buttonOK); 91 92 uiLayout(); 93 uiStyle(); 94 95 buttonOK.addActionListener(new ActionListener() { 96 public void actionPerformed (ActionEvent e) { 97 onOK(); 98 } 99 }); 100 buttonCancel.addActionListener(new ActionListener() { 101 @Override 102 public void actionPerformed (ActionEvent e) { 103 onCancel(); 104 } 105 }); 106 107 setTitle("Third party external extensions"); 108 setSize(600, 300); 109 setLocationRelativeTo(null); 110 } 111 112 public void showDialog () { 113 takeSnapshot(); 114 setVisible(true); 115 } 116 117 private void uiLayout () { 118 119 topPanel = new JPanel(new GridBagLayout()); 120 topPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 121 warningNotice = new JLabel("List of third party extensions for LibGDX"); 122 warningNotice2 = new JLabel("These are not maintained by the LibGDX team, please see the support links for info and help"); 123 warningNotice.setHorizontalAlignment(JLabel.CENTER); 124 warningNotice2.setHorizontalAlignment(JLabel.CENTER); 125 126 topPanel.add(warningNotice, new GridBagConstraints(0, 0, 1, 1, 1, 0, NORTH, HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); 127 topPanel.add(warningNotice2, new GridBagConstraints(0, 1, 1, 1, 1, 0, NORTH, HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); 128 129 JSeparator separator = new JSeparator(); 130 separator.setForeground(new Color(85, 85, 85)); 131 separator.setBackground(new Color(85, 85, 85)); 132 133 topPanel.add(separator, new GridBagConstraints(0, 2, 1, 1, 1, 1, NORTH, HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); 134 135 tableModel = new ExtensionTableModel(); 136 table = new JTable(tableModel) { 137 @Override 138 public String getToolTipText (MouseEvent e) { 139 return ((ExtensionTableModel)getModel()).getToolTip(e); 140 } 141 }; 142 table.getColumnModel().getColumn(0).setPreferredWidth(10); 143 table.getColumnModel().getColumn(1).setPreferredWidth(50); 144 table.getColumnModel().getColumn(2).setPreferredWidth(100); 145 table.getColumnModel().getColumn(3).setPreferredWidth(20); 146 table.getColumnModel().getColumn(4).setPreferredWidth(30); 147 148 table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); 149 150 table.getTableHeader().setReorderingAllowed(false); 151 table.getModel().addTableModelListener(this); 152 table.addMouseListener(new MouseAdapter() { 153 public void mouseClicked (MouseEvent e) { 154 int row = table.getSelectedRow(); 155 int column = table.getSelectedColumn(); 156 if (column == 5) { 157 URI uri = ((ExtensionTableModel)table.getModel()).getURI(row, column); 158 if (uri != null) { 159 try { 160 Desktop.getDesktop().browse(uri); 161 } catch (IOException e1) { 162 e1.printStackTrace(); 163 } 164 } 165 } 166 } 167 }); 168 169 scrollPane = new JScrollPane(table); 170 171 bottomPanel = new JPanel(new GridBagLayout()); 172 173 buttonPanel = new JPanel(new GridBagLayout()); 174 buttonPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 175 buttonOK = new SetupButton("Save"); 176 buttonCancel = new SetupButton("Cancel"); 177 buttonPanel.add(buttonOK, new GridBagConstraints(0, 0, 1, 1, 0, 0, CENTER, HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); 178 buttonPanel.add(buttonCancel, new GridBagConstraints(1, 0, 1, 1, 0, 0, CENTER, HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); 179 bottomPanel.add(buttonPanel, new GridBagConstraints(3, 0, 1, 1, 1, 1, SOUTHEAST, NONE, new Insets(0, 0, 0, 0), 0, 0)); 180 181 contentPane.add(topPanel, new GridBagConstraints(0, 0, 1, 1, 1, 0.1, NORTH, BOTH, new Insets(0, 0, 0, 0), 0, 0)); 182 contentPane.add(scrollPane, new GridBagConstraints(0, 1, 1, 1, 1, 1, NORTH, BOTH, new Insets(0, 0, 0, 0), 0, 0)); 183 contentPane.add(bottomPanel, new GridBagConstraints(0, 2, 1, 1, 1, 0, SOUTH, HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); 184 185 try { 186 initData(); 187 } catch (Exception e) { 188 e.printStackTrace(); 189 } 190 191 } 192 193 private void initData () throws ParserConfigurationException, IOException, SAXException { 194 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); 195 DocumentBuilder builder = dbFactory.newDocumentBuilder(); 196 Document doc = builder.parse(ExternalExtensionsDialog.class 197 .getResourceAsStream("/com/badlogic/gdx/setup/data/extensions.xml")); 198 199 doc.getDocumentElement().normalize(); 200 201 NodeList nList = doc.getElementsByTagName("extension"); 202 203 for (int i = 0; i < nList.getLength(); i++) { 204 Node nNode = nList.item(i); 205 if (nNode.getNodeType() == Node.ELEMENT_NODE) { 206 207 Element eElement = (Element)nNode; 208 String name = eElement.getElementsByTagName("name").item(0).getTextContent(); 209 String description = eElement.getElementsByTagName("description").item(0).getTextContent(); 210 String version = eElement.getElementsByTagName("version").item(0).getTextContent(); 211 String compatibility = eElement.getElementsByTagName("compatibility").item(0).getTextContent(); 212 String url = eElement.getElementsByTagName("website").item(0).getTextContent(); 213 214 String[] gwtInherits = null; 215 NodeList inheritsNode = eElement.getElementsByTagName("inherit"); 216 gwtInherits = new String[inheritsNode.getLength()]; 217 218 for (int j = 0; j < inheritsNode.getLength(); j++) 219 gwtInherits[j] = inheritsNode.item(j).getTextContent(); 220 221 final HashMap<String, List<ExternalExtensionDependency>> dependencies = new HashMap<String, List<ExternalExtensionDependency>>(); 222 223 addToDependencyMapFromXML(dependencies, eElement, "core"); 224 addToDependencyMapFromXML(dependencies, eElement, "desktop"); 225 addToDependencyMapFromXML(dependencies, eElement, "android"); 226 addToDependencyMapFromXML(dependencies, eElement, "ios"); 227 addToDependencyMapFromXML(dependencies, eElement, "html"); 228 229 URI uri = null; 230 try { 231 uri = new URI(url); 232 } catch (URISyntaxException e) { 233 e.printStackTrace(); 234 } 235 236 if (uri != null) { 237 final ExternalExtension extension = new ExternalExtension(name, gwtInherits, description, version); 238 extension.setDependencies(dependencies); 239 tableModel.addExtension(extension, false, name, description, version, compatibility, uri); 240 } 241 } 242 } 243 } 244 245 private void uiStyle () { 246 contentPane.setBackground(new Color(36, 36, 36)); 247 248 topPanel.setBackground(new Color(36, 36, 36)); 249 topPanel.setForeground(new Color(255, 255, 255)); 250 table.setBackground(new Color(46, 46, 46)); 251 table.setForeground(new Color(255, 255, 255)); 252 bottomPanel.setBackground(new Color(36, 36, 36)); 253 bottomPanel.setForeground(new Color(255, 255, 255)); 254 buttonPanel.setBackground(new Color(36, 36, 36)); 255 buttonPanel.setForeground(new Color(255, 255, 255)); 256 257 scrollPane.setBorder(BorderFactory.createEmptyBorder()); 258 scrollPane.setBackground(new Color(36, 36, 36)); 259 scrollPane.getViewport().setBackground(new Color(36, 36, 36)); 260 261 warningNotice.setForeground(new Color(255, 20, 20)); 262 warningNotice2.setForeground(new Color(255, 20, 20)); 263 } 264 265 void onOK () { 266 setVisible(false); 267 } 268 269 void onCancel () { 270 setVisible(false); 271 restore(); 272 } 273 274 private void takeSnapshot () { 275 mainDependenciesSnapshot.clear(); 276 for (int i = 0; i < mainDependencies.size(); i++) { 277 mainDependenciesSnapshot.add(mainDependencies.get(i)); 278 } 279 } 280 281 private void restore () { 282 mainDependencies.clear(); 283 ((ExtensionTableModel)table.getModel()).unselectAll(); 284 for (int i = 0; i < mainDependenciesSnapshot.size(); i++) { 285 mainDependencies.add(mainDependenciesSnapshot.get(i)); 286 String extensionName = mainDependenciesSnapshot.get(i).getName(); 287 if (((ExtensionTableModel)table.getModel()).hasExtension(extensionName)) { 288 ((ExtensionTableModel)table.getModel()).setSelected(extensionName, true); 289 } else { 290 } 291 } 292 } 293 294 private void addToDependencyMapFromXML (Map<String, List<ExternalExtensionDependency>> dependencies, Element eElement, String platform) { 295 if (eElement.getElementsByTagName(platform).item(0) != null) { 296 Element project = (Element)eElement.getElementsByTagName(platform).item(0); 297 298 ArrayList<ExternalExtensionDependency> deps = new ArrayList<ExternalExtensionDependency>(); 299 300 if (project.getTextContent().trim().equals("")) { 301 // No dependencies required 302 } else if (project.getTextContent().trim().equals("null")) { 303 // Not supported 304 deps = null; 305 } else { 306 NodeList nList = project.getElementsByTagName("dependency"); 307 308 for (int i = 0; i < nList.getLength(); i++) { 309 Node nNode = nList.item(i); 310 if (nNode.getNodeType() == Node.ELEMENT_NODE) { 311 Element dependencyNode = (Element)nNode; 312 boolean external = Boolean.parseBoolean(dependencyNode.getAttribute("external")); 313 deps.add(new ExternalExtensionDependency(dependencyNode.getTextContent(), external)); 314 } 315 316 } 317 } 318 319 dependencies.put(platform, deps); 320 } 321 } 322 323 class ExtensionTableModel extends DefaultTableModel { 324 325 private HashMap<Integer, ExternalExtension> extensions = new HashMap<Integer, ExternalExtension>(); 326 private int rowCount = 0; 327 328 public ExtensionTableModel () { 329 addColumn("Use"); 330 addColumn("Extension"); 331 addColumn("Description"); 332 addColumn("Version"); 333 addColumn("Compatibility"); 334 addColumn("Support"); 335 } 336 337 public ExternalExtension getExtension (int row) { 338 return extensions.get(row); 339 } 340 341 public URI getURI (int row, int column) { 342 if (column != 5) return null; 343 return (URI)getValueAt(row, column); 344 } 345 346 @Override 347 public Class getColumnClass (int column) { 348 if (column == 0) return Boolean.class; 349 if (column == 5) return URI.class; 350 return super.getColumnClass(column); 351 } 352 353 @Override 354 public boolean isCellEditable (int x, int y) { 355 return y == 0; 356 } 357 358 public String getToolTip (MouseEvent e) { 359 int row = table.rowAtPoint(e.getPoint()); 360 int column = table.columnAtPoint(e.getPoint()); 361 362 if (column == 5) { 363 return "Click me!"; 364 } else if (column != 0) { 365 return getValueAt(row, column).toString(); 366 } else { 367 return "Select if you want to use this extension!"; 368 } 369 } 370 371 public void unselectAll () { 372 for (int row : extensions.keySet()) { 373 table.setValueAt(false, row, 0); 374 } 375 } 376 377 public boolean hasExtension (String extensionName) { 378 for (ExternalExtension extension : extensions.values()) { 379 if (extension.getName().equals(extensionName)) return true; 380 } 381 return false; 382 } 383 384 public void setSelected (String extensionName, boolean selected) { 385 int row = -1; 386 for (int i : extensions.keySet()) { 387 if (extensions.get(i).getName().equals(extensionName)) { 388 row = i; 389 break; 390 } 391 } 392 if (row != -1) table.setValueAt(selected, row, 0); 393 } 394 395 public void addExtension (ExternalExtension extension, Boolean checkbox, String name, String description, String version, 396 String compatibility, URI support) { 397 addRow(new Object[] {checkbox, name, description, version, compatibility, support}); 398 extensions.put(rowCount++, extension); 399 } 400 401 } 402 403 @Override 404 public void tableChanged (TableModelEvent e) { 405 int row = e.getFirstRow(); 406 int column = e.getColumn(); 407 408 if (column == 0) { 409 ExternalExtension extension = ((ExtensionTableModel)table.getModel()).getExtension(row); 410 Dependency dep = extension.generateDependency(); 411 boolean selected = (Boolean)table.getModel().getValueAt(row, 0); 412 if (selected) { 413 if (!mainDependencies.contains(dep)) { 414 mainDependencies.add(dep); 415 } 416 } else { 417 mainDependencies.remove(dep); 418 } 419 } 420 } 421 422 } 423