mbien commented on code in PR #7938:
URL: https://github.com/apache/netbeans/pull/7938#discussion_r1893152379


##########
ide/svg/src/org/netbeans/modules/svg/toolbar/SVGViewerToolbar.java:
##########
@@ -0,0 +1,206 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.svg.toolbar;
+
+import java.awt.Color;
+import org.netbeans.modules.svg.toolbar.actions.CustomZoomAction;
+import org.netbeans.modules.svg.toolbar.actions.ZoomInAction;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JToolBar;
+import org.netbeans.modules.svg.BackgroundMode;
+import org.netbeans.modules.svg.SVGViewerElement;
+import org.netbeans.modules.svg.toolbar.actions.ZoomOutAction;
+import org.openide.util.ImageUtilities;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ * @author Christian Lenz
+ */
+public class SVGViewerToolbar {
+
+    /**
+     * collection of all buttons in the toolbar
+     */
+    private final Collection<JButton> toolbarButtons = new ArrayList<>(11);
+    private SVGViewerElement svgViewerElement;
+    private final DecimalFormat formatter = new DecimalFormat("#.##"); //NOI18N
+    private CustomZoomAction customZoomAction;
+
+    public JToolBar createToolbar(SVGViewerElement svgViewerElement) {
+        this.svgViewerElement = svgViewerElement;
+
+        // Initialisiere die CustomZoomAction nur einmal
+        if (customZoomAction == null) {
+            customZoomAction = new CustomZoomAction();
+            customZoomAction.setSvgViewerElement(svgViewerElement);
+        }
+
+        JToolBar toolBar = new JToolBar();
+
+        toolBar.putClientProperty("JToolBar.isRollover", Boolean.TRUE); 
//NOI18N
+        toolBar.setFloatable(false);
+        toolBar.setName(NbBundle.getMessage(SVGViewerToolbar.class, 
"ACSN_Toolbar"));
+        
toolBar.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(SVGViewerToolbar.class,
 "ACSD_Toolbar"));
+
+        ZoomOutAction zoomOutAction = new ZoomOutAction();
+        zoomOutAction.setSvgViewerElement(svgViewerElement);
+        JButton outButton = new JButton(zoomOutAction);
+        
outButton.setIcon(ImageUtilities.loadImageIcon("org/netbeans/modules/image/zoomOut.gif",
 false));
+        outButton.setToolTipText(NbBundle.getMessage(ZoomOutAction.class, 
"LBL_ZoomOut"));
+        outButton.setMnemonic(NbBundle.getMessage(SVGViewerToolbar.class, 
"ACS_Out_BTN_Mnem").charAt(0));
+        
outButton.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(SVGViewerToolbar.class,
 "ACSD_Out_BTN"));
+        outButton.setText("");
+        outButton.addActionListener((ActionEvent e) -> {
+            svgViewerElement.zoomOut();
+        });
+        toolBar.add(outButton);
+        toolbarButtons.add(outButton);
+
+        ZoomInAction zoomInAction = new ZoomInAction();
+        zoomInAction.setSvgViewerElement(svgViewerElement);
+        JButton inButton = new JButton(zoomInAction);
+        inButton.setToolTipText(NbBundle.getMessage(ZoomInAction.class, 
"LBL_ZoomIn"));
+        inButton.setMnemonic(NbBundle.getMessage(SVGViewerToolbar.class, 
"ACS_In_BTN_Mnem").charAt(0));
+        
inButton.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(SVGViewerToolbar.class,
 "ACSD_In_BTN"));
+        inButton.setText("");
+        inButton.addActionListener((ActionEvent e) -> {
+            svgViewerElement.zoomIn();
+        });
+        toolBar.add(inButton);
+        toolbarButtons.add(inButton);
+
+        toolBar.addSeparator(new Dimension(11, 0));
+
+        JButton button;
+        toolBar.add(button = getZoomButton(1, 1));
+        toolbarButtons.add(button);
+        toolBar.addSeparator(new Dimension(11, 0));
+        toolBar.add(button = getZoomButton(1, 3));
+        toolbarButtons.add(button);
+        toolBar.add(button = getZoomButton(1, 5));
+        toolbarButtons.add(button);
+        toolBar.add(button = getZoomButton(1, 7));
+        toolbarButtons.add(button);
+        toolBar.addSeparator(new Dimension(11, 0));
+        toolBar.add(button = getZoomButton(3, 1));
+        toolbarButtons.add(button);
+        toolBar.add(button = getZoomButton(5, 1));
+        toolbarButtons.add(button);
+        toolBar.add(button = getZoomButton(7, 1));
+        toolbarButtons.add(button);
+
+        toolBar.addSeparator(new Dimension(11, 0));
+
+        toolBar.add(button = getZoomButton());
+        toolbarButtons.add(button);
+
+        toolBar.addSeparator(new Dimension(11, 0));
+
+        // Backgrounds
+        toolBar.add(button = getCustomBackgroundButton(BackgroundMode.BLACK, 
Color.BLACK));
+        toolbarButtons.add(button);
+        toolBar.add(button = getCustomBackgroundButton(BackgroundMode.WHITE, 
Color.WHITE));
+        toolbarButtons.add(button);
+        toolBar.add(button = 
getCustomBackgroundButton(BackgroundMode.TRANSPARENT, Color.LIGHT_GRAY));
+        toolbarButtons.add(button);
+        toolBar.add(button = 
getCustomBackgroundButton(BackgroundMode.DARK_TRANSPARENT, Color.DARK_GRAY));
+        toolbarButtons.add(button);
+        toolBar.add(button = getCustomBackgroundButton(BackgroundMode.DEFAULT, 
Color.WHITE));
+        toolbarButtons.add(button);
+
+        // Image Dimension
+        toolBar.addSeparator(new Dimension(11, 0));
+        toolBar.add(new JLabel(NbBundle.getMessage(SVGViewerToolbar.class, 
"LBL_ImageDimensions", svgViewerElement.getImageWidth(), 
svgViewerElement.getImageHeight())));
+
+        // Image File Size in KB, MB
+        if (svgViewerElement.getImageSize() != -1) {
+            toolBar.addSeparator(new Dimension(11, 0));
+            double kb = 1024.0;
+            double mb = kb * kb;
+            final double size;
+            final String label;
+            if (svgViewerElement.getImageSize() >= mb) {
+                size = svgViewerElement.getImageSize() / mb;
+                label = "LBL_ImageSizeMb"; // NOI18N
+            } else if (svgViewerElement.getImageSize() >= kb) {
+                size = svgViewerElement.getImageSize() / kb;
+                label = "LBL_ImageSizeKb"; // NOI18N
+            } else {
+                size = svgViewerElement.getImageSize();
+                label = "LBL_ImageSizeBytes"; //NOI18N
+            }
+
+            toolBar.add(new JLabel(NbBundle.getMessage(SVGViewerToolbar.class, 
label, formatter.format(size))));
+        }
+        for (JButton jb : toolbarButtons) {
+            jb.setFocusable(false);
+        }
+        return toolBar;
+    }
+
+    /**
+     * Gets zoom button.
+     */
+    private JButton getZoomButton(final int xf, final int yf) {

Review Comment:
   all getters in this class are essentially factory methods. 
   
   analog to `createToolbar` above, I think `create*` would describe it better.



##########
ide/svg/src/org/netbeans/modules/svg/SVGViewerElement.java:
##########
@@ -0,0 +1,351 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.svg;
+
+import com.github.weisj.jsvg.SVGDocument;
+import com.github.weisj.jsvg.geometry.size.FloatSize;
+import com.github.weisj.jsvg.parser.SVGLoader;
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.Action;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JToolBar;
+import org.netbeans.core.spi.multiview.CloseOperationState;
+import org.netbeans.core.spi.multiview.MultiViewElement;
+import org.netbeans.core.spi.multiview.MultiViewElementCallback;
+import org.netbeans.modules.svg.toolbar.SVGViewerToolbar;
+import org.openide.awt.UndoRedo;
+import org.openide.filesystems.FileChangeAdapter;
+import org.openide.filesystems.FileChangeListener;
+import org.openide.filesystems.FileEvent;
+import org.openide.filesystems.FileObject;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle.Messages;
+import org.openide.windows.TopComponent;
+
+/**
+ *
+ * @author Christian Lenz
+ */
[email protected](
+    displayName = "#LBL_SVGViewer",
+    iconBase = "org/netbeans/modules/svg/resources/svgLogo.png",
+    mimeType = "image/svg+xml",
+    persistenceType = TopComponent.PERSISTENCE_NEVER,
+    preferredID = "SVGViewer",
+    position = 1100
+)
+@Messages("LBL_SVGViewer=Preview")
+public class SVGViewerElement implements MultiViewElement {
+
+    private static final Logger LOG = 
Logger.getLogger(SVGViewerElement.class.getName());
+
+    private final SVGDataObject dataObject;
+    private transient JToolBar toolbar;
+    private transient JComponent component;
+
+    /**
+     * Component showing SVG.
+     */
+    private transient JPanel viewer;
+
+    private final SVGLoader svgLoader = new SVGLoader();
+    private final SVGPanel svgPanel = new SVGPanel();
+    private SVGDocument svgDocument = null;
+
+    private int imageHeight = 0;
+    private int imageWidth = 0;
+    private long imageSize = -1;
+
+    /**
+     * Scale of SVG.
+     */
+    private double scale = 1.0D;
+
+    /**
+     * Increase/decrease factor.
+     */
+    private final double changeFactor = Math.sqrt(2.0D);
+
+    private final FileChangeListener fcl = new FileChangeAdapter() {
+        @Override
+        public void fileChanged(FileEvent fe) {
+            updateView();
+        }
+    };
+
+    public SVGViewerElement(Lookup lookup) {
+        dataObject = lookup.lookup(SVGDataObject.class);
+    }
+
+    @Override
+    public JComponent getVisualRepresentation() {
+        if (component == null) {
+            viewer = new JPanel();
+            component = viewer;
+        }
+
+        return component;
+    }
+
+    @Override
+    public JComponent getToolbarRepresentation() {
+        if (toolbar == null) {
+            toolbar = new SVGViewerToolbar().createToolbar(this);
+        }
+
+        return toolbar;
+    }
+
+    @Override
+    public Action[] getActions() {
+        return new Action[0];
+    }
+
+    @Override
+    public Lookup getLookup() {
+        return dataObject.getLookup();
+    }
+
+    @Override
+    public void componentOpened() {
+        dataObject.getPrimaryFile().addFileChangeListener(fcl);
+
+        updateView();
+    }
+
+    @Override
+    public void componentClosed() {
+        dataObject.getPrimaryFile().removeFileChangeListener(fcl);
+    }
+
+    @Override
+    public void componentShowing() {
+    }
+
+    @Override
+    public void componentHidden() {
+    }
+
+    @Override
+    public void componentActivated() {
+    }
+
+    @Override
+    public void componentDeactivated() {
+    }
+
+    @Override
+    public UndoRedo getUndoRedo() {
+        return UndoRedo.NONE;
+    }
+
+    @Override
+    public void setMultiViewCallback(MultiViewElementCallback callback) {
+    }
+
+    @Override
+    public CloseOperationState canCloseElement() {
+        return CloseOperationState.STATE_OK;
+    }
+
+    private void addMouseWheelListenerToViewer(JScrollPane scrollPane) {
+        svgPanel.addMouseWheelListener(e -> {
+            double oldScale = scale;
+
+            // Point in scrolled pane
+            Point visiblePoint = e.getPoint();
+
+            // "Picturepixel"
+            Point markedPoint = new Point(
+                (int) (visiblePoint.getX() / oldScale),
+                (int) (visiblePoint.getY() / oldScale));
+
+            int clicks = e.getWheelRotation();
+            int clicks_abs = Math.abs(clicks);
+            for (int i = 0; i < clicks_abs; i++) {
+                if (clicks < 0) {
+                    zoomIn();
+                } else {
+                    zoomOut();
+                }
+            }
+
+            double newScale = scale;
+
+            Point markedPointInRealSpace = new Point(
+                (int) (markedPoint.getX() * newScale),
+                (int) (markedPoint.getY() * newScale)
+            );
+
+            Rectangle r = scrollPane.getViewport().getViewRect();
+
+            r.setLocation(markedPointInRealSpace);
+            r.translate(-r.width / 2, -r.height / 2);
+
+            svgPanel.scrollRectToVisible(r);
+        });
+    }
+
+    private void updateView() {
+        FileObject fo = dataObject.getPrimaryFile();
+
+        if (fo == null) {
+            return;
+        }
+
+        if (viewer == null) {
+            return;
+        }
+
+        svgDocument = svgLoader.load(fo.toURL());

Review Comment:
   not sure what the failure mode of SVGLoader is. Does it return null? Throw 
runtime exceptions? Javadoc unfortunately doesn't mention it. Probably 
something we should test by trying to load a broken svg file.
   
   It would be better to extract loading into a utility method, which handles 
logging and Exceptions, so that both `SvgNavigatorPanel` and `SVGViewerElement` 
can use it.



##########
ide/svg/src/org/netbeans/modules/svg/navigation/SvgNavigatorPanel.java:
##########
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.svg.navigation;
+
+import com.github.weisj.jsvg.SVGDocument;
+import com.github.weisj.jsvg.parser.SVGLoader;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.JComponent;
+import javax.swing.SwingUtilities;
+import org.netbeans.modules.svg.SVGDataObject;
+import org.netbeans.modules.svg.SVGViewerElement;
+import org.netbeans.spi.navigator.NavigatorPanel;
+import org.openide.filesystems.FileChangeAdapter;
+import org.openide.filesystems.FileChangeListener;
+import org.openide.filesystems.FileEvent;
+import org.openide.filesystems.FileObject;
+import org.openide.loaders.DataObject;
+import org.openide.loaders.DataObjectNotFoundException;
+import org.openide.util.*;
+
+/**
+ *
+ * @author christian lenz
+ */
[email protected]({
+    @NavigatorPanel.Registration(mimeType = "image/svg+xml", displayName = 
"#Navigator_DisplayName")
+})
+public class SvgNavigatorPanel implements NavigatorPanel {
+
+    private static final Logger LOG = 
Logger.getLogger(SVGViewerElement.class.getName());
+
+    /**
+     * holds UI of this panel
+     */
+    private SvgPreviewPanel panelUI;
+    /**
+     * template for finding data in given context. Object used as example,
+     * replace with your own data source, for example JavaDataObject etc
+     */
+    private static final Lookup.Template<SVGDataObject> MY_DATA = new 
Lookup.Template<>(SVGDataObject.class);
+    /**
+     * current context to work on
+     */
+    private Lookup.Result<SVGDataObject> currentContext;
+    /**
+     * listener to context changes
+     */
+    private LookupListener contextListener;
+    /**
+     * Listens for changes on image file.
+     */
+    private FileChangeListener fileChangeListener;
+    private long lastSaveTime = -1;
+    private DataObject currentDataObject;
+    private static final RequestProcessor WORKER = new 
RequestProcessor(SvgNavigatorPanel.class.getName());
+
+    @Override
+    public String getDisplayName() {
+        return NbBundle.getMessage(SvgNavigatorPanel.class, 
"Navigator_DisplayName");
+    }
+
+    @Override
+    public String getDisplayHint() {
+        return NbBundle.getMessage(SvgNavigatorPanel.class, 
"Navigator_DisplayHint");
+    }
+
+    @Override
+    public JComponent getComponent() {
+        if (lastSaveTime == -1) {
+            lastSaveTime = System.currentTimeMillis();
+        }
+        if (panelUI == null) {
+            panelUI = new SvgPreviewPanel();
+        }
+        return panelUI;
+    }
+
+    @Override
+    public void panelActivated(Lookup context) {
+        // lookup context and listen to result to get notified about context 
changes
+        currentContext = context.lookup(MY_DATA);
+        currentContext.addLookupListener(getContextListener());
+        // get actual data and recompute content
+        Collection<? extends SVGDataObject> data = 
currentContext.allInstances();
+        currentDataObject = getDataObject(data);
+
+        if (currentDataObject == null) {
+            return;
+        }
+
+        if (fileChangeListener == null) {
+            fileChangeListener = new SvgFileChangeAdapter();
+        }
+        
currentDataObject.getPrimaryFile().addFileChangeListener(fileChangeListener);
+        setNewContent(currentDataObject);
+    }
+
+    @Override
+    public void panelDeactivated() {
+        currentContext.removeLookupListener(getContextListener());
+        currentContext = null;
+        if (currentDataObject != null) {
+            
currentDataObject.getPrimaryFile().removeFileChangeListener(fileChangeListener);
+        }
+        currentDataObject = null;
+    }
+
+    @Override
+    public Lookup getLookup() {
+        // go with default activated Node strategy
+        return null;
+    }
+
+    private void setNewContent(final DataObject dataObject) {
+        if (dataObject == null) {
+            return;
+        }
+
+        WORKER.post(() -> {
+            FileObject fo = dataObject.getPrimaryFile();
+
+            if (fo == null) {
+                return;
+            }
+
+            if (panelUI == null) {
+                return;
+            }
+
+            try {
+                SVGLoader svgLoader = new SVGLoader();
+                SVGDocument svgDocument = svgLoader.load(fo.toURL());
+
+                SwingUtilities.invokeLater(() -> panelUI.setSvg(svgDocument));
+            } catch (Exception ex) {
+                LOG.log(Level.SEVERE, ex.getMessage());

Review Comment:
   ```java
                   LOG.log(Level.SEVERE, "can not load svg: " + fo, ex);
   ```
   retains stack and lists the file. Note that `SVGViewerElement` does also 
load SVGs, see other comment.



##########
ide/svg/src/org/netbeans/modules/svg/navigation/SvgNavigatorPanel.java:
##########
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.svg.navigation;
+
+import com.github.weisj.jsvg.SVGDocument;
+import com.github.weisj.jsvg.parser.SVGLoader;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.JComponent;
+import javax.swing.SwingUtilities;
+import org.netbeans.modules.svg.SVGDataObject;
+import org.netbeans.modules.svg.SVGViewerElement;
+import org.netbeans.spi.navigator.NavigatorPanel;
+import org.openide.filesystems.FileChangeAdapter;
+import org.openide.filesystems.FileChangeListener;
+import org.openide.filesystems.FileEvent;
+import org.openide.filesystems.FileObject;
+import org.openide.loaders.DataObject;
+import org.openide.loaders.DataObjectNotFoundException;
+import org.openide.util.*;
+
+/**
+ *
+ * @author christian lenz
+ */
[email protected]({
+    @NavigatorPanel.Registration(mimeType = "image/svg+xml", displayName = 
"#Navigator_DisplayName")
+})
+public class SvgNavigatorPanel implements NavigatorPanel {
+
+    private static final Logger LOG = 
Logger.getLogger(SVGViewerElement.class.getName());
+
+    /**
+     * holds UI of this panel
+     */
+    private SvgPreviewPanel panelUI;
+    /**
+     * template for finding data in given context. Object used as example,
+     * replace with your own data source, for example JavaDataObject etc
+     */
+    private static final Lookup.Template<SVGDataObject> MY_DATA = new 
Lookup.Template<>(SVGDataObject.class);
+    /**
+     * current context to work on
+     */
+    private Lookup.Result<SVGDataObject> currentContext;
+    /**
+     * listener to context changes
+     */
+    private LookupListener contextListener;
+    /**
+     * Listens for changes on image file.
+     */
+    private FileChangeListener fileChangeListener;
+    private long lastSaveTime = -1;
+    private DataObject currentDataObject;
+    private static final RequestProcessor WORKER = new 
RequestProcessor(SvgNavigatorPanel.class.getName());
+
+    @Override
+    public String getDisplayName() {
+        return NbBundle.getMessage(SvgNavigatorPanel.class, 
"Navigator_DisplayName");
+    }
+
+    @Override
+    public String getDisplayHint() {
+        return NbBundle.getMessage(SvgNavigatorPanel.class, 
"Navigator_DisplayHint");
+    }
+
+    @Override
+    public JComponent getComponent() {
+        if (lastSaveTime == -1) {
+            lastSaveTime = System.currentTimeMillis();
+        }
+        if (panelUI == null) {
+            panelUI = new SvgPreviewPanel();
+        }
+        return panelUI;
+    }
+
+    @Override
+    public void panelActivated(Lookup context) {
+        // lookup context and listen to result to get notified about context 
changes
+        currentContext = context.lookup(MY_DATA);
+        currentContext.addLookupListener(getContextListener());
+        // get actual data and recompute content
+        Collection<? extends SVGDataObject> data = 
currentContext.allInstances();
+        currentDataObject = getDataObject(data);
+
+        if (currentDataObject == null) {
+            return;
+        }
+
+        if (fileChangeListener == null) {
+            fileChangeListener = new SvgFileChangeAdapter();
+        }
+        
currentDataObject.getPrimaryFile().addFileChangeListener(fileChangeListener);
+        setNewContent(currentDataObject);
+    }
+
+    @Override
+    public void panelDeactivated() {
+        currentContext.removeLookupListener(getContextListener());
+        currentContext = null;
+        if (currentDataObject != null) {
+            
currentDataObject.getPrimaryFile().removeFileChangeListener(fileChangeListener);
+        }
+        currentDataObject = null;
+    }
+
+    @Override
+    public Lookup getLookup() {
+        // go with default activated Node strategy
+        return null;
+    }
+
+    private void setNewContent(final DataObject dataObject) {
+        if (dataObject == null) {
+            return;
+        }
+
+        WORKER.post(() -> {
+            FileObject fo = dataObject.getPrimaryFile();
+
+            if (fo == null) {
+                return;
+            }
+
+            if (panelUI == null) {
+                return;
+            }
+
+            try {
+                SVGLoader svgLoader = new SVGLoader();
+                SVGDocument svgDocument = svgLoader.load(fo.toURL());
+
+                SwingUtilities.invokeLater(() -> panelUI.setSvg(svgDocument));
+            } catch (Exception ex) {
+                LOG.log(Level.SEVERE, ex.getMessage());
+            }
+        });
+    }
+
+    private DataObject getDataObject(Collection<? extends SVGDataObject> data) 
{
+        if (data.isEmpty()) {
+            return null;
+        } else {
+            return data.iterator().next();
+        }
+    }
+
+    /**
+     * Accessor for listener to context
+     */
+    private LookupListener getContextListener() {
+        if (contextListener == null) {
+            contextListener = new ContextListener();
+        }
+        return contextListener;
+    }
+
+    /**
+     * Listens to changes of context and triggers proper action
+     */
+    private class ContextListener implements LookupListener {
+
+        @Override
+        public void resultChanged(LookupEvent ev) {
+            currentDataObject = getDataObject(currentContext.allInstances());
+            setNewContent(currentDataObject);
+        }
+    }
+
+    private class SvgFileChangeAdapter extends FileChangeAdapter {
+
+        @Override
+        public void fileChanged(final FileEvent fe) {
+            if (fe.getTime() > lastSaveTime) {
+                lastSaveTime = System.currentTimeMillis();
+
+                // Refresh image viewer
+                SwingUtilities.invokeLater(() -> {
+                    try {
+                        currentDataObject = DataObject.find(fe.getFile());
+                        setNewContent(currentDataObject);
+                    } catch (DataObjectNotFoundException ex) {
+                        
Logger.getLogger(SvgNavigatorPanel.class.getName()).info(NbBundle.getMessage(SvgNavigatorPanel.class,
 "ERR_DataObject"));

Review Comment:
   can use outer class `LOG` constant



##########
ide/svg/src/org/netbeans/modules/svg/navigation/SvgNavigatorPanel.java:
##########


Review Comment:
   some classes use `SVG`, other use `Svg` prefix. I am ok with either but lets 
try to not mix styles within the same module at least.



##########
ide/svg/src/org/netbeans/modules/svg/SVGPanel.java:
##########
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.svg;
+
+import com.github.weisj.jsvg.SVGDocument;
+
+import java.awt.*;
+import javax.swing.*;
+
+/**
+ *
+ * @author Christian Lenz
+ */
+public class SVGPanel extends JPanel {
+
+    private SVGDocument svgDocument;
+    private double scale = 1.0D;
+    private BackgroundMode bgMode = BackgroundMode.DEFAULT;
+
+    public void setSvgDocument(SVGDocument doc) {
+        this.svgDocument = doc;
+
+        repaint();
+    }
+
+    public void setScale(double scale) {
+        this.scale = scale;
+
+        repaint();
+    }
+
+    public void setBackgroundMode(BackgroundMode mode) {
+        this.bgMode = mode;
+
+        repaint();
+    }
+
+    @Override
+    protected void paintComponent(Graphics g) {
+        super.paintComponent(g);
+
+        Rectangle visibleRect = getVisibleRectangle();
+
+        switch (bgMode) {
+            case BLACK:
+                g.setColor(Color.BLACK);
+                g.fillRect(visibleRect.x, visibleRect.y, visibleRect.width, 
visibleRect.height);
+                break;
+
+            case WHITE:
+                g.setColor(Color.WHITE);
+                g.fillRect(visibleRect.x, visibleRect.y, visibleRect.width, 
visibleRect.height);
+                break;
+
+            case TRANSPARENT:
+            case DARK_TRANSPARENT:
+                Utils.drawChestTilePattern(g, visibleRect, 20, bgMode == 
BackgroundMode.DARK_TRANSPARENT);
+                break;
+
+            default:
+                g.setColor(getBackground());
+                g.fillRect(visibleRect.x, visibleRect.y, visibleRect.width, 
visibleRect.height);
+                break;

Review Comment:
   the switch appears to be exhaustive and handles all `BackgroundMode` enum 
values. 
   
   `case DEFAULT:` would be safer here. Also, once you switch from `source` to 
`release` in the module properties NB should make the suggestion to convert 
this whole switch into arrow syntax which would get rid of the breaks too.



##########
ide/svg/src/org/netbeans/modules/svg/toolbar/BackgroundIcon.java:
##########
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.svg.toolbar;
+
+import org.netbeans.modules.svg.BackgroundMode;
+
+import java.awt.*;
+import javax.swing.*;
+import org.netbeans.modules.svg.Utils;
+
+/**
+ *
+ * @author Christian Lenz
+ */
+public class BackgroundIcon implements Icon {
+
+    private final BackgroundMode bgMode;
+    private final Color defaultColor;
+
+    public BackgroundIcon(BackgroundMode bgMode, Color defaultColor) {
+        this.bgMode = bgMode;
+        this.defaultColor = defaultColor;
+    }
+
+    @Override
+    public void paintIcon(Component c, Graphics g, int x, int y) {
+        Graphics2D g2d = (Graphics2D) g;
+
+        int width = getIconWidth();
+        int height = getIconHeight();
+
+        switch (bgMode) {

Review Comment:
   arrow switch candidate since exhaustive



##########
ide/xml/nbproject/project.xml:
##########
@@ -53,20 +53,20 @@
                     </run-dependency>
                 </dependency>
                 <dependency>
-                    
<code-name-base>org.netbeans.modules.editor.lib</code-name-base>
+                    
<code-name-base>org.netbeans.modules.editor.document</code-name-base>
                     <build-prerequisite/>
                     <compile-dependency/>
                     <run-dependency>
-                        <release-version>3</release-version>
-                        <specification-version>4.0</specification-version>
+                        <specification-version>1.0</specification-version>
                     </run-dependency>

Review Comment:
   nitpick: i believe the changes to the dependencies here are due to NB 
sorting the deps differently now, they can be likely reverted if all you wanted 
is to add the `friend-package` registration on the tail end of the file



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to