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