org.netbeans.modules.diff.builtin.SingleDiffPanel Maven / Gradle / Ivy
The newest version!
/*
* 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.diff.builtin;
import java.awt.Container;
import java.awt.EventQueue;
import org.netbeans.api.diff.DiffController;
import org.netbeans.api.diff.StreamSource;
import org.netbeans.api.diff.Difference;
import org.netbeans.api.options.OptionsDisplayer;
import org.netbeans.api.queries.FileEncodingQuery;
import org.openide.filesystems.FileRenameEvent;
import org.openide.util.Lookup;
import org.openide.util.lookup.Lookups;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.LifecycleManager;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.Reader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Writer;
import java.util.logging.Logger;
import java.util.logging.Level;
import org.netbeans.modules.diff.Utils;
import org.netbeans.modules.diff.options.DiffOptionsController;
import org.openide.awt.UndoRedo;
import org.openide.cookies.EditorCookie;
import org.openide.filesystems.FileChangeAdapter;
import org.openide.filesystems.FileChangeListener;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.util.WeakListeners;
import org.openide.windows.TopComponent;
/**
*
* @author Maros Sandor
*/
public class SingleDiffPanel extends javax.swing.JPanel implements PropertyChangeListener {
private FileObject base;
private FileObject modified;
private final FileObject type;
private DiffController controller;
private Action nextAction;
private Action prevAction;
private JComponent innerPanel;
private FileChangeListener baseFCL, modifiedFCL;
private PropertyChangeListener locationKeeper;
/** Creates new form SingleDiffPanel */
public SingleDiffPanel(FileObject left, FileObject right, FileObject type) throws IOException {
this.base = left;
this.modified = right;
this.type = type;
setListeners();
initComponents();
initMyComponents();
refreshComponents();
}
private void initMyComponents() throws IOException {
// centers components on the toolbar
actionsToolbar.add(Box.createHorizontalGlue(), 0);
actionsToolbar.add(Box.createHorizontalGlue());
nextAction = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
onNext();
}
};
bNext.setAction(nextAction);
// setAction sets the properties from action, so init tooltip & co. afterwards
bNext.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/netbeans/modules/diff/builtin/visualizer/editable/diff-next.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(bNext, org.openide.util.NbBundle.getMessage(SingleDiffPanel.class, "SingleDiffPanel.bNext.text")); // NOI18N
bNext.setToolTipText(org.openide.util.NbBundle.getMessage(SingleDiffPanel.class, "SingleDiffPanel.bNext.toolTipText")); // NOI18N
prevAction = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
onPrev();
}
};
bPrevious.setAction(prevAction);
// setAction sets the properties from action, so init tooltip & co. afterwards
bPrevious.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/netbeans/modules/diff/builtin/visualizer/editable/diff-prev.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(bPrevious, org.openide.util.NbBundle.getMessage(SingleDiffPanel.class, "SingleDiffPanel.bPrevious.text")); // NOI18N
bPrevious.setToolTipText(org.openide.util.NbBundle.getMessage(SingleDiffPanel.class, "SingleDiffPanel.bPrevious.toolTipText")); // NOI18N
getActionMap().put("jumpNext", nextAction); // NOI18N
getActionMap().put("jumpPrev", prevAction); // NOI18N
refreshController(false);
}
private void refreshController(boolean keepLocation) throws IOException {
int diffIndex = -1;
if (controller != null) {
diffIndex = controller.getDifferenceIndex();
controller.removePropertyChangeListener(this);
addPropertyChangeListener(this);
if (locationKeeper != null) {
controller.removePropertyChangeListener(locationKeeper);
locationKeeper = null;
}
}
// whatever the reason is that the fileobject isn't refreshed (!?),
// this is an explicit user refresh so
// refresh the FO explicitly as well
base.refresh();
modified.refresh();
StreamSource ss1 = new DiffStreamSource(base, type, false);
StreamSource ss2 = new DiffStreamSource(modified, type, true);
controller = DiffController.createEnhanced(ss1, ss2);
controller.addPropertyChangeListener(this);
if (keepLocation && diffIndex >= 0) {
final int fDiffIndex = diffIndex;
controller.addPropertyChangeListener(locationKeeper = new PropertyChangeListener() {
@Override
public void propertyChange (PropertyChangeEvent evt) {
if (DiffController.PROP_DIFFERENCES.equals(evt.getPropertyName())) {
if (controller.getDifferenceCount() > controller.getDifferenceIndex()) {
controller.setLocation(DiffController.DiffPane.Modified, DiffController.LocationType.DifferenceIndex, fDiffIndex);
}
controller.removePropertyChangeListener(this);
}
}
});
}
controllerPanel.removeAll();
innerPanel = controller.getJComponent();
controllerPanel.add(innerPanel);
setName(innerPanel.getName());
Container c = getParent();
if (c != null) {
c.setName(getName());
}
activateNodes();
revalidate();
repaint();
}
public void activateNodes () {
TopComponent tc = (TopComponent) getClientProperty(TopComponent.class);
if (tc != null) {
Node node;
try {
DataObject dobj = DataObject.find(modified);
node = dobj.getNodeDelegate();
} catch (DataObjectNotFoundException e) {
node = new AbstractNode(Children.LEAF, Lookups.singleton(modified));
}
tc.setActivatedNodes(new Node[] {node});
}
}
public UndoRedo getUndoRedo() {
UndoRedo undoRedo = null;
if (innerPanel != null) {
undoRedo = (UndoRedo) innerPanel.getClientProperty(UndoRedo.class);
}
if (undoRedo == null) {
undoRedo = UndoRedo.NONE;
}
return undoRedo;
}
public void requestActive () {
if (controllerPanel != null) {
controllerPanel.requestFocusInWindow();
}
}
public void closed() {
// Traverse children components of controller panel and release the editor panes
// from editor registry and annotation holder
releaseChildrenPanes(controllerPanel);
}
private static void releaseChildrenPanes(JComponent c) {
for (int i = c.getComponentCount() - 1; i >= 0; i--) {
java.awt.Component ac = c.getComponent(i);
if (ac instanceof JComponent) {
JComponent ch = (JComponent) ac;
if (Boolean.TRUE.equals(ch.getClientProperty("usedByCloneableEditor"))) {
ch.putClientProperty("usedByCloneableEditor", Boolean.FALSE);
} else {
releaseChildrenPanes(ch);
}
}
}
}
private void onPrev() {
int idx = controller.getDifferenceIndex();
if (idx > 0) {
controller.setLocation(DiffController.DiffPane.Modified, DiffController.LocationType.DifferenceIndex, idx - 1);
}
}
private void onNext() {
int idx = controller.getDifferenceIndex();
if (idx < controller.getDifferenceCount() - 1) {
controller.setLocation(DiffController.DiffPane.Modified, DiffController.LocationType.DifferenceIndex, idx + 1);
}
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
refreshComponents();
}
private void refreshComponents() {
nextAction.setEnabled(controller.getDifferenceIndex() < controller.getDifferenceCount() - 1);
prevAction.setEnabled(controller.getDifferenceIndex() > 0);
}
private void setListeners () {
FileObject baseParent = base.getParent();
FileObject modifiedParent = modified.getParent();
if (baseParent != null) {
baseParent.addFileChangeListener(WeakListeners.create(FileChangeListener.class, baseFCL = new DiffFileChangeListener(), baseParent));
}
if (baseParent != modifiedParent && modifiedParent != null) {
modifiedParent.addFileChangeListener(WeakListeners.create(FileChangeListener.class, modifiedFCL = new DiffFileChangeListener(), modifiedParent));
}
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// //GEN-BEGIN:initComponents
private void initComponents() {
actionsToolbar = new javax.swing.JToolBar();
bNext = new javax.swing.JButton();
bPrevious = new javax.swing.JButton();
jSeparator1 = new javax.swing.JToolBar.Separator();
bRefresh = new javax.swing.JButton();
bSwap = new javax.swing.JButton();
bExport = new javax.swing.JButton();
bOptions = new javax.swing.JButton();
controllerPanel = new javax.swing.JPanel();
actionsToolbar.setFloatable(false);
actionsToolbar.setRollover(true);
org.openide.awt.Mnemonics.setLocalizedText(bNext, org.openide.util.NbBundle.getMessage(SingleDiffPanel.class, "SingleDiffPanel.bNext.text")); // NOI18N
bNext.setFocusable(false);
bNext.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
bNext.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
actionsToolbar.add(bNext);
org.openide.awt.Mnemonics.setLocalizedText(bPrevious, org.openide.util.NbBundle.getMessage(SingleDiffPanel.class, "SingleDiffPanel.bPrevious.text")); // NOI18N
bPrevious.setFocusable(false);
bPrevious.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
bPrevious.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
actionsToolbar.add(bPrevious);
actionsToolbar.add(jSeparator1);
bRefresh.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/netbeans/modules/diff/builtin/visualizer/editable/diff-refresh.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(bRefresh, org.openide.util.NbBundle.getMessage(SingleDiffPanel.class, "SingleDiffPanel.bRefresh.text")); // NOI18N
bRefresh.setToolTipText(org.openide.util.NbBundle.getMessage(SingleDiffPanel.class, "SingleDiffPanel.bRefresh.toolTipText")); // NOI18N
bRefresh.setFocusable(false);
bRefresh.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
bRefresh.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
bRefresh.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bRefreshActionPerformed(evt);
}
});
actionsToolbar.add(bRefresh);
org.openide.awt.Mnemonics.setLocalizedText(bSwap, org.openide.util.NbBundle.getMessage(SingleDiffPanel.class, "SingleDiffPanel.bSwap.text")); // NOI18N
bSwap.setFocusable(false);
bSwap.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
bSwap.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
bSwap.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bSwapActionPerformed(evt);
}
});
actionsToolbar.add(bSwap);
org.openide.awt.Mnemonics.setLocalizedText(bExport, org.openide.util.NbBundle.getMessage(SingleDiffPanel.class, "SingleDiffPanel.bExport.text")); // NOI18N
bExport.setFocusable(false);
bExport.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
bExport.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
bExport.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bExportActionPerformed(evt);
}
});
actionsToolbar.add(bExport);
org.openide.awt.Mnemonics.setLocalizedText(bOptions, org.openide.util.NbBundle.getMessage(SingleDiffPanel.class, "SingleDiffPanel.bOptions.text")); // NOI18N
bOptions.setFocusable(false);
bOptions.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
bOptions.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
bOptions.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bOptionsActionPerformed(evt);
}
});
actionsToolbar.add(bOptions);
controllerPanel.setLayout(new java.awt.BorderLayout());
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(controllerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 531, Short.MAX_VALUE)
.addComponent(actionsToolbar, javax.swing.GroupLayout.DEFAULT_SIZE, 531, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(actionsToolbar, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(controllerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 371, Short.MAX_VALUE))
);
}// //GEN-END:initComponents
private void bRefreshActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bRefreshActionPerformed
LifecycleManager.getDefault().saveAll();
try {
refreshController(false);
} catch (IOException e) {
Logger.getLogger(SingleDiffPanel.class.getName()).log(Level.SEVERE, "", e); // elegant, nice and simple exception logging
}
}//GEN-LAST:event_bRefreshActionPerformed
private void bSwapActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bSwapActionPerformed
LifecycleManager.getDefault().saveAll();
FileObject temp = base;
base = modified;
modified = temp;
try {
refreshController(true);
} catch (IOException e) {
Logger.getLogger(SingleDiffPanel.class.getName()).log(Level.SEVERE, "", e); // elegant, nice and simple exception logging
}
}//GEN-LAST:event_bSwapActionPerformed
private void bExportActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bExportActionPerformed
StreamSource ss1 = new DiffStreamSource(base, type, false);
StreamSource ss2 = new DiffStreamSource(modified, type, true);
ExportPatch.exportPatch(new StreamSource[] { ss1 }, new StreamSource[] { ss2 });
}//GEN-LAST:event_bExportActionPerformed
private void bOptionsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bOptionsActionPerformed
OptionsDisplayer.getDefault().open("Advanced/" + DiffOptionsController.OPTIONS_SUBPATH);
}//GEN-LAST:event_bOptionsActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JToolBar actionsToolbar;
private javax.swing.JButton bExport;
private javax.swing.JButton bNext;
private javax.swing.JButton bOptions;
private javax.swing.JButton bPrevious;
private javax.swing.JButton bRefresh;
private javax.swing.JButton bSwap;
private javax.swing.JPanel controllerPanel;
private javax.swing.JToolBar.Separator jSeparator1;
// End of variables declaration//GEN-END:variables
private class DiffFileChangeListener extends FileChangeAdapter {
@Override
public void fileRenamed(FileRenameEvent fe) {
if (fe.getFile() == base || fe.getFile() == modified) {
refreshFiles();
}
}
private void refreshFiles() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
refreshController(true);
} catch (IOException ex) {
Logger.getLogger(SingleDiffPanel.class.getName()).log(Level.SEVERE, "", ex); //NOI18N
}
}
});
}
}
private static class DiffStreamSource extends StreamSource {
private final FileObject fileObject;
private final FileObject type;
private final boolean isRight;
public DiffStreamSource(FileObject fileObject, FileObject type, boolean isRight) {
this.fileObject = fileObject;
this.type = type;
this.isRight = isRight;
}
@Override
public boolean isEditable() {
return isRight && fileObject.canWrite();
}
@Override
public Lookup getLookup() {
return Lookups.fixed(fileObject);
}
@Override
public String getName() {
return fileObject.getName();
}
@Override
public String getTitle() {
return FileUtil.getFileDisplayName(fileObject);
}
@Override
public String getMIMEType() {
if (type != null) {
if (Utils.isFileContentBinary(type)) {
return null;
}
return type.getMIMEType();
} else {
if (Utils.isFileContentBinary(fileObject)) {
return null;
}
return fileObject.getMIMEType();
}
}
@Override
public Reader createReader() throws IOException {
if (type != null) {
return new InputStreamReader(fileObject.getInputStream(), FileEncodingQuery.getEncoding(type));
} else {
return new InputStreamReader(fileObject.getInputStream(), FileEncodingQuery.getEncoding(fileObject));
}
}
@Override
public Writer createWriter(Difference[] conflicts) throws IOException {
return null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy