From 3f0eefddf6b4c2474600d879f9429fe4c5b3c429 Mon Sep 17 00:00:00 2001 From: Chrizzly Date: Sat, 22 Jul 2023 23:38:58 +0200 Subject: [PATCH] Init SVGPreview commit --- ide/xml/nbproject/project.xml | 24 +- .../modules/xml/svg/Bundle.properties | 24 ++ .../modules/xml/svg/SVGDataObject.java | 358 ++++++++++++++++++ .../modules/xml/svg/SVGViewerElement.java | 165 ++++++++ 4 files changed, 563 insertions(+), 8 deletions(-) create mode 100644 ide/xml/src/org/netbeans/modules/xml/svg/Bundle.properties create mode 100644 ide/xml/src/org/netbeans/modules/xml/svg/SVGDataObject.java create mode 100644 ide/xml/src/org/netbeans/modules/xml/svg/SVGViewerElement.java diff --git a/ide/xml/nbproject/project.xml b/ide/xml/nbproject/project.xml index 3661a55839f1..9a3ee38777c8 100644 --- a/ide/xml/nbproject/project.xml +++ b/ide/xml/nbproject/project.xml @@ -53,12 +53,11 @@ - org.netbeans.modules.editor.lib + org.netbeans.libs.batik.read - 3 - 4.0 + 1.16 @@ -69,6 +68,15 @@ 1.0 + + org.netbeans.modules.editor.lib + + + + 3 + 4.0 + + org.netbeans.modules.editor.mimelookup @@ -239,7 +247,7 @@ - org.openide.util.ui + org.openide.util @@ -247,19 +255,19 @@ - org.openide.util + org.openide.util.lookup - 9.3 + 8.0 - org.openide.util.lookup + org.openide.util.ui - 8.0 + 9.3 diff --git a/ide/xml/src/org/netbeans/modules/xml/svg/Bundle.properties b/ide/xml/src/org/netbeans/modules/xml/svg/Bundle.properties new file mode 100644 index 000000000000..5866c54b8e4a --- /dev/null +++ b/ide/xml/src/org/netbeans/modules/xml/svg/Bundle.properties @@ -0,0 +1,24 @@ +# 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. + + + +## SVGDataObject.java +PROP_SVGDataNode_description=SVG Document +#-- + +CTL_SourceTabCaption=&Source diff --git a/ide/xml/src/org/netbeans/modules/xml/svg/SVGDataObject.java b/ide/xml/src/org/netbeans/modules/xml/svg/SVGDataObject.java new file mode 100644 index 000000000000..247fa1c5ad9d --- /dev/null +++ b/ide/xml/src/org/netbeans/modules/xml/svg/SVGDataObject.java @@ -0,0 +1,358 @@ +/* + * 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.xml.svg; + +import java.beans.*; +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; +import org.netbeans.core.spi.multiview.MultiViewElement; +import org.netbeans.core.spi.multiview.text.MultiViewEditorElement; +import org.openide.filesystems.*; +import org.openide.loaders.*; +import org.openide.util.*; +import org.openide.nodes.*; +import org.openide.cookies.*; +import org.openide.windows.CloneableOpenSupport; +import org.netbeans.modules.xml.sync.*; +import org.netbeans.modules.xml.cookies.*; +import org.netbeans.modules.xml.util.Util; +import org.openide.windows.TopComponent; + +/** Object that provides main functionality for xml document. + * Instance holds all synchronization related state information. + * This class is final only for performance reasons, + * can be unfinaled if desired. + * + * @author Libor Kramolis + */ +@DataObject.Registration( + mimeType = SVGDataObject.MIME_SVG, + iconBase = "org/netbeans/modules/xml/resources/xmlObject.gif", + displayName = "Smth", + position = 300 +) +public final class SVGDataObject extends XMLDataObject { + + /** + * Special MIME type so that other XML data objects do not inherit our editor + */ + public static final String MIME_SVG = "image/svg+xml"; + + /** Serial Version UID */ + private static final long serialVersionUID = 9153823984913876866L; + + /** Synchronization implementation delegate. */ + private Reference refSync; + + /** Cookie Manager */ +// private final DataObjectCookieManager cookieManager; + + /** Create new XMLDataObject + * + * @param fo the primary file object + * @param loader loader of this data object + */ + public SVGDataObject (final FileObject fo, MultiFileLoader loader) throws DataObjectExistsException { + super (fo, loader, false); + registerEditor(MIME_SVG, true); + +// CookieSet set = getCookieSet(); +// set.add (cookieManager = new DataObjectCookieManager (this, set)); +// editorSupportFactory = +// TextEditorSupport.findEditorSupportFactory (this, null); +// +// editorSupportFactory.registerCookies (set); +// CookieSet.Factory viewCookieFactory = new ViewCookieFactory(); +// set.add (ViewCookie.class, viewCookieFactory); +// InputSource is = DataObjectAdapters.inputSource (this); +// //enable "Save As" +// set.assign( SaveAsCapable.class, new SaveAsCapable() { +// public void saveAs(FileObject folder, String fileName) throws IOException { +// editorSupportFactory.createEditor().saveAs( folder, fileName ); +// } +// }); +// +// // add check and validate cookies +// set.add (new CheckXMLSupport (is)); +// set.add (new ValidateXMLSupport (is)); +// // add TransformableCookie +// Source source = DataObjectAdapters.source (this); +// set.add (new TransformableSupport (source)); +// new CookieManager (this, set, XMLCookieFactoryCreator.class); +// this.addPropertyChangeListener (this); //??? - strange be aware of firing cycles + } + + @MultiViewElement.Registration( + displayName="org.netbeans.modules.xml.Bundle#CTL_SourceTabCaption", + iconBase="org/netbeans/modules/xml/resources/xmlObject.gif", + persistenceType=TopComponent.PERSISTENCE_ONLY_OPENED, + preferredID="svg.text", + mimeType=MIME_SVG, + position=1 + ) + public static MultiViewEditorElement createMultiViewEditorElement(Lookup context) { + return new MultiViewEditorElement(context); + } + + @Override protected int associateLookup() { + return 1; + } + + + /** + */ + @Override + protected Node createNodeDelegate () { + if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("--> XMLDataObject.createNodeDelegate: this = " + this); + + DataNodeCreator dataNodeCreator = Lookup.getDefault().lookup (DataNodeCreator.class); + Node dataNode = null; + + if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("-*- XMLD O .createNodeDelegate: dataNodeCreator = " + dataNodeCreator); + + if ( dataNodeCreator != null ) { + dataNode = dataNodeCreator.createDataNode (this); + } else { + Lookup env = Environment.find(this); + dataNode = env == null ? null : env.lookup(Node.class); + if (dataNode == null) { + dataNode = new SVGDataNode (this); + } + } + + if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("<-- XMLDataObject.createNodeDelegate: dataNode = " + dataNode); + + return dataNode; + } + + /** + * Get 'semantics' node delegate from superclass. + */ +// Node createDefaultNodeDelegate () { +// return super.createNodeDelegate(); //it is a FilterNode +// } + + /** Delegate to super with possible debug messages. */ + @Override + public void setModified (boolean state) { + if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("XMLDataObject:setModified: state = " + state); // NOI18N + + super.setModified (state); + } + + + /** Delegate to super with possible debug messages. */ + @Override + public org.openide.nodes.Node.Cookie getCookie(Class klass) { + Node.Cookie cake = null; + + if (SaveCookie.class.equals (klass) ) { + if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("XMLDataObject::getCookie");//, new RuntimeException ("Save cookie check")); // NOI18N + } + + // take lock to prevent deadlock on cookie set that can be called + // from other thread during cookie removal + synchronized (this) { + cake = super.getCookie (klass); + + if ( ( cake == null ) && + ( CloneableOpenSupport.class == klass ) ) { //!!! HACK -- backward compatibility + cake = super.getCookie (OpenCookie.class); + } + } + + if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("XMLDataOObject::getCookie: class = " + klass + " => " + cake); // NOI18N + + return cake; + } + + +// public DataObjectCookieManager getCookieManager() { +// return cookieManager; +// } + + /** TREE -> TEXT + * Updates document by content of parsed tree based on the + * last document version. + * Note: the tree is always maximum valid part of document. + * It takes parsed tree as primary data model. IT MUST CHANGE + * tree must contain an error element. + */ + public synchronized void updateDocument () { + + //!!! to be implemented without dependency on tree + Thread.dumpStack(); +// sync.representationChanged(TreeDocument.class); //!!! + + } + + private synchronized Synchronizator getSyncIfAvailable() { + if (refSync == null) { + return null; + } + return refSync.get(); + } + + public synchronized Synchronizator getSyncInterface() { + Synchronizator sync = null; + if (refSync != null) { + sync = refSync.get(); + } + if (sync != null) { + return sync; + } +// sync = new XMLSyncSupport(this); + refSync = new WeakReference<>(sync); + return sync; + } + + + + + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * LISTENERS section + * handlers of various listeners attached by this DataObject + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + + /** + * File was externaly modified, detected by OpenIDE DataObject. + */ + public void propertyChange (PropertyChangeEvent e) { + + if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("event " + e.getPropertyName()); // NOI18N + + if (org.openide.loaders.XMLDataObject.PROP_DOCUMENT.equals (e.getPropertyName())) { + + // filter out uninteresting events + if (e.getOldValue() == e.getNewValue()) return; //e.g. null == null + + Synchronizator s = getSyncIfAvailable(); + if (s != null) { + s.representationChanged(FileObject.class); + } + } + } + + + @Override + public HelpCtx getHelpCtx() { + //return new HelpCtx(XMLDataObject.class); + return HelpCtx.DEFAULT_HELP; + } + + // + // class SVGDataNode + // + + /** + * + */ + public static class SVGDataNode extends DataNode { + + /** Create new SVGDataNode. */ + public SVGDataNode (SVGDataObject obj) { + super (obj, Children.LEAF); + setIconBaseWithExtension ("org/netbeans/modules/xml/resources/xmlObject.gif"); // NOI18N +// setShortDescription (Util.THIS.getString (XMLDataObject.class, "PROP_SVGDataNode_description")); + setShortDescription("It is an SVG"); + } + + } // end of class SVGDataNode + + + // + // class ViewCookieFactory + // + + /** + * + */ +// private class ViewCookieFactory implements CookieSet.Factory { +// +// /** Creates new Cookie */ +// public Node.Cookie createCookie (Class klass) { +// if (klass == ViewCookie.class) { +// return new ViewSupport (SVGDataObject.this.getPrimaryEntry()); +// } else { +// return null; +// } +// } +// +// } // end of class ViewCookieFactory + + + // + // class ViewSupport + // + + /** + * + */ +// private static final class ViewSupport implements ViewCookie { +// +// /** entry */ +// private MultiDataObject.Entry primary; +// +// /** Constructs new ViewSupport */ +// public ViewSupport (MultiDataObject.Entry primary) { +// this.primary = primary; +// } +// +// /** +// */ +// public void view () { +// HtmlBrowser.URLDisplayer.getDefault().showURL(primary.getFile().toURL()); +// } +// +// } // end of class ViewSupport + + + + // + // interface DataNodeCreator + // + + /** + * + */ + public static interface DataNodeCreator { + + /** + */ + public DataNode createDataNode (XMLDataObject xmlDO); + + } // end of interface DataNodeCreator + + + + // + // interface XMLCookieFactoryCreator + // + + /** + * + */ + public static interface XMLCookieFactoryCreator extends CookieFactoryCreator { + + } // end: interface XMLCookieFactoryCreator + +} diff --git a/ide/xml/src/org/netbeans/modules/xml/svg/SVGViewerElement.java b/ide/xml/src/org/netbeans/modules/xml/svg/SVGViewerElement.java new file mode 100644 index 000000000000..5465711cab7e --- /dev/null +++ b/ide/xml/src/org/netbeans/modules/xml/svg/SVGViewerElement.java @@ -0,0 +1,165 @@ +/* + * 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.xml.svg; + +import java.io.IOException; +import java.util.logging.Logger; +import javax.swing.Action; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JToolBar; +import org.apache.batik.anim.dom.SAXSVGDocumentFactory; +import org.apache.batik.util.XMLResourceDescriptor; +import org.netbeans.core.spi.multiview.CloseOperationState; +import org.netbeans.core.spi.multiview.MultiViewElement; +import org.netbeans.core.spi.multiview.MultiViewElementCallback; +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.Exceptions; +import org.openide.util.Lookup; +import org.openide.util.NbBundle.Messages; +import org.openide.windows.TopComponent; +import org.w3c.dom.svg.SVGDocument; + +/** + * + * @author Chris + */ +@MultiViewElement.Registration( + displayName = "#LBL_SVGViewer", + iconBase = "org/netbeans/modules/xml/resources/xmlObject.gif", + 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; + private transient JPanel viewer; + + 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 JToolBar(); + } + 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 JSVGCanvas svgCanvas = new JSVGCanvas(); + + @Messages("TXT_MarkdownViewerElement_Error=Something happened during markdown parsing.") + private void updateView() { + FileObject fo = dataObject.getPrimaryFile(); + if ((fo != null) && (viewer != null)) { + String parser = XMLResourceDescriptor.getXMLParserClassName(); + SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser); + String uri = "https://upload.wikimedia.org/wikipedia/commons/b/bd/Test.svg"; +// String uri = fo.getPath(); + + try { + SVGDocument doc = (SVGDocument) f.createDocument(uri); + viewer.add(doc.getRootElement().); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + } +}