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.Vector; 059import java.util.logging.Level; 060import java.util.logging.Logger; 061import java.util.regex.Matcher; 062import java.util.regex.Pattern; 063import javax.swing.JFileChooser; 064import javax.swing.JOptionPane; 065 066/** 067 * @author Mark McKay 068 * @author <a href="mailto:mark@kitfox.com">Mark McKay</a> 069 */ 070public class SVGPlayer extends javax.swing.JFrame 071{ 072 public static final long serialVersionUID = 1; 073 074 SVGDisplayPanel svgDisplayPanel = new SVGDisplayPanel(); 075 076 final PlayerDialog playerDialog; 077 078 SVGUniverse universe; 079 080 /** FileChooser for running in trusted environments */ 081 final JFileChooser fileChooser; 082 { 083// fileChooser = new JFileChooser(new File(".")); 084 JFileChooser fc = null; 085 try 086 { 087 fc = new JFileChooser(); 088 fc.setFileFilter( 089 new javax.swing.filechooser.FileFilter() { 090 final Matcher matchLevelFile = Pattern.compile(".*\\.svg[z]?").matcher(""); 091 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 public String getDescription() { return "SVG file (*.svg, *.svgz)"; } 101 } 102 ); 103 } 104 catch (AccessControlException ex) 105 { 106 //Do not create file chooser if webstart refuses permissions 107 } 108 fileChooser = fc; 109 } 110 111 /** Backup file service for opening files in WebStart situations */ 112 /* 113 final FileOpenService fileOpenService; 114 { 115 try 116 { 117 fileOpenService = (FileOpenService)ServiceManager.lookup("javax.jnlp.FileOpenService"); 118 } 119 catch (UnavailableServiceException e) 120 { 121 fileOpenService = null; 122 } 123 } 124 */ 125 126 /** Creates new form SVGViewer */ 127 public SVGPlayer() { 128 initComponents(); 129 130 setSize(800, 600); 131 132 svgDisplayPanel.setBgColor(Color.white); 133 svgDisplayPanel.addMouseListener(new MouseAdapter() 134 { 135 public void mouseClicked(MouseEvent evt) 136 { 137 SVGDiagram diagram = svgDisplayPanel.getDiagram(); 138 if (diagram == null) return; 139 140 System.out.println("Picking at cursor (" + evt.getX() + ", " + evt.getY() + ")"); 141 try 142 { 143 List paths = diagram.pick(new Point2D.Float(evt.getX(), evt.getY()), null); 144 for (int i = 0; i < paths.size(); i++) 145 { 146 ArrayList path = (ArrayList)paths.get(i); 147 System.out.println(pathToString(path)); 148 } 149 } 150 catch (SVGException ex) 151 { 152 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, 153 "Could not pick", ex); 154 } 155 } 156 } 157 ); 158 159 svgDisplayPanel.setPreferredSize(getSize()); 160 scrollPane_svgArea.setViewportView(svgDisplayPanel); 161 162 playerDialog = new PlayerDialog(this); 163 } 164 165 private String pathToString(List path) 166 { 167 if (path.size() == 0) return ""; 168 169 StringBuffer sb = new StringBuffer(); 170 sb.append(path.get(0)); 171 for (int i = 1; i < path.size(); i++) 172 { 173 sb.append("/"); 174 sb.append(((SVGElement)path.get(i)).getId()); 175 } 176 return sb.toString(); 177 } 178 179 public void updateTime(double curTime) 180 { 181 try 182 { 183 if (universe != null) 184 { 185 universe.setCurTime(curTime); 186 universe.updateTime(); 187 // svgDisplayPanel.updateTime(curTime); 188 repaint(); 189 } 190 } 191 catch (Exception e) 192 { 193 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e); 194 } 195 } 196 197 private void loadURL(URL url) 198 { 199 boolean verbose = cmCheck_verbose.isSelected(); 200 201 universe = new SVGUniverse(); 202 universe.setVerbose(verbose); 203 SVGDiagram diagram = null; 204 205 if (!CheckBoxMenuItem_anonInputStream.isSelected()) 206 { 207 //Load from a disk with a valid URL 208 URI uri = universe.loadSVG(url); 209 210 if (verbose) System.err.println(uri.toString()); 211 212 diagram = universe.getDiagram(uri); 213 } 214 else 215 { 216 //Load from a stream with no particular valid URL 217 try 218 { 219 InputStream is = url.openStream(); 220 URI uri = universe.loadSVG(is, "defaultName"); 221 222 if (verbose) System.err.println(uri.toString()); 223 224 diagram = universe.getDiagram(uri); 225 } 226 catch (Exception e) 227 { 228 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e); 229 } 230 } 231 232 svgDisplayPanel.setDiagram(diagram); 233 repaint(); 234 } 235 236 /** This method is called from within the constructor to 237 * initialize the form. 238 * WARNING: Do NOT modify this code. The content of this method is 239 * always regenerated by the Form Editor. 240 */ 241 // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents 242 private void initComponents() 243 { 244 scrollPane_svgArea = new javax.swing.JScrollPane(); 245 jMenuBar1 = new javax.swing.JMenuBar(); 246 menu_file = new javax.swing.JMenu(); 247 cm_loadFile = new javax.swing.JMenuItem(); 248 cm_loadUrl = new javax.swing.JMenuItem(); 249 menu_window = new javax.swing.JMenu(); 250 cm_player = new javax.swing.JMenuItem(); 251 jSeparator2 = new javax.swing.JSeparator(); 252 cm_800x600 = new javax.swing.JMenuItem(); 253 CheckBoxMenuItem_anonInputStream = new javax.swing.JCheckBoxMenuItem(); 254 cmCheck_verbose = new javax.swing.JCheckBoxMenuItem(); 255 menu_help = new javax.swing.JMenu(); 256 cm_about = new javax.swing.JMenuItem(); 257 258 setTitle("SVG Player - Salamander Project"); 259 addWindowListener(new java.awt.event.WindowAdapter() 260 { 261 public void windowClosing(java.awt.event.WindowEvent evt) 262 { 263 exitForm(evt); 264 } 265 }); 266 267 getContentPane().add(scrollPane_svgArea, java.awt.BorderLayout.CENTER); 268 269 menu_file.setMnemonic('f'); 270 menu_file.setText("File"); 271 cm_loadFile.setMnemonic('l'); 272 cm_loadFile.setText("Load File..."); 273 cm_loadFile.addActionListener(new java.awt.event.ActionListener() 274 { 275 public void actionPerformed(java.awt.event.ActionEvent evt) 276 { 277 cm_loadFileActionPerformed(evt); 278 } 279 }); 280 281 menu_file.add(cm_loadFile); 282 283 cm_loadUrl.setText("Load URL..."); 284 cm_loadUrl.addActionListener(new java.awt.event.ActionListener() 285 { 286 public void actionPerformed(java.awt.event.ActionEvent evt) 287 { 288 cm_loadUrlActionPerformed(evt); 289 } 290 }); 291 292 menu_file.add(cm_loadUrl); 293 294 jMenuBar1.add(menu_file); 295 296 menu_window.setText("Window"); 297 cm_player.setText("Player"); 298 cm_player.addActionListener(new java.awt.event.ActionListener() 299 { 300 public void actionPerformed(java.awt.event.ActionEvent evt) 301 { 302 cm_playerActionPerformed(evt); 303 } 304 }); 305 306 menu_window.add(cm_player); 307 308 menu_window.add(jSeparator2); 309 310 cm_800x600.setText("800 x 600"); 311 cm_800x600.addActionListener(new java.awt.event.ActionListener() 312 { 313 public void actionPerformed(java.awt.event.ActionEvent evt) 314 { 315 cm_800x600ActionPerformed(evt); 316 } 317 }); 318 319 menu_window.add(cm_800x600); 320 321 CheckBoxMenuItem_anonInputStream.setText("Anonymous Input Stream"); 322 menu_window.add(CheckBoxMenuItem_anonInputStream); 323 324 cmCheck_verbose.setText("Verbose"); 325 cmCheck_verbose.addActionListener(new java.awt.event.ActionListener() 326 { 327 public void actionPerformed(java.awt.event.ActionEvent evt) 328 { 329 cmCheck_verboseActionPerformed(evt); 330 } 331 }); 332 333 menu_window.add(cmCheck_verbose); 334 335 jMenuBar1.add(menu_window); 336 337 menu_help.setText("Help"); 338 cm_about.setText("About..."); 339 cm_about.addActionListener(new java.awt.event.ActionListener() 340 { 341 public void actionPerformed(java.awt.event.ActionEvent evt) 342 { 343 cm_aboutActionPerformed(evt); 344 } 345 }); 346 347 menu_help.add(cm_about); 348 349 jMenuBar1.add(menu_help); 350 351 setJMenuBar(jMenuBar1); 352 353 pack(); 354 }// </editor-fold>//GEN-END:initComponents 355 356 private void cm_loadUrlActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_loadUrlActionPerformed 357 {//GEN-HEADEREND:event_cm_loadUrlActionPerformed 358 String urlStrn = JOptionPane.showInputDialog(this, "Enter URL of SVG file"); 359 if (urlStrn == null) return; 360 361 try 362 { 363 URL url = new URL(URLEncoder.encode(urlStrn, "UTF-8")); 364 loadURL(url); 365 } 366 catch (Exception e) 367 { 368 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e); 369 } 370 371 }//GEN-LAST:event_cm_loadUrlActionPerformed 372 373 private void cmCheck_verboseActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cmCheck_verboseActionPerformed 374 {//GEN-HEADEREND:event_cmCheck_verboseActionPerformed 375// TODO add your handling code here: 376 }//GEN-LAST:event_cmCheck_verboseActionPerformed 377 378 private void cm_playerActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_playerActionPerformed 379 {//GEN-HEADEREND:event_cm_playerActionPerformed 380 playerDialog.setVisible(true); 381 }//GEN-LAST:event_cm_playerActionPerformed 382 383 private void cm_aboutActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_aboutActionPerformed 384 {//GEN-HEADEREND:event_cm_aboutActionPerformed 385 VersionDialog dia = new VersionDialog(this, true, cmCheck_verbose.isSelected()); 386 dia.setVisible(true); 387// JOptionPane.showMessageDialog(this, "Salamander SVG - Created by Mark McKay\nhttp://www.kitfox.com"); 388 }//GEN-LAST:event_cm_aboutActionPerformed 389 390 private void cm_800x600ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cm_800x600ActionPerformed 391 setSize(800, 600); 392 }//GEN-LAST:event_cm_800x600ActionPerformed 393 394 private void cm_loadFileActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_cm_loadFileActionPerformed 395 {//GEN-HEADEREND:event_cm_loadFileActionPerformed 396 boolean verbose = cmCheck_verbose.isSelected(); 397 398 try 399 { 400 int retVal = fileChooser.showOpenDialog(this); 401 if (retVal == JFileChooser.APPROVE_OPTION) 402 { 403 File chosenFile = fileChooser.getSelectedFile(); 404 405 URL url = chosenFile.toURI().toURL(); 406 407 loadURL(url); 408 } 409 } 410 catch (Exception e) 411 { 412 Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, null, e); 413 } 414 415 }//GEN-LAST:event_cm_loadFileActionPerformed 416 417 /** Exit the Application */ 418 private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm 419 System.exit(0); 420 }//GEN-LAST:event_exitForm 421 422 /** 423 * @param args the command line arguments 424 */ 425 public static void main(String args[]) { 426 new SVGPlayer().setVisible(true); 427 } 428 429 public void updateTime(double curTime, double timeStep, int playState) 430 { 431 } 432 433 // Variables declaration - do not modify//GEN-BEGIN:variables 434 private javax.swing.JCheckBoxMenuItem CheckBoxMenuItem_anonInputStream; 435 private javax.swing.JCheckBoxMenuItem cmCheck_verbose; 436 private javax.swing.JMenuItem cm_800x600; 437 private javax.swing.JMenuItem cm_about; 438 private javax.swing.JMenuItem cm_loadFile; 439 private javax.swing.JMenuItem cm_loadUrl; 440 private javax.swing.JMenuItem cm_player; 441 private javax.swing.JMenuBar jMenuBar1; 442 private javax.swing.JSeparator jSeparator2; 443 private javax.swing.JMenu menu_file; 444 private javax.swing.JMenu menu_help; 445 private javax.swing.JMenu menu_window; 446 private javax.swing.JScrollPane scrollPane_svgArea; 447 // End of variables declaration//GEN-END:variables 448 449}