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