001/* 002 * SVG Salamander 003 * Copyright (c) 2004, Mark McKay 004 * All rights reserved. 005 * 006 * Redistribution and use in source and binary forms, with or 007 * without modification, are permitted provided that the following 008 * conditions are met: 009 * 010 * - Redistributions of source code must retain the above 011 * copyright notice, this list of conditions and the following 012 * disclaimer. 013 * - Redistributions in binary form must reproduce the above 014 * copyright notice, this list of conditions and the following 015 * disclaimer in the documentation and/or other materials 016 * provided with the distribution. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 019 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 020 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 021 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 022 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 023 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 025 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 026 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 027 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 028 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 029 * OF THE POSSIBILITY OF SUCH DAMAGE. 030 * 031 * Mark McKay can be contacted at mark@kitfox.com. Salamander and other 032 * projects can be found at http://www.kitfox.com 033 * 034 * Created on April 3, 2004, 5:28 PM 035 */ 036 037package com.kitfox.svg.app; 038 039 040import com.kitfox.svg.SVGConst; 041import com.kitfox.svg.SVGDiagram; 042import com.kitfox.svg.SVGDisplayPanel; 043import com.kitfox.svg.SVGElement; 044import com.kitfox.svg.SVGException; 045import com.kitfox.svg.SVGUniverse; 046import java.awt.Color; 047import java.awt.event.MouseAdapter; 048import java.awt.event.MouseEvent; 049import java.awt.geom.Point2D; 050import java.io.File; 051import java.io.InputStream; 052import java.net.URI; 053import java.net.URL; 054import java.net.URLEncoder; 055import java.security.AccessControlException; 056import java.util.ArrayList; 057import java.util.List; 058import java.util.logging.Level; 059import java.util.logging.Logger; 060import java.util.regex.Matcher; 061import java.util.regex.Pattern; 062import javax.swing.JFileChooser; 063import javax.swing.JOptionPane; 064 065/** 066 * @author Mark McKay 067 * @author <a href="mailto:mark@kitfox.com">Mark McKay</a> 068 */ 069public class SVGPlayer extends javax.swing.JFrame 070{ 071 public static final long serialVersionUID = 1; 072 073 SVGDisplayPanel svgDisplayPanel = new SVGDisplayPanel(); 074 075 final PlayerDialog playerDialog; 076 077 SVGUniverse universe; 078 079 /** FileChooser for running in trusted environments */ 080 final JFileChooser fileChooser; 081 { 082// fileChooser = new JFileChooser(new File(".")); 083 JFileChooser fc = null; 084 try 085 { 086 fc = new JFileChooser(); 087 fc.setFileFilter( 088 new javax.swing.filechooser.FileFilter() { 089 final Matcher matchLevelFile = Pattern.compile(".*\\.svg[z]?").matcher(""); 090 091 @Override 092 public boolean accept(File file) 093 { 094 if (file.isDirectory()) return true; 095 096 matchLevelFile.reset(file.getName()); 097 return matchLevelFile.matches(); 098 } 099 100 @Override 101 public String getDescription() { return "SVG file (*.svg, *.svgz)"; } 102 } 103 ); 104 } 105 catch (AccessControlException ex) 106 { 107 //Do not create file chooser if webstart refuses permissions 108 } 109 fileChooser = fc; 110 } 111 112 /** Backup file service for opening files in WebStart situations */ 113 /* 114 final FileOpenService fileOpenService; 115 { 116 try 117 { 118 fileOpenService = (FileOpenService)ServiceManager.lookup("javax.jnlp.FileOpenService"); 119 } 120 catch (UnavailableServiceException e) 121 { 122 fileOpenService = null; 123 } 124 } 125 */ 126 127 /** Creates new form SVGViewer */ 128 public SVGPlayer() { 129 initComponents(); 130 131 setSize(800, 600); 132 133 svgDisplayPanel.setBgColor(Color.white); 134 svgDisplayPanel.addMouseListener(new MouseAdapter() 135 { 136 @Override 137 public void mouseClicked(MouseEvent evt) 138 { 139 SVGDiagram diagram = svgDisplayPanel.getDiagram(); 140 if (diagram == null) return; 141 142 System.out.println("Picking at cursor (" + evt.getX() + ", " + evt.getY() + ")"); 143 try 144 { 145 List<List<SVGElement>> paths = diagram.pick(new Point2D.Float(evt.getX(), evt.getY()), null); 146 for (int i = 0; i < paths.size(); i++) 147 { 148 System.out.println(pathToString(paths.get(i))); 149 } 150 } 151 catch (SVGException ex) 152 { 153 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, 154 "Could not pick", ex); 155 } 156 } 157 } 158 ); 159 160 svgDisplayPanel.setPreferredSize(getSize()); 161 scrollPane_svgArea.setViewportView(svgDisplayPanel); 162 163 playerDialog = new PlayerDialog(this); 164 } 165 166 private String pathToString(List<SVGElement> path) 167 { 168 if (path.size() == 0) return ""; 169 170 StringBuffer sb = new StringBuffer(); 171 sb.append(path.get(0)); 172 for (int i = 1; i < path.size(); i++) 173 { 174 sb.append("/"); 175 sb.append(path.get(i).getId()); 176 } 177 return sb.toString(); 178 } 179 180 public void updateTime(double curTime) 181 { 182 try 183 { 184 if (universe != null) 185 { 186 universe.setCurTime(curTime); 187 universe.updateTime(); 188 // svgDisplayPanel.updateTime(curTime); 189 repaint(); 190 } 191 } 192 catch (Exception e) 193 { 194 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e); 195 } 196 } 197 198 private void loadURL(URL url) 199 { 200 boolean verbose = cmCheck_verbose.isSelected(); 201 202 universe = new SVGUniverse(); 203 universe.setVerbose(verbose); 204 SVGDiagram diagram = null; 205 206 if (!CheckBoxMenuItem_anonInputStream.isSelected()) 207 { 208 //Load from a disk with a valid URL 209 URI uri = universe.loadSVG(url); 210 211 if (verbose) System.err.println(uri.toString()); 212 213 diagram = universe.getDiagram(uri); 214 } 215 else 216 { 217 //Load from a stream with no particular valid URL 218 try 219 { 220 InputStream is = url.openStream(); 221 URI uri = universe.loadSVG(is, "defaultName"); 222 223 if (verbose) System.err.println(uri.toString()); 224 225 diagram = universe.getDiagram(uri); 226 } 227 catch (Exception e) 228 { 229 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e); 230 } 231 } 232 233 svgDisplayPanel.setDiagram(diagram); 234 repaint(); 235 } 236 237 /** This method is called from within the constructor to 238 * initialize the form. 239 * WARNING: Do NOT modify this code. The content of this method is 240 * always regenerated by the Form Editor. 241 */ 242 // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents 243 private void initComponents() 244 { 245 scrollPane_svgArea = new javax.swing.JScrollPane(); 246 jMenuBar1 = new javax.swing.JMenuBar(); 247 menu_file = new javax.swing.JMenu(); 248 cm_loadFile = new javax.swing.JMenuItem(); 249 cm_loadUrl = new javax.swing.JMenuItem(); 250 menu_window = new javax.swing.JMenu(); 251 cm_player = new javax.swing.JMenuItem(); 252 jSeparator2 = new javax.swing.JSeparator(); 253 cm_800x600 = new javax.swing.JMenuItem(); 254 CheckBoxMenuItem_anonInputStream = new javax.swing.JCheckBoxMenuItem(); 255 cmCheck_verbose = new javax.swing.JCheckBoxMenuItem(); 256 menu_help = new javax.swing.JMenu(); 257 cm_about = new javax.swing.JMenuItem(); 258 259 setTitle("SVG Player - Salamander Project"); 260 addWindowListener(new java.awt.event.WindowAdapter() 261 { 262 @Override 263 public void windowClosing(java.awt.event.WindowEvent evt) 264 { 265 exitForm(evt); 266 } 267 }); 268 269 getContentPane().add(scrollPane_svgArea, java.awt.BorderLayout.CENTER); 270 271 menu_file.setMnemonic('f'); 272 menu_file.setText("File"); 273 cm_loadFile.setMnemonic('l'); 274 cm_loadFile.setText("Load File..."); 275 cm_loadFile.addActionListener(new java.awt.event.ActionListener() 276 { 277 public void actionPerformed(java.awt.event.ActionEvent evt) 278 { 279 cm_loadFileActionPerformed(evt); 280 } 281 }); 282 283 menu_file.add(cm_loadFile); 284 285 cm_loadUrl.setText("Load URL..."); 286 cm_loadUrl.addActionListener(new java.awt.event.ActionListener() 287 { 288 public void actionPerformed(java.awt.event.ActionEvent evt) 289 { 290 cm_loadUrlActionPerformed(evt); 291 } 292 }); 293 294 menu_file.add(cm_loadUrl); 295 296 jMenuBar1.add(menu_file); 297 298 menu_window.setText("Window"); 299 cm_player.setText("Player"); 300 cm_player.addActionListener(new java.awt.event.ActionListener() 301 { 302 public void actionPerformed(java.awt.event.ActionEvent evt) 303 { 304 cm_playerActionPerformed(evt); 305 } 306 }); 307 308 menu_window.add(cm_player); 309 310 menu_window.add(jSeparator2); 311 312 cm_800x600.setText("800 x 600"); 313 cm_800x600.addActionListener(new java.awt.event.ActionListener() 314 { 315 public void actionPerformed(java.awt.event.ActionEvent evt) 316 { 317 cm_800x600ActionPerformed(evt); 318 } 319 }); 320 321 menu_window.add(cm_800x600); 322 323 CheckBoxMenuItem_anonInputStream.setText("Anonymous Input Stream"); 324 menu_window.add(CheckBoxMenuItem_anonInputStream); 325 326 cmCheck_verbose.setText("Verbose"); 327 cmCheck_verbose.addActionListener(new java.awt.event.ActionListener() 328 { 329 public void actionPerformed(java.awt.event.ActionEvent evt) 330 { 331 cmCheck_verboseActionPerformed(evt); 332 } 333 }); 334 335 menu_window.add(cmCheck_verbose); 336 337 jMenuBar1.add(menu_window); 338 339 menu_help.setText("Help"); 340 cm_about.setText("About..."); 341 cm_about.addActionListener(new java.awt.event.ActionListener() 342 { 343 public void actionPerformed(java.awt.event.ActionEvent evt) 344 { 345 cm_aboutActionPerformed(evt); 346 } 347 }); 348 349 menu_help.add(cm_about); 350 351 jMenuBar1.add(menu_help); 352 353 setJMenuBar(jMenuBar1); 354 355 pack(); 356 }// </editor-fold>//GEN-END:initComponents 357 358 private void cm_loadUrlActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_loadUrlActionPerformed 359 {//GEN-HEADEREND:event_cm_loadUrlActionPerformed 360 String urlStrn = JOptionPane.showInputDialog(this, "Enter URL of SVG file"); 361 if (urlStrn == null) return; 362 363 try 364 { 365 URL url = new URL(URLEncoder.encode(urlStrn, "UTF-8")); 366 loadURL(url); 367 } 368 catch (Exception e) 369 { 370 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e); 371 } 372 373 }//GEN-LAST:event_cm_loadUrlActionPerformed 374 375 private void cmCheck_verboseActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cmCheck_verboseActionPerformed 376 {//GEN-HEADEREND:event_cmCheck_verboseActionPerformed 377// TODO add your handling code here: 378 }//GEN-LAST:event_cmCheck_verboseActionPerformed 379 380 private void cm_playerActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_playerActionPerformed 381 {//GEN-HEADEREND:event_cm_playerActionPerformed 382 playerDialog.setVisible(true); 383 }//GEN-LAST:event_cm_playerActionPerformed 384 385 private void cm_aboutActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_aboutActionPerformed 386 {//GEN-HEADEREND:event_cm_aboutActionPerformed 387 VersionDialog dia = new VersionDialog(this, true, cmCheck_verbose.isSelected()); 388 dia.setVisible(true); 389// JOptionPane.showMessageDialog(this, "Salamander SVG - Created by Mark McKay\nhttp://www.kitfox.com"); 390 }//GEN-LAST:event_cm_aboutActionPerformed 391 392 private void cm_800x600ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cm_800x600ActionPerformed 393 setSize(800, 600); 394 }//GEN-LAST:event_cm_800x600ActionPerformed 395 396 private void cm_loadFileActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_loadFileActionPerformed 397 {//GEN-HEADEREND:event_cm_loadFileActionPerformed 398 boolean verbose = cmCheck_verbose.isSelected(); 399 400 try 401 { 402 int retVal = fileChooser.showOpenDialog(this); 403 if (retVal == JFileChooser.APPROVE_OPTION) 404 { 405 File chosenFile = fileChooser.getSelectedFile(); 406 407 URL url = chosenFile.toURI().toURL(); 408 409 loadURL(url); 410 } 411 } 412 catch (Exception e) 413 { 414 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e); 415 } 416 417 }//GEN-LAST:event_cm_loadFileActionPerformed 418 419 /** Exit the Application */ 420 private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm 421 System.exit(0); 422 }//GEN-LAST:event_exitForm 423 424 /** 425 * @param args the command line arguments 426 */ 427 public static void main(String args[]) { 428 new SVGPlayer().setVisible(true); 429 } 430 431 public void updateTime(double curTime, double timeStep, int playState) 432 { 433 } 434 435 // Variables declaration - do not modify//GEN-BEGIN:variables 436 private javax.swing.JCheckBoxMenuItem CheckBoxMenuItem_anonInputStream; 437 private javax.swing.JCheckBoxMenuItem cmCheck_verbose; 438 private javax.swing.JMenuItem cm_800x600; 439 private javax.swing.JMenuItem cm_about; 440 private javax.swing.JMenuItem cm_loadFile; 441 private javax.swing.JMenuItem cm_loadUrl; 442 private javax.swing.JMenuItem cm_player; 443 private javax.swing.JMenuBar jMenuBar1; 444 private javax.swing.JSeparator jSeparator2; 445 private javax.swing.JMenu menu_file; 446 private javax.swing.JMenu menu_help; 447 private javax.swing.JMenu menu_window; 448 private javax.swing.JScrollPane scrollPane_svgArea; 449 // End of variables declaration//GEN-END:variables 450 451}